-- | This module is planned to disappear in favor of a stateful polyline -- drawing mode. It's still here for various renderers. module Gelatin.Core.Polyline where import Data.List (unzip5) import Data.Vector.Unboxed (Unbox, Vector) import qualified Data.Vector.Unboxed as V import Linear hiding (trace) type PolylineData f = ( Vector (V2 Float) , Vector (f Float) , Vector (V2 Float) , Vector (V2 Float) , Vector (V2 Float) , Float ) expandPolyline :: Unbox (f Float) => Vector (V2 Float) -> Vector (f Float) -> Float -> Float -> Maybe (PolylineData f) expandPolyline verts colors thickness feather | Just (v1,v2) <- (,) <$> (verts V.!? 0) <*> (verts V.!? 1) , Just c1 <- colors V.!? 0 , Just (v3,v3n) <- (,) <$> (verts V.!? (V.length verts -1)) <*> (verts V.!? (V.length verts -2)) , Just c3 <- colors V.!? (V.length verts -1) = let -- clamp the lower bound of our thickness to 1 absthick = max thickness 1 d = fromIntegral (ceiling $ absthick + 2.5 * feather :: Integer) lens = 0 `V.cons` V.zipWith distance verts (V.drop 1 verts) totalLen = V.foldl' (+) 0 lens totalEnd = totalLen + d seqfunc (total,ts) len = (total + len,ts V.++ V.singleton (total + len)) seqLens = snd $ V.foldl' seqfunc (0,mempty) lens isClosed = distance v1 v3 <= 0.00001 -- if the polyline is closed return a miter with the last point startCap = ( V.fromList [cap,cap] , V.fromList [c1,c1] , uvs , V.fromList [v2,v2] , V.fromList [prev,prev] ) where (uvs,cap,prev) = if isClosed -- no cap then (V.fromList [V2 0 d, V2 0 (-d)],v1,v3n) -- cap else let c = d *^ signorm (v2 - v1) in ( V.fromList [V2 (-d) d, V2 (-d) (-d)] , v1 - c , v1 - 2*c) endCap = ( V.fromList [cap,cap] , V.fromList [c3,c3] , uvs , V.fromList [next,next] , V.fromList [v3n,v3n] ) where (uvs,cap,next) = if isClosed -- no cap then ( V.fromList [ V2 totalLen d , V2 totalLen (-d) ] , v3 , v2 ) -- cap else let c = d *^ signorm (v3 - v3n) in (V.fromList [ V2 totalEnd d , V2 totalEnd (-d) ] , v3 + c , v3 + 2*c ) vcs = V.toList $ V.zip3 verts colors seqLens zs = zipWith3 strp vcs (drop 1 vcs) (drop 2 vcs) -- Expand the line into a triangle strip strp :: Unbox (f Float) => (V2 Float, f Float, Float) -> (V2 Float, f Float, Float) -> (V2 Float, f Float, Float) -> (Vector (V2 Float) ,Vector (f Float) ,Vector (V2 Float) ,Vector (V2 Float) ,Vector (V2 Float) ) strp (a,_,_) (b,bc,l) (c,_,_) = ( V.fromList [b,b] , V.fromList [bc,bc] , V.fromList [V2 l d,V2 l (-d)] , V.fromList [c,c] , V.fromList [a,a] ) (vs,cs,us,ns,ps) = unzip5 $ startCap : zs ++ [endCap] in Just (V.concat vs, V.concat cs, V.concat us, V.concat ns, V.concat ps, totalLen) | otherwise = Nothing