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
谁能告诉我使用 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