packages feed

brillo-examples-1.13.3: picture/Visibility/World.hs

module World (
  Segment,
  World (..),
  initialWorld,
  normaliseWorld,
)
where

import Brillo (Point)
import Data.Vector.Unboxed qualified as V
import Geometry.Randomish (randomishPoints)
import Geometry.Segment (Segment, splitSegmentsOnY, translateSegment)


-- We keep this unpacked so we can use unboxed vector.
-- index, x1, y1, x2, y2
newtype World = World {worldSegments :: V.Vector Segment}


-- | Generate the initial world.
initialWorld :: IO World
initialWorld = do
  let
    n = 100
    minZ = -300
    maxZ = 300

    minDelta = -100
    maxDelta = 100

    centers = randomishPoints 1234 n minZ maxZ
    deltas = randomishPoints 4321 n minDelta maxDelta

    makePoint n' (cX, cY) (dX, dY) =
      (n', (cX, cY), (cX + dX, cY + dY))

    segs = V.zipWith3 makePoint (V.enumFromTo 0 (n - 1)) centers deltas

  return $ World segs


{-| Normalise the world so that the given point is at the origin,
  and split segements that cross the y=0 line.
-}
normaliseWorld :: Point -> World -> World
normaliseWorld (px, py) world = do
  let
    segments_trans =
      V.map (translateSegment (-px) (-py)) $
        worldSegments world
    segments_split =
      splitSegmentsOnY 0 segments_trans

  world{worldSegments = segments_split}