packages feed

pure-cdt-0.2.0.0: app/Examples/Circle.hs

module Examples.Circle (
  drawCircle,
  drawTorus,
) where

import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NE
import Drawer (drawTriangulation)
import Examples.Common (canvas, orFail)
import Triangulation (Point (..), Polygon (..), constrainedTriangulate, vertices)
import Triangulation.Generator (generatePointsWithDistance)

drawCircle :: FilePath -> IO ()
drawCircle path = do
  triangles <- orFail $ constrainedTriangulate circle [] points
  drawTriangulation path triangles [] [circle]
  where
    circle = circleOf (Point 1000 1000) 800 150
    points = generatePointsWithDistance 2 8000 20 canvas (vertices circle)

drawTorus :: FilePath -> IO ()
drawTorus path = do
  triangles <- orFail $ constrainedTriangulate outer [inner] points
  drawTriangulation path triangles [] [outer, inner]
  where
    outer = circleOf (Point 1000 1000) 800 100
    inner = circleOf (Point 1000 1000) 400 50
    points = generatePointsWithDistance 1 4000 20 canvas (vertices outer ++ vertices inner)

-- | A regular @n@-gon inscribed in the circle, wound clockwise.
circleOf :: Point -> Double -> Int -> Polygon
circleOf (Point x0 y0) radius n =
  let angleStep = 2 * pi / fromIntegral n
      angles = NE.map ((angleStep *) . fromIntegral) (0 :| [1 .. n - 1])
   in Polygon
        $ NE.reverse
        $ NE.map (\angle -> Point (x0 + radius * cos angle) (y0 + radius * sin angle)) angles