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