haskell CodeWorld 中的圆弧段

circular segment in haskell CodeWorld

谁能告诉我使用 haskell codeworld API 绘制圆弧的最佳方法?

我有一个方法,只有当通过组合三个扇区在半径以下截断圆弧段时才有效。但是,这在圆在半径以上被截断的情况下不起作用。

编辑:我当前的尝试已修改为与上下文无关

-- x = coords of the centre of the circle
-- y = A point on the circumference
-- z = the y-axis to cut off the circle at. 
Segment :: Point -> Point -> Double -> Picture
Segment x y z = case capCutOffPoints x (pointDistance x y) z of
      Nothing 
        | z <= snd x - pointDistance x y -> translated (fst x) (snd x) (solidCircle (pointDistance x y))
        | otherwise -> blank
      Just points
        | snd (fst points) < snd x -> solidPolygon [(fst x, snd x + 0.5*(pointDistance x y)), fst points, snd points] & translated (fst x) (snd x) (sector  (fst (capArcAngles x points) +2*pi) (snd (capArcAngles x points)) (pointDistance x y))
        | otherwise -> translated (fst x) (snd x) (sector  (fst (capArcAngles x points)) (snd (capArcAngles x points)) (pointDistance x y))

-- | Returns the points at which the circle of the cap is cut off at.
capCutOffPoints :: Point -> Double -> Double -> Maybe (Point, Point)
capCutOffPoints centre radius y = points
  where
    sqrtX = sqrt (radius^2 - (y - (snd centre))^2)
    points
      | isNaN sqrtX = Nothing
      | otherwise = Just ((sqrtX + fst centre, y), (-sqrtX + fst centre, y))

-- | Returns the angle from the centre of the cap circle to the cut off points
-- Modified to always return an angle between 0 and 2pi
capArcAngles :: Point -> (Point, Point) -> (Double, Double)
capArcAngles centre points = (a2, a1)
  where
    a1 = atan2 (snd (fst points) - snd centre) (fst (fst points) - fst centre)
    a2 = atan2 (snd (snd points) - snd centre) (fst (snd points) - fst centre)

pointDistance :: Point -> Point -> Double
pointDistance p1 p2 = sqrt ((abs ((fst p1) - (fst p2)))^2 + (abs ((snd p1) - (snd p2)))^2)

我认为最简单的方法是以您想要的角度剪裁圆圈。所以这个过程。

  • 绘制实心圆坐标(0,0)
  • 将其移动到所需的坐标以生成线段
  • 使用矩形剪辑它
  • 将其移回原来的位置。

下面的代码在给定的角度上生成实心圆段,并在 (0,0)

处停止
import CodeWorld


--                 |- Angle  |- Radious
circularSegment :: Double -> Double -> Picture
circularSegment ang r = translated 0 (- translation_dir * translation_amount) -- Translate back
                      $ clipped (2*r) (2*r) -- clip it using rectangle 
                      $ translated 0 (translation_dir * translation_amount) -- translate it
                      $ solidCircle r -- plot a solid circle
  where s = r * sin ang
        translation_amount = r + abs s -- you want to translate your circle a the radious + the sin of the angle
        translation_dir = - signum s -- you want to translate the circle in the oposite direction as the sinus

举个例子。下面的代码生成给定的图片

topCirc    = circularSegment (pi / 4) 3 
bottomCirc = coloured red $ circularSegment ( - pi / 4) 3 

main = drawingOf $ topCirc
                 <> bottomCirc