-- | 'Path' query functions and related operations. module Graphics.PS.Query where import Data.CG.Minus.Types {- hcg-minus -} import qualified Data.CG.Minus as CG {- hcg-minus -} import qualified Data.CG.Minus.Bezier as CG {- hcg-minus -} import Graphics.PS.Paper import Graphics.PS.Path -- | Locate the starting point of the path, which must begin with a 'MoveTo' node. startPt :: Path -> Maybe (Pt Double) startPt path = case path of MoveTo p -> Just p Join p _ -> startPt p _ -> Nothing -- | Variant that allows the initial node to be a 'LineTo' or 'CurveTo' node. startPt' :: Path -> Maybe (Pt Double) startPt' path = case path of MoveTo p -> Just p LineTo p -> Just p CurveTo p _ _ -> Just p Join p _ -> startPt' p _ -> Nothing -- | Ensure path begins with a 'MoveTo' node. mkValid :: Path -> Path mkValid path = case startPt' path of Just p -> MoveTo p +++ path Nothing -> path -- | Locate the end point of the path. endPt :: Path -> Maybe (Pt Double) endPt path = case path of MoveTo p -> Just p LineTo p -> Just p CurveTo _ _ p -> Just p Join _ p -> endPt p _ -> Nothing -- | Append a 'LineTo' the start point of 'Path'. close :: Path -> Path close path = case startPt path of Just p -> path +++ ClosePath p Nothing -> path -- | Approximate curves as /n/ straight line segments. That is -- replace 'CurveTo' nodes with /n/ 'LineTo' nodes calculated using -- 'bezier4'. approx :: Double -> Path -> Path approx n path = case path of Join a (CurveTo p2 p3 p4) -> let is = [0, (1.0/n) .. 1.0] l = case endPt a of Just p1 -> map (CG.bezier4 p1 p2 p3 p4) is Nothing -> [] in a +++ line l _ -> path -- | Rectangle, given as lower left and upper right points. data Rect a = Rect {rect_ll :: Pt a ,rect_ur :: Pt a} deriving (Eq,Show) -- | Sum (join) of two 'Rect'. rect_sum :: Ord a => Rect a -> Rect a -> Rect a rect_sum (Rect a b) (Rect c d) = Rect (CG.pt_min a c) (CG.pt_max b d) -- | Rectangle bounding a (simple) 'Path'. path_rect :: Path -> Rect Double path_rect path = case path of MoveTo p -> Rect p p LineTo p -> Rect p p CurveTo c0 c1 p0 -> Rect (foldl1 CG.pt_min [c0,c1,p0]) (foldl1 CG.pt_max [c0,c1,p0]) Join p q -> path_rect p `rect_sum` path_rect q _ -> error "path_rect: illegal query" -- | Translate 'Rect' to 'BBox'. rect_to_bbox :: RealFrac a => Rect a -> BBox rect_to_bbox (Rect (Pt x0 y0) (Pt x1 y1)) = BBox (floor x0) (floor y0) (ceiling x1) (ceiling y1) path_to_bbox :: Path -> BBox path_to_bbox = rect_to_bbox . path_rect {-- import Graphics.PS.Transform join :: Path -> Path -> Path join a b = a +++ translate x y b where (Pt x y) = endPt a link :: Path -> Path -> Path link a b = a +++ LineTo (startPt b) +++ b relMoveTo :: Path -> Pt -> Path relMoveTo path (Pt dx dy) = path +++ MoveTo (Pt (x + dx) (y + dy)) where (Pt x y) = endPt path relLineTo :: Path -> Pt -> Path relLineTo path (Pt dx dy) = path +++ LineTo (Pt (x + dx) (y + dy)) where (Pt x y) = endPt path hasText :: Path -> Bool hasText (Join p1 p2) = hasText p1 || hasText p2 hasText (Text _ _) = True hasText _ = False --}