53 lines
2.0 KiB
Haskell
53 lines
2.0 KiB
Haskell
module Picture.Arc
|
|
( arcFull
|
|
) where
|
|
|
|
import Color
|
|
import Geometry
|
|
import Picture.Data
|
|
|
|
-- this should work regardless of which angle is larger, though swapping the
|
|
-- angles will affect the winding of the drawn triangles
|
|
arcFull :: Float -> Float -> Color -> Float -> Float -> Color -> Float -> Color -> Picture
|
|
{-# INLINE arcFull #-}
|
|
arcFull startA swidth scol endA ewidth ecol r centercol
|
|
| abs (difference startA endA) > pi / 2 =
|
|
arcFull startA swidth scol midA mw mc r centercol
|
|
<> arcFull midA mw mc endA ewidth ecol r centercol
|
|
| otherwise = arcPart startA swidth scol endA ewidth ecol r centercol
|
|
where
|
|
midA = 0.5 * (startA + endA)
|
|
mw = 0.5 * (swidth + ewidth)
|
|
mc = mixColors 0.5 0.5 scol ecol
|
|
|
|
-- should work if the angles are pi/2 or less apart.
|
|
arcPart :: Float -> Float -> Color -> Float -> Float -> Color -> Float -> Color -> Picture
|
|
arcPart startA sw sc endA ew ec r centercol =
|
|
map
|
|
f
|
|
[ (V3 0 0 0, centercol, V3 0 0 mwdth)
|
|
, (V3 xa ya 0, sc, V3 ad op wdth)
|
|
, (V3 xb yb 0, mc, V3 1 1 mwdth)
|
|
, (V3 0 0 0, centercol, V3 0 0 mwdth)
|
|
, (V3 xb yb 0, mc, V3 1 1 mwdth)
|
|
, (V3 xc yc 0, ec, V3 ad op ewdth)
|
|
]
|
|
where
|
|
mc = mixColors 0.5 0.5 sc ec
|
|
ang = endA - startA
|
|
-- imagine that the arc is centered on the diagonal of the first quadrant
|
|
-- then the x-y values for the start and end of the arc are the following
|
|
op = sin ((pi / 2 - ang) / 2)
|
|
ad = cos ((pi / 2 - ang) / 2)
|
|
-- for most of the drawn triangles, the "width" value is interpolated towards the center
|
|
wdth = (wdth' + (wdth' - 1) * mwdth) / wdth'
|
|
wdth' = 1 - sw / r
|
|
-- along the middle line the "width" value is the following constant
|
|
mwdth = 1 - (0.5 * (sw + ew)) / r
|
|
ewdth' = 1 - ew / r
|
|
ewdth = (ewdth' + (ewdth' - 1) * mwdth) / ewdth'
|
|
(V2 xa ya) = rotateV startA (V2 r 0)
|
|
(V2 xb yb) = rotateV (0.5 * (startA + endA)) (V2 (r * sqrt 2) 0)
|
|
(V2 xc yc) = rotateV endA (V2 r 0)
|
|
f (pos, col, V3 a b c) = Verx pos col [a, b, c] minBound ArcShad
|