wumpus-drawing 0.2.0 → 0.3.0
raw patch · 77 files changed
+7170/−4812 lines, 77 filesdep ~wumpus-basicdep ~wumpus-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: wumpus-basic, wumpus-core
API changes (from Hackage documentation)
- Wumpus.Drawing.Arrows.Connectors: leftArrow :: (Real u, Floating u) => Arrowhead u -> ConnectorPath u -> ArrowConnector u
- Wumpus.Drawing.Arrows.Connectors: leftRightArrow :: (Real u, Floating u) => Arrowhead u -> Arrowhead u -> ConnectorPath u -> ArrowConnector u
- Wumpus.Drawing.Arrows.Connectors: rightArrow :: (Real u, Floating u) => Arrowhead u -> ConnectorPath u -> ArrowConnector u
- Wumpus.Drawing.Arrows.Connectors: type ArrowConnector u = ConnectorImage u (Path u)
- Wumpus.Drawing.Arrows.Connectors: uniformArrow :: (Real u, Floating u) => Arrowhead u -> ConnectorPath u -> ArrowConnector u
- Wumpus.Drawing.Arrows.Tips: Arrowhead :: DrawingInfo u -> LocThetaGraphic u -> Arrowhead u
- Wumpus.Drawing.Arrows.Tips: arrowhead_draw :: Arrowhead u -> LocThetaGraphic u
- Wumpus.Drawing.Arrows.Tips: arrowhead_retract_dist :: Arrowhead u -> DrawingInfo u
- Wumpus.Drawing.Arrows.Tips: barb45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: barb60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: barb90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: bracket :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: curveTip :: (Real u, Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: data Arrowhead u
- Wumpus.Drawing.Arrows.Tips: diamondTip :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: diskTip :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: odiamondTip :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: odiskTip :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: orevtri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: orevtri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: orevtri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: osquareTip :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: otri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: otri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: otri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: perp :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revbarb45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revbarb60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revbarb90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revcurveTip :: (Real u, Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revtri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revtri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: revtri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: squareTip :: (Floating u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: tri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: tri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Arrows.Tips: tri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u
- Wumpus.Drawing.Chains.Base: liftChainF :: (Point2 u -> PointChain u) -> LocChain u
- Wumpus.Drawing.Chains.Base: type ConnectorChain u = ConnectorCF u (PointChain u)
- Wumpus.Drawing.Chains.Base: type LocChain u = LocDrawingInfo u (PointChain u)
- Wumpus.Drawing.Chains.Base: type PointChain u = [Point2 u]
- Wumpus.Drawing.Chains.Base: unchain :: (Num u, OPlus a) => Int -> LocCF u (ImageAns u a) -> LocCF u (ImageAns u a) -> LocChain u -> LocCF u (ImageAns u a)
- Wumpus.Drawing.Chains.Base: unchainU :: (Num u, OPlus a) => LocCF u (ImageAns u a) -> LocCF u (ImageAns u a) -> LocChain u -> LocCF u (ImageAns u a)
- Wumpus.Drawing.Chains.Base: unchainZip :: (Num u, OPlus a) => LocCF u (ImageAns u a) -> [LocCF u (ImageAns u a)] -> LocChain u -> LocCF u (ImageAns u a)
- Wumpus.Drawing.Chains.Base: unchainZipWith :: (Num u, OPlus a) => LocCF u (ImageAns u a) -> (s -> LocCF u (ImageAns u a)) -> [s] -> LocChain u -> LocCF u (ImageAns u a)
- Wumpus.Drawing.Chains.Base: unconnectorChain :: (Num u, OPlus a) => ConnectorCF u (ImageAns u a) -> LocCF u (ImageAns u a) -> ConnectorChain u -> ConnectorCF u (ImageAns u a)
- Wumpus.Drawing.Chains.Derived: horizontalPoints :: Num u => u -> LocChain u
- Wumpus.Drawing.Chains.Derived: horizontalSteps :: Num u => [u] -> LocChain u
- Wumpus.Drawing.Chains.Derived: innerHorizontals :: RealFrac u => u -> ConnectorChain u
- Wumpus.Drawing.Chains.Derived: innerVerticals :: RealFrac u => u -> ConnectorChain u
- Wumpus.Drawing.Chains.Derived: tableDown :: Num u => Int -> (u, u) -> LocChain u
- Wumpus.Drawing.Chains.Derived: tableRight :: Num u => Int -> (u, u) -> LocChain u
- Wumpus.Drawing.Chains.Derived: verticalPoints :: Num u => u -> LocChain u
- Wumpus.Drawing.Chains.Derived: verticalSteps :: Num u => [u] -> LocChain u
- Wumpus.Drawing.Grids: grid :: Fractional u => (Int, Int) -> u -> LocGraphic u
- Wumpus.Drawing.Grids: interiorGrid :: RealFrac u => u -> ConnectorGraphic u
- Wumpus.Drawing.Paths.Base: (:<<) :: PathSegment u -> Path u -> PathViewL u
- Wumpus.Drawing.Paths.Base: (:>>) :: Path u -> PathSegment u -> PathViewR u
- Wumpus.Drawing.Paths.Base: Curve1 :: (Point2 u) -> (Point2 u) -> (Point2 u) -> (Point2 u) -> PathSegment u
- Wumpus.Drawing.Paths.Base: Line1 :: (Point2 u) -> (Point2 u) -> PathSegment u
- Wumpus.Drawing.Paths.Base: PathOneL :: (PathSegment u) -> PathViewL u
- Wumpus.Drawing.Paths.Base: PathOneR :: (PathSegment u) -> PathViewR u
- Wumpus.Drawing.Paths.Base: append :: Floating u => Path u -> Path u -> Path u
- Wumpus.Drawing.Paths.Base: atend :: (Real u, Floating u) => Path u -> (Point2 u, Radian)
- Wumpus.Drawing.Paths.Base: atend_ :: Path u -> Point2 u
- Wumpus.Drawing.Paths.Base: atstart :: (Real u, Floating u) => Path u -> (Point2 u, Radian)
- Wumpus.Drawing.Paths.Base: atstart_ :: Path u -> Point2 u
- Wumpus.Drawing.Paths.Base: curve :: (Floating u, Ord u, FromPtSize u) => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Path u
- Wumpus.Drawing.Paths.Base: curveByAngles :: (Floating u, Ord u, FromPtSize u) => Point2 u -> Radian -> Radian -> Point2 u -> Path u
- Wumpus.Drawing.Paths.Base: data Path u
- Wumpus.Drawing.Paths.Base: data PathSegment u
- Wumpus.Drawing.Paths.Base: data PathViewL u
- Wumpus.Drawing.Paths.Base: data PathViewR u
- Wumpus.Drawing.Paths.Base: directionL :: (Real u, Floating u) => Path u -> Radian
- Wumpus.Drawing.Paths.Base: directionR :: (Real u, Floating u) => Path u -> Radian
- Wumpus.Drawing.Paths.Base: instance Eq u => Eq (Path u)
- Wumpus.Drawing.Paths.Base: instance Eq u => Eq (PathSeg u)
- Wumpus.Drawing.Paths.Base: instance Eq u => Eq (PathSegment u)
- Wumpus.Drawing.Paths.Base: instance Eq u => Eq (PathViewL u)
- Wumpus.Drawing.Paths.Base: instance Eq u => Eq (PathViewR u)
- Wumpus.Drawing.Paths.Base: instance Show u => Show (Path u)
- Wumpus.Drawing.Paths.Base: instance Show u => Show (PathSeg u)
- Wumpus.Drawing.Paths.Base: instance Show u => Show (PathSegment u)
- Wumpus.Drawing.Paths.Base: instance Show u => Show (PathViewL u)
- Wumpus.Drawing.Paths.Base: instance Show u => Show (PathViewR u)
- Wumpus.Drawing.Paths.Base: length :: Num u => Path u -> u
- Wumpus.Drawing.Paths.Base: line :: Floating u => Point2 u -> Point2 u -> Path u
- Wumpus.Drawing.Paths.Base: midway :: (Real u, Floating u) => Path u -> (Point2 u, Radian)
- Wumpus.Drawing.Paths.Base: midway_ :: (Real u, Floating u) => Path u -> Point2 u
- Wumpus.Drawing.Paths.Base: pathViewL :: Num u => Path u -> PathViewL u
- Wumpus.Drawing.Paths.Base: pathViewR :: Num u => Path u -> PathViewR u
- Wumpus.Drawing.Paths.Base: pconcat :: Floating u => Path u -> [Path u] -> Path u
- Wumpus.Drawing.Paths.Base: pivot :: Floating u => Point2 u -> Path u
- Wumpus.Drawing.Paths.Base: roundInterior :: (Real u, Floating u, FromPtSize u) => u -> [Point2 u] -> Path u
- Wumpus.Drawing.Paths.Base: roundTrail :: (Real u, Floating u, FromPtSize u) => u -> [Point2 u] -> Path u
- Wumpus.Drawing.Paths.Base: shortenL :: (Real u, Floating u) => u -> Path u -> Path u
- Wumpus.Drawing.Paths.Base: shortenPath :: (Real u, Floating u) => u -> u -> Path u -> Path u
- Wumpus.Drawing.Paths.Base: shortenR :: (Real u, Floating u) => u -> Path u -> Path u
- Wumpus.Drawing.Paths.Base: tipL :: Path u -> Point2 u
- Wumpus.Drawing.Paths.Base: tipR :: Path u -> Point2 u
- Wumpus.Drawing.Paths.Base: toPrimPath :: Num u => Path u -> PrimPath u
- Wumpus.Drawing.Paths.Base: traceCurvePoints :: (Floating u, Ord u, FromPtSize u) => [Point2 u] -> Path u
- Wumpus.Drawing.Paths.Base: traceLinePoints :: Floating u => [Point2 u] -> Path u
- Wumpus.Drawing.Paths.Base: type DPath = Path Double
- Wumpus.Drawing.Paths.Base: type DPathSegment = PathSegment Double
- Wumpus.Drawing.Paths.Base: type DPathViewL = PathViewL Double
- Wumpus.Drawing.Paths.Base: type DPathViewR = PathViewR Double
- Wumpus.Drawing.Paths.Connectors: connIsosceles :: (Real u, Floating u, FromPtSize u) => u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connIsosceles2 :: (Real u, Floating u, FromPtSize u) => u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connIsoscelesCurve :: (Real u, Floating u, FromPtSize u) => u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connLightningBolt :: (Real u, Floating u, FromPtSize u) => u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connLine :: Floating u => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connRightHV :: (Real u, Floating u, FromPtSize u) => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connRightHVH :: (Real u, Floating u, FromPtSize u) => u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connRightVH :: (Real u, Floating u, FromPtSize u) => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connRightVHV :: (Real u, Floating u, FromPtSize u) => u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connSquareCurve :: (Real u, Floating u, FromPtSize u) => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connTrapezoidCurve :: (Real u, Floating u, FromPtSize u) => u -> u -> ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connUSquareCurve :: (Real u, Floating u, FromPtSize u) => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connUZSquareCurve :: (Real u, Floating u, FromPtSize u) => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: connZSquareCurve :: (Real u, Floating u, FromPtSize u) => ConnectorPath u
- Wumpus.Drawing.Paths.Connectors: sconnect :: Num u => ConnectorPath u -> Point2 u -> Point2 u -> Image u (Path u)
- Wumpus.Drawing.Paths.Connectors: type ConnectorPath u = ConnectorCF u (Path u)
- Wumpus.Drawing.Paths.Connectors: type DConnectorPath = ConnectorPath Double
- Wumpus.Drawing.Paths.ControlPoints: dblpointIsosceles :: (Real u, Floating u) => u -> Point2 u -> Point2 u -> (Point2 u, Point2 u)
- Wumpus.Drawing.Paths.ControlPoints: midpointIsosceles :: (Real u, Floating u) => u -> Point2 u -> Point2 u -> Point2 u
- Wumpus.Drawing.Paths.ControlPoints: rectangleFromBasePoints :: (Real u, Floating u) => u -> Point2 u -> Point2 u -> (Point2 u, Point2 u)
- Wumpus.Drawing.Paths.ControlPoints: squareFromBasePoints :: (Real u, Floating u) => Point2 u -> Point2 u -> (Point2 u, Point2 u)
- Wumpus.Drawing.Paths.ControlPoints: squareFromCornerPoints :: (Real u, Floating u) => Point2 u -> Point2 u -> (Point2 u, Point2 u)
- Wumpus.Drawing.Paths.ControlPoints: trapezoidFromBasePoints :: (Real u, Floating u) => u -> u -> Point2 u -> Point2 u -> (Point2 u, Point2 u)
- Wumpus.Drawing.Paths.ControlPoints: usquareFromBasePoints :: (Real u, Floating u) => Point2 u -> Point2 u -> (Point2 u, Point2 u)
- Wumpus.Drawing.Paths.MonadicConstruction: bezierto :: (Floating u, Ord u, FromPtSize u) => Point2 u -> Point2 u -> Point2 u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: curveto :: (Floating u, Ord u, FromPtSize u) => Radian -> Radian -> Point2 u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: data PathM u a
- Wumpus.Drawing.Paths.MonadicConstruction: execPath :: Floating u => Point2 u -> PathM u a -> Path u
- Wumpus.Drawing.Paths.MonadicConstruction: hline :: Floating u => u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: horizontalVertical :: Floating u => Point2 u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: instance Applicative (PathM u)
- Wumpus.Drawing.Paths.MonadicConstruction: instance Functor (PathM u)
- Wumpus.Drawing.Paths.MonadicConstruction: instance Monad (PathM u)
- Wumpus.Drawing.Paths.MonadicConstruction: lineto :: Floating u => Point2 u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: rlineto :: Floating u => Vec2 u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: runPath :: Floating u => Point2 u -> PathM u a -> (a, Path u)
- Wumpus.Drawing.Paths.MonadicConstruction: tip :: PathM u (Point2 u)
- Wumpus.Drawing.Paths.MonadicConstruction: verticalHorizontal :: Floating u => Point2 u -> PathM u ()
- Wumpus.Drawing.Paths.MonadicConstruction: vline :: Floating u => u -> PathM u ()
- Wumpus.Drawing.Shapes.Base: displaceCenter :: (Real u, Floating u) => Vec2 u -> ShapeCTM u -> Point2 u
- Wumpus.Drawing.Shapes.Base: instance Eq u => Eq (ShapeCTM u)
- Wumpus.Drawing.Shapes.Base: instance Functor (Shape u)
- Wumpus.Drawing.Shapes.Base: instance Num u => Scale (ShapeCTM u)
- Wumpus.Drawing.Shapes.Base: instance Ord u => Ord (ShapeCTM u)
- Wumpus.Drawing.Shapes.Base: instance Rotate (ShapeCTM u)
- Wumpus.Drawing.Shapes.Circle: instance Num u => Scale (Circle u)
- Wumpus.Drawing.Shapes.Circle: instance Rotate (Circle u)
- Wumpus.Drawing.Shapes.Diamond: instance (Real u, Floating u, Fractional u) => CardinalAnchor2 (Diamond u)
- Wumpus.Drawing.Shapes.Diamond: instance Num u => Scale (Diamond u)
- Wumpus.Drawing.Shapes.Diamond: instance Rotate (Diamond u)
- Wumpus.Drawing.Shapes.Ellipse: instance Num u => Scale (Ellipse u)
- Wumpus.Drawing.Shapes.Ellipse: instance Num u => Translate (Ellipse u)
- Wumpus.Drawing.Shapes.Ellipse: instance Rotate (Ellipse u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor2 (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, FromPtSize u) => RadialAnchor (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance Num u => Scale (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance Num u => Translate (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance Rotate (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u) => CenterAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u) => TopCornerAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, FromPtSize u) => ApexAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor2 (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, FromPtSize u) => RadialAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance Num u => Scale (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance Num u => Translate (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance Rotate (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvTriangle: instance Num u => Scale (InvTriangle u)
- Wumpus.Drawing.Shapes.InvTriangle: instance Num u => Translate (InvTriangle u)
- Wumpus.Drawing.Shapes.InvTriangle: instance Rotate (InvTriangle u)
- Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor2 (Parallelogram u)
- Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u, FromPtSize u) => RadialAnchor (Parallelogram u)
- Wumpus.Drawing.Shapes.Parallelogram: instance Num u => Scale (Parallelogram u)
- Wumpus.Drawing.Shapes.Parallelogram: instance Num u => Translate (Parallelogram u)
- Wumpus.Drawing.Shapes.Parallelogram: instance Rotate (Parallelogram u)
- Wumpus.Drawing.Shapes.Rectangle: instance Eq u => Eq (Rectangle u)
- Wumpus.Drawing.Shapes.Rectangle: instance Num u => Scale (Rectangle u)
- Wumpus.Drawing.Shapes.Rectangle: instance Num u => Translate (Rectangle u)
- Wumpus.Drawing.Shapes.Rectangle: instance Ord u => Ord (Rectangle u)
- Wumpus.Drawing.Shapes.Rectangle: instance Rotate (Rectangle u)
- Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor2 (Semicircle u)
- Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, FromPtSize u) => RadialAnchor (Semicircle u)
- Wumpus.Drawing.Shapes.Semicircle: instance Num u => Scale (Semicircle u)
- Wumpus.Drawing.Shapes.Semicircle: instance Num u => Translate (Semicircle u)
- Wumpus.Drawing.Shapes.Semicircle: instance Rotate (Semicircle u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, FromPtSize u) => ApexAnchor (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor2 (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, FromPtSize u) => RadialAnchor (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance Num u => Scale (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance Num u => Translate (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance Rotate (Semiellipse u)
- Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor (Trapezium u)
- Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, FromPtSize u) => CardinalAnchor2 (Trapezium u)
- Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, FromPtSize u) => RadialAnchor (Trapezium u)
- Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, FromPtSize u) => SideMidpointAnchor (Trapezium u)
- Wumpus.Drawing.Shapes.Trapezium: instance Num u => Scale (Trapezium u)
- Wumpus.Drawing.Shapes.Trapezium: instance Num u => Translate (Trapezium u)
- Wumpus.Drawing.Shapes.Trapezium: instance Rotate (Trapezium u)
- Wumpus.Drawing.Shapes.Triangle: instance Num u => Scale (Triangle u)
- Wumpus.Drawing.Shapes.Triangle: instance Num u => Translate (Triangle u)
- Wumpus.Drawing.Shapes.Triangle: instance Rotate (Triangle u)
- Wumpus.Drawing.Text.Base: advtext :: FromPtSize u => EscapedText -> AdvGraphic u
- Wumpus.Drawing.Text.Base: borderedTextObjectPos :: (Real u, Floating u, FromPtSize u) => Int -> u -> DrawingInfo (ObjectPos u)
- Wumpus.Drawing.Text.Base: centerSpinePoints :: Floating u => Int -> Radian -> LocChain u
- Wumpus.Drawing.Text.Base: centerToBaseline :: (Fractional u, FromPtSize u) => DrawingInfo u
- Wumpus.Drawing.Text.Base: charVector :: FromPtSize u => EscapedChar -> DrawingInfo (AdvanceVec u)
- Wumpus.Drawing.Text.Base: multilineHeight :: (Real u, Floating u, FromPtSize u) => Int -> DrawingInfo u
- Wumpus.Drawing.Text.Base: textObjectPos :: (Real u, Floating u, FromPtSize u) => Int -> u -> DrawingInfo (ObjectPos u)
- Wumpus.Drawing.Text.Base: textVector :: FromPtSize u => EscapedText -> DrawingInfo (AdvanceVec u)
- Wumpus.Drawing.Text.CatText: (<+>) :: FromPtSize u => CatText u -> CatText u -> CatText u
- Wumpus.Drawing.Text.CatText: (<>) :: CatText u -> CatText u -> CatText u
- Wumpus.Drawing.Text.CatText: blank :: Num u => CatText u
- Wumpus.Drawing.Text.CatText: centerAlign :: (Real u, FromPtSize u, Floating u) => [CatText u] -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.CatText: data CatText u
- Wumpus.Drawing.Text.CatText: fontColour :: RGBi -> CatText u -> CatText u
- Wumpus.Drawing.Text.CatText: leftAlign :: (Real u, FromPtSize u, Floating u) => [CatText u] -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.CatText: rightAlign :: (Real u, FromPtSize u, Floating u) => [CatText u] -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.CatText: space :: FromPtSize u => CatText u
- Wumpus.Drawing.Text.CatText: string :: FromPtSize u => String -> CatText u
- Wumpus.Drawing.Text.LRText: escSingleLine :: (Real u, Floating u, FromPtSize u) => EscapedText -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: multiAlignCenter :: (Real u, Floating u, FromPtSize u) => Radian -> String -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: multiAlignLeft :: (Real u, Floating u, FromPtSize u) => Radian -> String -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: multiAlignRight :: (Real u, Floating u, FromPtSize u) => Radian -> String -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: rescSingleLine :: (Real u, Floating u, FromPtSize u) => Radian -> EscapedText -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: rsingleLine :: (Real u, Floating u, FromPtSize u) => Radian -> String -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: singleLine :: (Real u, Floating u, FromPtSize u) => String -> PosImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: textAlignCenter :: (Real u, Floating u, FromPtSize u) => String -> LocImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: textAlignLeft :: (Real u, Floating u, FromPtSize u) => String -> LocImage u (BoundingBox u)
- Wumpus.Drawing.Text.LRText: textAlignRight :: (Real u, Floating u, FromPtSize u) => String -> LocImage u (BoundingBox u)
- Wumpus.Drawing.Text.SafeFonts: courier :: FontFace
- Wumpus.Drawing.Text.SafeFonts: courier_bold :: FontFace
- Wumpus.Drawing.Text.SafeFonts: courier_bold_oblique :: FontFace
- Wumpus.Drawing.Text.SafeFonts: courier_oblique :: FontFace
- Wumpus.Drawing.Text.SafeFonts: helvetica :: FontFace
- Wumpus.Drawing.Text.SafeFonts: helvetica_bold :: FontFace
- Wumpus.Drawing.Text.SafeFonts: helvetica_bold_oblique :: FontFace
- Wumpus.Drawing.Text.SafeFonts: helvetica_oblique :: FontFace
- Wumpus.Drawing.Text.SafeFonts: symbol :: FontFace
- Wumpus.Drawing.Text.SafeFonts: times_bold :: FontFace
- Wumpus.Drawing.Text.SafeFonts: times_bold_italic :: FontFace
- Wumpus.Drawing.Text.SafeFonts: times_italic :: FontFace
- Wumpus.Drawing.Text.SafeFonts: times_roman :: FontFace
- Wumpus.Drawing.Turtle.TurtleClass: class Monad m => TurtleM m
- Wumpus.Drawing.Turtle.TurtleClass: getLoc :: TurtleM m => m (Int, Int)
- Wumpus.Drawing.Turtle.TurtleClass: getOrigin :: TurtleM m => m (Int, Int)
- Wumpus.Drawing.Turtle.TurtleClass: moveDown :: TurtleM m => m ()
- Wumpus.Drawing.Turtle.TurtleClass: moveLeft :: TurtleM m => m ()
- Wumpus.Drawing.Turtle.TurtleClass: moveRight :: TurtleM m => m ()
- Wumpus.Drawing.Turtle.TurtleClass: moveUp :: TurtleM m => m ()
- Wumpus.Drawing.Turtle.TurtleClass: nextLine :: TurtleM m => m ()
- Wumpus.Drawing.Turtle.TurtleClass: resetLoc :: TurtleM m => m ()
- Wumpus.Drawing.Turtle.TurtleClass: setLoc :: TurtleM m => (Int, Int) -> m ()
- Wumpus.Drawing.Turtle.TurtleClass: setOrigin :: TurtleM m => (Int, Int) -> m ()
- Wumpus.Drawing.Turtle.TurtleClass: setsLoc :: TurtleM m => (Coord -> (a, Coord)) -> m a
- Wumpus.Drawing.Turtle.TurtleClass: setsLoc_ :: TurtleM m => (Coord -> Coord) -> m ()
- Wumpus.Drawing.Turtle.TurtleClass: type Coord = (Int, Int)
- Wumpus.Drawing.Turtle.TurtleMonad: data TurtleT u m a
- Wumpus.Drawing.Turtle.TurtleMonad: instance (u ~ MonUnit m, Monad m, Num u) => PointSupplyM (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: instance (u ~ MonUnit m, Monad m, TraceM m) => TraceM (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: instance DrawingCtxM m => DrawingCtxM (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: instance Monad m => Applicative (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: instance Monad m => Functor (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: instance Monad m => Monad (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: instance Monad m => TurtleM (TurtleT u m)
- Wumpus.Drawing.Turtle.TurtleMonad: runTurtleT :: (Monad m, Num u) => (Int, Int) -> ScalingContext Int Int u -> TurtleT u m a -> m a
+ Wumpus.Drawing.Connectors.Arrowheads: barb45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: barb60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: barb90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: bracket :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: curveTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: diamondTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: diamondWideTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: diskTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: odiamondTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: odiamondWideTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: odiskTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: orevtri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: orevtri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: orevtri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: osquareTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: otri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: otri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: otri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: perp :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revbarb45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revbarb60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revbarb90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revcurveTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revtri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revtri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revtri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: squareTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: tri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: tri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: tri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Base: data ArrowTip u
+ Wumpus.Drawing.Connectors.Base: leftArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: leftRightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: makeArrowTip :: Query u -> Query u -> LocThetaGraphic En -> ArrowTip u
+ Wumpus.Drawing.Connectors.Base: promoteConn :: (Real u, Floating u, InterpretUnit u) => (Point2 u -> Point2 u -> CF a) -> CF (Point2 u -> Point2 u -> a)
+ Wumpus.Drawing.Connectors.Base: rightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: type ArrowConnector u = ConnectorImage u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: type Connector u = ConnectorQuery u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: uniformArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.BoxConnectors: connbox :: (Real u, Floating u, InterpretUnit u) => ConnectorBox u
+ Wumpus.Drawing.Connectors.BoxConnectors: type ConnectorBox u = ConnectorGraphic u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connabar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connaloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connarc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connaright :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connbbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connbloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connbright :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conndiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conndiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connhbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connhdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connhdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connhrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connline :: (Real u, Floating u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connrrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connrrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connvbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connvdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connvdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connvrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u
+ Wumpus.Drawing.Connectors.Loop: loop :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorQuery u (AbsPath u)
+ Wumpus.Drawing.Connectors.Loop: loopPoints :: (Real u, Floating u) => u -> Point2 u -> Radian -> [Point2 u]
+ Wumpus.Drawing.Extras.Axes: orthontAxes :: (Real u, Floating u, InterpretUnit u) => (Double, Double) -> Graphic u
+ Wumpus.Drawing.Extras.Grids: grid :: (Fractional u, InterpretUnit u) => GridContextF -> (Int, Int) -> (Int, Int) -> Graphic u
+ Wumpus.Drawing.Extras.Grids: grid_label_colour :: RGBi -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_major_colour :: RGBi -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_major_dotnum :: Int -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_major_line_width :: Double -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_minor_colour :: RGBi -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_minor_dotnum :: Int -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_minor_line_width :: Double -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_minor_subdivisions :: Int -> GridContextF
+ Wumpus.Drawing.Extras.Grids: grid_point_size :: FontSize -> GridContextF
+ Wumpus.Drawing.Extras.Grids: standard_grid :: GridContextF
+ Wumpus.Drawing.Extras.Grids: type GridContextF = GridProps -> GridProps
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: class Monad m => TurtleM m
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: getLoc :: TurtleM m => m (Int, Int)
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: getOrigin :: TurtleM m => m (Int, Int)
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: moveDown :: TurtleM m => m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: moveLeft :: TurtleM m => m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: moveRight :: TurtleM m => m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: moveUp :: TurtleM m => m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: nextLine :: TurtleM m => m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: resetLoc :: TurtleM m => m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: setLoc :: TurtleM m => (Int, Int) -> m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: setOrigin :: TurtleM m => (Int, Int) -> m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: setsLoc :: TurtleM m => (Coord -> (a, Coord)) -> m a
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: setsLoc_ :: TurtleM m => (Coord -> Coord) -> m ()
+ Wumpus.Drawing.Extras.Turtle.TurtleClass: type Coord = (Int, Int)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: data TurtleT u m a
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance (u ~ MonUnit (m ()), Monad m, TraceM m) => TraceM (TurtleT u m)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance DrawingCtxM m => DrawingCtxM (TurtleT u m)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => Applicative (TurtleT u m)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => Functor (TurtleT u m)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => Monad (TurtleT u m)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => TurtleM (TurtleT u m)
+ Wumpus.Drawing.Extras.Turtle.TurtleMonad: runTurtleT :: (Monad m, Num u) => (Int, Int) -> TurtleT u m a -> m a
+ Wumpus.Drawing.Paths.Base.AbsBuilder: abscurve :: (Floating u, Ord u, Tolerance u) => Point2 u -> Point2 u -> Point2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: absline :: Floating u => Point2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: absmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Point2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: aline :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: amove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: ctrlcurve :: (Floating u, Ord u, Tolerance u) => Radian -> Radian -> Point2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: cycle :: (Floating u, InterpretUnit u) => AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: data AbsBuild u a
+ Wumpus.Drawing.Paths.Base.AbsBuilder: evalAbsBuild :: (Floating u, InterpretUnit u) => Point2 u -> AbsBuild u a -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsBuilder: execAbsBuild :: (Floating u, InterpretUnit u) => Point2 u -> AbsBuild u a -> Graphic u
+ Wumpus.Drawing.Paths.Base.AbsBuilder: hline :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: hmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: insert :: Num u => LocGraphic u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: instance Applicative (AbsBuild u)
+ Wumpus.Drawing.Paths.Base.AbsBuilder: instance Functor (AbsBuild u)
+ Wumpus.Drawing.Paths.Base.AbsBuilder: instance Monad (AbsBuild u)
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_down :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_down_left :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_down_right :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_east :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_left :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_north :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_northeast :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_northwest :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_right :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_south :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_southeast :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_southwest :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_up :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_up_left :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_up_right :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: line_west :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_down :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_down_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_down_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_east :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_north :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_northeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_northwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_south :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_southeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_southwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_up :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_up_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_up_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: move_west :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: pen_colour :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => RGBi -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: pen_width :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Double -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: relcurve :: (Floating u, Ord u, Tolerance u) => Vec2 u -> Vec2 u -> Vec2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: relline :: Floating u => Vec2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: rellineParallel :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: rellinePerpendicular :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: relmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Vec2 u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: relmoveParallel :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: relmovePerpendicular :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: runAbsBuild :: (Floating u, InterpretUnit u) => Point2 u -> AbsBuild u a -> (AbsPath u, Graphic u)
+ Wumpus.Drawing.Paths.Base.AbsBuilder: setIncline :: Radian -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: tip :: AbsBuild u (Point2 u)
+ Wumpus.Drawing.Paths.Base.AbsBuilder: vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Vamp u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: vline :: Floating u => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsBuilder: vmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
+ Wumpus.Drawing.Paths.Base.AbsPath: (:<<) :: PathSegment u -> AbsPath u -> PathViewL u
+ Wumpus.Drawing.Paths.Base.AbsPath: (:>>) :: AbsPath u -> PathSegment u -> PathViewR u
+ Wumpus.Drawing.Paths.Base.AbsPath: CurveSeg :: (Point2 u) -> (Point2 u) -> (Point2 u) -> (Point2 u) -> PathSegment u
+ Wumpus.Drawing.Paths.Base.AbsPath: LineSeg :: (Point2 u) -> (Point2 u) -> PathSegment u
+ Wumpus.Drawing.Paths.Base.AbsPath: PathOneL :: (PathSegment u) -> PathViewL u
+ Wumpus.Drawing.Paths.Base.AbsPath: PathOneR :: (PathSegment u) -> PathViewR u
+ Wumpus.Drawing.Paths.Base.AbsPath: append :: (Floating u, Ord u, Tolerance u) => AbsPath u -> AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: atend :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)
+ Wumpus.Drawing.Paths.Base.AbsPath: atend_ :: AbsPath u -> Point2 u
+ Wumpus.Drawing.Paths.Base.AbsPath: atstart :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)
+ Wumpus.Drawing.Paths.Base.AbsPath: atstart_ :: AbsPath u -> Point2 u
+ Wumpus.Drawing.Paths.Base.AbsPath: consCurveTo :: (Floating u, Ord u, Tolerance u) => Point2 u -> Point2 u -> Point2 u -> AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: consLineTo :: Floating u => Point2 u -> AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: controlCurve :: (Floating u, Ord u, Tolerance u) => Point2 u -> Radian -> Radian -> Point2 u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: curve1 :: (Floating u, Ord u, Tolerance u) => Point2 u -> Point2 u -> Point2 u -> Point2 u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: curvePath :: (Floating u, Ord u, Tolerance u) => [Point2 u] -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: data AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: data PathSegment u
+ Wumpus.Drawing.Paths.Base.AbsPath: data PathViewL u
+ Wumpus.Drawing.Paths.Base.AbsPath: data PathViewR u
+ Wumpus.Drawing.Paths.Base.AbsPath: directionL :: (Real u, Floating u) => AbsPath u -> Radian
+ Wumpus.Drawing.Paths.Base.AbsPath: directionR :: (Real u, Floating u) => AbsPath u -> Radian
+ Wumpus.Drawing.Paths.Base.AbsPath: empty :: Floating u => Point2 u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: instance (Ord u, Tolerance u) => Eq (AbsPath u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance (Ord u, Tolerance u) => Eq (AbsPathSeg u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance (Ord u, Tolerance u) => Eq (PathSegment u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance (Ord u, Tolerance u) => Eq (PathViewL u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance (Ord u, Tolerance u) => Eq (PathViewR u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Functor AbsPath
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Functor AbsPathSeg
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Functor PathSegment
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Functor PathViewL
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Functor PathViewR
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Show u => Show (AbsPath u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Show u => Show (AbsPathSeg u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Show u => Show (PathSegment u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Show u => Show (PathViewL u)
+ Wumpus.Drawing.Paths.Base.AbsPath: instance Show u => Show (PathViewR u)
+ Wumpus.Drawing.Paths.Base.AbsPath: length :: Num u => AbsPath u -> u
+ Wumpus.Drawing.Paths.Base.AbsPath: line1 :: Floating u => Point2 u -> Point2 u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: midway :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)
+ Wumpus.Drawing.Paths.Base.AbsPath: midway_ :: (Real u, Floating u) => AbsPath u -> Point2 u
+ Wumpus.Drawing.Paths.Base.AbsPath: null :: AbsPath u -> Bool
+ Wumpus.Drawing.Paths.Base.AbsPath: pathViewL :: Num u => AbsPath u -> PathViewL u
+ Wumpus.Drawing.Paths.Base.AbsPath: pathViewR :: Num u => AbsPath u -> PathViewR u
+ Wumpus.Drawing.Paths.Base.AbsPath: pathconcat :: (Floating u, Ord u, Tolerance u) => AbsPath u -> [AbsPath u] -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: roundInterior :: (Real u, Floating u, Tolerance u) => u -> [Point2 u] -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: roundTrail :: (Real u, Floating u, Tolerance u) => u -> [Point2 u] -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: shortenL :: (Real u, Floating u) => u -> AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: shortenPath :: (Real u, Floating u) => u -> u -> AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: shortenR :: (Real u, Floating u) => u -> AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: snocCurveTo :: (Floating u, Ord u, Tolerance u) => AbsPath u -> Point2 u -> Point2 u -> Point2 u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: snocLineTo :: Floating u => AbsPath u -> Point2 u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.AbsPath: tipL :: AbsPath u -> Point2 u
+ Wumpus.Drawing.Paths.Base.AbsPath: tipR :: AbsPath u -> Point2 u
+ Wumpus.Drawing.Paths.Base.AbsPath: toPrimPath :: InterpretUnit u => AbsPath u -> Query PrimPath
+ Wumpus.Drawing.Paths.Base.AbsPath: type DAbsPath = AbsPath Double
+ Wumpus.Drawing.Paths.Base.AbsPath: type DPathSegment = PathSegment Double
+ Wumpus.Drawing.Paths.Base.AbsPath: type DPathViewL = PathViewL Double
+ Wumpus.Drawing.Paths.Base.AbsPath: type DPathViewR = PathViewR Double
+ Wumpus.Drawing.Paths.Base.AbsPath: vertexPath :: (Floating u, Ord u, Tolerance u) => [Point2 u] -> AbsPath u
+ Wumpus.Drawing.Paths.Base.BuildCommon: PATH_CLOSED :: PathEnd
+ Wumpus.Drawing.Paths.Base.BuildCommon: PATH_OPEN :: PathEnd
+ Wumpus.Drawing.Paths.Base.BuildCommon: Vamp :: Vec2 u -> Vec2 u -> DrawingContextF -> RelPath u -> PathEnd -> Vamp u
+ Wumpus.Drawing.Paths.Base.BuildCommon: addInsert :: a -> BuildLog a -> BuildLog a
+ Wumpus.Drawing.Paths.Base.BuildCommon: addPen :: a -> BuildLog a -> BuildLog a
+ Wumpus.Drawing.Paths.Base.BuildCommon: data BuildLog a
+ Wumpus.Drawing.Paths.Base.BuildCommon: data PathEnd
+ Wumpus.Drawing.Paths.Base.BuildCommon: data Vamp u
+ Wumpus.Drawing.Paths.Base.BuildCommon: extractTrace :: OPlus a => a -> BuildLog a -> (a, a)
+ Wumpus.Drawing.Paths.Base.BuildCommon: insert1 :: a -> BuildLog a
+ Wumpus.Drawing.Paths.Base.BuildCommon: instance Eq PathEnd
+ Wumpus.Drawing.Paths.Base.BuildCommon: instance Monoid (BuildLog a)
+ Wumpus.Drawing.Paths.Base.BuildCommon: instance Show PathEnd
+ Wumpus.Drawing.Paths.Base.BuildCommon: pen1 :: a -> BuildLog a
+ Wumpus.Drawing.Paths.Base.BuildCommon: vamp_dc_update :: Vamp u -> DrawingContextF
+ Wumpus.Drawing.Paths.Base.BuildCommon: vamp_deco_path :: Vamp u -> RelPath u
+ Wumpus.Drawing.Paths.Base.BuildCommon: vamp_move_span :: Vamp u -> Vec2 u
+ Wumpus.Drawing.Paths.Base.BuildCommon: vamp_move_start :: Vamp u -> Vec2 u
+ Wumpus.Drawing.Paths.Base.BuildCommon: vamp_path_end :: Vamp u -> PathEnd
+ Wumpus.Drawing.Paths.Base.RelBuilder: aline :: Floating u => Radian -> u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: amove :: (Floating u, InterpretUnit u) => Radian -> u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: curve :: Floating u => Vec2 u -> Vec2 u -> Vec2 u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: cycle :: (Floating u, InterpretUnit u) => RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: data RelBuild u a
+ Wumpus.Drawing.Paths.Base.RelBuilder: evalRelBuild :: (Floating u, InterpretUnit u) => RelBuild u a -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelBuilder: execPivot :: (Floating u, InterpretUnit u) => RelBuild u a -> LocGraphic u
+ Wumpus.Drawing.Paths.Base.RelBuilder: execRelBuild :: (Floating u, InterpretUnit u) => RelBuild u a -> LocGraphic u
+ Wumpus.Drawing.Paths.Base.RelBuilder: hline :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: hmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: insert :: Num u => LocGraphic u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: instance Applicative (RelBuild u)
+ Wumpus.Drawing.Paths.Base.RelBuilder: instance Functor (RelBuild u)
+ Wumpus.Drawing.Paths.Base.RelBuilder: instance Monad (RelBuild u)
+ Wumpus.Drawing.Paths.Base.RelBuilder: line :: Floating u => Vec2 u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_down :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_down_left :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_down_right :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_east :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_left :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_north :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_northeast :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_northwest :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_right :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_south :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_southeast :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_southwest :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_up :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_up_left :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_up_right :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: line_west :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move :: (Floating u, InterpretUnit u) => Vec2 u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_down :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_down_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_down_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_east :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_north :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_northeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_northwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_south :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_southeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_southwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_up :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_up_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_up_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: move_west :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: pen_colour :: (Floating u, InterpretUnit u) => RGBi -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: pen_width :: (Floating u, InterpretUnit u) => Double -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: pivot :: RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: runRelBuild :: (Floating u, InterpretUnit u) => RelBuild u a -> (RelPath u, LocGraphic u)
+ Wumpus.Drawing.Paths.Base.RelBuilder: setIncline :: Radian -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: tip :: RelBuild u (Vec2 u)
+ Wumpus.Drawing.Paths.Base.RelBuilder: vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Vamp u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: vline :: Floating u => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelBuilder: vmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
+ Wumpus.Drawing.Paths.Base.RelPath: append :: RelPath u -> RelPath u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: circular :: Floating u => u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: consCurveTo :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: consLineTo :: Vec2 u -> RelPath u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: curve1 :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: curvedPath :: [Vec2 u] -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: data RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: empty :: RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: fromPathAlgCurves :: Num u => PathAlg u -> (Vec2 u, RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: fromPathAlgVertices :: Num u => PathAlg u -> (Vec2 u, RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: instance (Ord u, Tolerance u) => Eq (RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: instance (Ord u, Tolerance u) => Eq (RelPathSeg u)
+ Wumpus.Drawing.Paths.Base.RelPath: instance Functor RelPath
+ Wumpus.Drawing.Paths.Base.RelPath: instance Functor RelPathSeg
+ Wumpus.Drawing.Paths.Base.RelPath: instance Monoid (RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: instance Show u => Show (RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: instance Show u => Show (RelPathSeg u)
+ Wumpus.Drawing.Paths.Base.RelPath: line1 :: Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: null :: RelPath u -> Bool
+ Wumpus.Drawing.Paths.Base.RelPath: snocCurveTo :: RelPath u -> Vec2 u -> Vec2 u -> Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: snocLineTo :: RelPath u -> Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: strokeRelPath :: InterpretUnit u => RelPath u -> LocGraphic u
+ Wumpus.Drawing.Paths.Base.RelPath: toAbsPath :: (Floating u, Ord u, Tolerance u) => Point2 u -> RelPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.RelPath: toPrimPath :: InterpretUnit u => Point2 u -> RelPath u -> Query PrimPath
+ Wumpus.Drawing.Paths.Base.RelPath: type DRelPath = RelPath Double
+ Wumpus.Drawing.Paths.Base.RelPath: vertexPath :: [Vec2 u] -> RelPath u
+ Wumpus.Drawing.Paths.Vamps: PATH_CLOSED :: PathEnd
+ Wumpus.Drawing.Paths.Vamps: PATH_OPEN :: PathEnd
+ Wumpus.Drawing.Paths.Vamps: Vamp :: Vec2 u -> Vec2 u -> DrawingContextF -> RelPath u -> PathEnd -> Vamp u
+ Wumpus.Drawing.Paths.Vamps: circleVamp :: (Fractional u, Floating u) => Vec2 u -> Vamp u
+ Wumpus.Drawing.Paths.Vamps: data PathEnd
+ Wumpus.Drawing.Paths.Vamps: data Vamp u
+ Wumpus.Drawing.Paths.Vamps: vamp_dc_update :: Vamp u -> DrawingContextF
+ Wumpus.Drawing.Paths.Vamps: vamp_deco_path :: Vamp u -> RelPath u
+ Wumpus.Drawing.Paths.Vamps: vamp_move_span :: Vamp u -> Vec2 u
+ Wumpus.Drawing.Paths.Vamps: vamp_move_start :: Vamp u -> Vec2 u
+ Wumpus.Drawing.Paths.Vamps: vamp_path_end :: Vamp u -> PathEnd
+ Wumpus.Drawing.Shapes.Base: dblStrokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)
+ Wumpus.Drawing.Shapes.Base: instance (Ord u, Tolerance u) => Eq (ShapeCTM u)
+ Wumpus.Drawing.Shapes.Base: instance (Ord u, Tolerance u) => Ord (ShapeCTM u)
+ Wumpus.Drawing.Shapes.Base: instance (Real u, Floating u) => Rotate (ShapeCTM u)
+ Wumpus.Drawing.Shapes.Base: instance Fractional u => Scale (ShapeCTM u)
+ Wumpus.Drawing.Shapes.Base: instance Functor ShapeCTM
+ Wumpus.Drawing.Shapes.Base: projectFromCtr :: (Real u, Floating u) => Vec2 u -> ShapeCTM u -> Anchor u
+ Wumpus.Drawing.Shapes.Base: shapeMap :: (t u -> t' u) -> Shape t u -> Shape t' u
+ Wumpus.Drawing.Shapes.Circle: instance (Real u, Floating u) => Rotate (Circle u)
+ Wumpus.Drawing.Shapes.Circle: instance Fractional u => Scale (Circle u)
+ Wumpus.Drawing.Shapes.Circle: instance Functor Circle
+ Wumpus.Drawing.Shapes.Diamond: instance (Real u, Floating u) => CardinalAnchor2 (Diamond u)
+ Wumpus.Drawing.Shapes.Diamond: instance (Real u, Floating u) => Rotate (Diamond u)
+ Wumpus.Drawing.Shapes.Diamond: instance Fractional u => Scale (Diamond u)
+ Wumpus.Drawing.Shapes.Diamond: instance Functor Diamond
+ Wumpus.Drawing.Shapes.Ellipse: instance (Real u, Floating u) => Rotate (Ellipse u)
+ Wumpus.Drawing.Shapes.Ellipse: instance Fractional u => Scale (Ellipse u)
+ Wumpus.Drawing.Shapes.Ellipse: instance Functor Ellipse
+ Wumpus.Drawing.Shapes.Ellipse: instance InterpretUnit u => Translate (Ellipse u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u) => Rotate (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, Tolerance u) => RadialAnchor (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance Fractional u => Scale (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance Functor InvSemicircle
+ Wumpus.Drawing.Shapes.InvSemicircle: instance InterpretUnit u => Translate (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u) => Rotate (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => ApexAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => CenterAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => RadialAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => TopCornerAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance Fractional u => Scale (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance Functor InvSemiellipse
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance InterpretUnit u => Translate (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvTriangle: instance (Real u, Floating u) => Rotate (InvTriangle u)
+ Wumpus.Drawing.Shapes.InvTriangle: instance Fractional u => Scale (InvTriangle u)
+ Wumpus.Drawing.Shapes.InvTriangle: instance Functor InvTriangle
+ Wumpus.Drawing.Shapes.InvTriangle: instance InterpretUnit u => Translate (InvTriangle u)
+ Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u) => Rotate (Parallelogram u)
+ Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Parallelogram u)
+ Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Parallelogram u)
+ Wumpus.Drawing.Shapes.Parallelogram: instance Fractional u => Scale (Parallelogram u)
+ Wumpus.Drawing.Shapes.Parallelogram: instance Functor Parallelogram
+ Wumpus.Drawing.Shapes.Parallelogram: instance Functor SyntheticProps
+ Wumpus.Drawing.Shapes.Parallelogram: instance InterpretUnit u => Translate (Parallelogram u)
+ Wumpus.Drawing.Shapes.Rectangle: instance (Ord u, Tolerance u) => Eq (Rectangle u)
+ Wumpus.Drawing.Shapes.Rectangle: instance (Ord u, Tolerance u) => Ord (Rectangle u)
+ Wumpus.Drawing.Shapes.Rectangle: instance (Real u, Floating u) => Rotate (Rectangle u)
+ Wumpus.Drawing.Shapes.Rectangle: instance Fractional u => Scale (Rectangle u)
+ Wumpus.Drawing.Shapes.Rectangle: instance Functor Rectangle
+ Wumpus.Drawing.Shapes.Rectangle: instance InterpretUnit u => Translate (Rectangle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u) => Rotate (Semicircle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Semicircle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, Tolerance u) => RadialAnchor (Semicircle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance Fractional u => Scale (Semicircle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance Functor Semicircle
+ Wumpus.Drawing.Shapes.Semicircle: instance Functor SyntheticProps
+ Wumpus.Drawing.Shapes.Semicircle: instance InterpretUnit u => Translate (Semicircle u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u) => Rotate (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => ApexAnchor (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => RadialAnchor (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance Fractional u => Scale (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance Functor Semiellipse
+ Wumpus.Drawing.Shapes.Semiellipse: instance Functor SyntheticProps
+ Wumpus.Drawing.Shapes.Semiellipse: instance InterpretUnit u => Translate (Semiellipse u)
+ Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u) => Rotate (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, Tolerance u) => RadialAnchor (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: instance (Real u, Floating u, Tolerance u) => SideMidpointAnchor (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: instance Fractional u => Scale (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: instance Functor Trapezium
+ Wumpus.Drawing.Shapes.Trapezium: instance InterpretUnit u => Translate (Trapezium u)
+ Wumpus.Drawing.Shapes.Triangle: instance (Real u, Floating u) => Rotate (Triangle u)
+ Wumpus.Drawing.Shapes.Triangle: instance Fractional u => Scale (Triangle u)
+ Wumpus.Drawing.Shapes.Triangle: instance Functor SyntheticProps
+ Wumpus.Drawing.Shapes.Triangle: instance Functor Triangle
+ Wumpus.Drawing.Shapes.Triangle: instance InterpretUnit u => Translate (Triangle u)
+ Wumpus.Drawing.Text.Base.Common: advtext :: InterpretUnit u => EscapedText -> AdvGraphic u
+ Wumpus.Drawing.Text.Base.Common: charOrientationZero :: (DrawingCtxM m, InterpretUnit u) => EscapedChar -> m (Orientation u)
+ Wumpus.Drawing.Text.Base.Common: charVector :: (DrawingCtxM m, InterpretUnit u) => EscapedChar -> m (AdvanceVec u)
+ Wumpus.Drawing.Text.Base.Common: hkernOrientationZero :: (DrawingCtxM m, InterpretUnit u) => [KernChar u] -> m (Orientation u)
+ Wumpus.Drawing.Text.Base.Common: hkernVector :: (DrawingCtxM m, InterpretUnit u) => [KernChar u] -> m (AdvanceVec u)
+ Wumpus.Drawing.Text.Base.Common: posTextWithMargins :: (Fractional u, InterpretUnit u) => PosObject u -> BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.Common: textOrientationZero :: (DrawingCtxM m, InterpretUnit u) => EscapedText -> m (Orientation u)
+ Wumpus.Drawing.Text.Base.Common: textVector :: (DrawingCtxM m, InterpretUnit u) => EscapedText -> m (AdvanceVec u)
+ Wumpus.Drawing.Text.Base.DocTextZero: (<+>) :: Doc u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: (<>) :: Doc u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: blank :: Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: bold :: Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: boldItalic :: Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: centerAlign :: [Doc u] -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: centerfill :: u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: data Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: escaped :: EscapedText -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: ffloat :: (RealFloat a, InterpretUnit u) => (Maybe Int) -> a -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: float :: (RealFloat a, InterpretUnit u) => a -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: fontColour :: RGBi -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: highlight :: (Fractional u, InterpretUnit u) => RGBi -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: instance Applicative (EvalM u)
+ Wumpus.Drawing.Text.Base.DocTextZero: instance Functor (EvalM u)
+ Wumpus.Drawing.Text.Base.DocTextZero: instance Monad (EvalM u)
+ Wumpus.Drawing.Text.Base.DocTextZero: int :: InterpretUnit u => Int -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: integer :: InterpretUnit u => Integer -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: italic :: Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: leftAlign :: [Doc u] -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: lfill :: u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: render :: (Real u, Floating u, InterpretUnit u) => FontFamily -> Doc u -> BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.DocTextZero: rfill :: u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: rightAlign :: [Doc u] -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: space :: Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: strikethrough :: Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: string :: String -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: textSize :: Int -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: type TextFrame u = BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.DocTextZero: underline :: Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: vcatc :: Doc u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: vcatl :: Doc u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.DocTextZero: vcatr :: Doc u -> Doc u -> Doc u
+ Wumpus.Drawing.Text.Base.Label: connectorPathLabel :: Floating u => (AbsPath u -> Point2 u) -> RectAddress -> BoundedLocRectGraphic u -> Image u (AbsPath u) -> Image u (AbsPath u)
+ Wumpus.Drawing.Text.Base.Label: label_above :: (Floating u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_atend_of :: (Real u, Floating u) => RectAddress -> BoundedLocRectGraphic u -> Image u (AbsPath u) -> Image u (AbsPath u)
+ Wumpus.Drawing.Text.Base.Label: label_atstart_of :: (Real u, Floating u) => RectAddress -> BoundedLocRectGraphic u -> Image u (AbsPath u) -> Image u (AbsPath u)
+ Wumpus.Drawing.Text.Base.Label: label_below :: (Floating u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_center_of :: (Floating u, CenterAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_left_of :: (Floating u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_midway_of :: (Real u, Floating u) => RectAddress -> BoundedLocRectGraphic u -> Image u (AbsPath u) -> Image u (AbsPath u)
+ Wumpus.Drawing.Text.Base.Label: label_right_of :: (Floating u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: locImageLabel :: Floating u => (a -> Anchor u) -> RectAddress -> BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.PosChar: charLabel :: (Floating u, InterpretUnit u) => Char -> LocRectChar u
+ Wumpus.Drawing.Text.Base.PosChar: escCharLabel :: (Floating u, InterpretUnit u) => EscapedChar -> LocRectChar u
+ Wumpus.Drawing.Text.Base.PosChar: posChar :: InterpretUnit u => Char -> PosChar u
+ Wumpus.Drawing.Text.Base.PosChar: posEscChar :: InterpretUnit u => EscapedChar -> PosChar u
+ Wumpus.Drawing.Text.Base.PosChar: type LocRectChar u = BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.RotTextZero: blcTextline :: (Floating u, InterpretUnit u) => String -> LocTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: bllTextline :: (Floating u, InterpretUnit u) => String -> LocTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: ccTextline :: (Floating u, InterpretUnit u) => String -> LocTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: multiAlignCenter :: (Real u, Floating u, InterpretUnit u) => String -> LocRectTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: multiAlignLeft :: (Real u, Floating u, InterpretUnit u) => String -> LocRectTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: multiAlignRight :: (Real u, Floating u, InterpretUnit u) => String -> LocRectTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: rescTextline :: (Real u, Floating u, Ord u, InterpretUnit u) => Radian -> EscapedText -> LocRectTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: rtextline :: (Real u, Floating u, Ord u, InterpretUnit u) => Radian -> String -> LocRectTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: textline :: (Fractional u, InterpretUnit u) => String -> LocRectTextLine u
+ Wumpus.Drawing.Text.Base.RotTextZero: type LocRectTextLine u = BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.RotTextZero: type LocTextLine u = BoundedLocGraphic u
+ Wumpus.Drawing.Text.Base.RotTextZero: type TextObject u = PosObject u
+ Wumpus.Drawing.Text.StandardFontDefs: courier :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: courier_bold :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: courier_bold_oblique :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: courier_family :: FontFamily
+ Wumpus.Drawing.Text.StandardFontDefs: courier_oblique :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: helvetica :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: helvetica_bold :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: helvetica_bold_oblique :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: helvetica_family :: FontFamily
+ Wumpus.Drawing.Text.StandardFontDefs: helvetica_oblique :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: symbol :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: times_bold :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: times_bold_italic :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: times_italic :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: times_roman :: FontDef
+ Wumpus.Drawing.Text.StandardFontDefs: times_roman_family :: FontFamily
- Wumpus.Drawing.Dots.AnchorDots: dotAsterisk :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotAsterisk :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotChar :: (Floating u, Real u, FromPtSize u) => Char -> DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotChar :: (Floating u, Real u, InterpretUnit u) => Char -> DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotCircle :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotCircle :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotCross :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotCross :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotDiamond :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotDiamond :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotDisk :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotDisk :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotFDiamond :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotFDiamond :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotFOCross :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotFOCross :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotHLine :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotHLine :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotOCross :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotOCross :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotOPlus :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotOPlus :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotPentagon :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotPentagon :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotPlus :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotPlus :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotSquare :: (Floating u, Real u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotSquare :: (Floating u, Real u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotStar :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotStar :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotText :: (Floating u, Real u, FromPtSize u) => String -> DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotText :: (Floating u, Real u, InterpretUnit u) => String -> DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotTriangle :: (Real u, Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotTriangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotVLine :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotVLine :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotX :: (Floating u, FromPtSize u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotX :: (Floating u, InterpretUnit u) => DotLocImage u
- Wumpus.Drawing.Dots.Marks: markAsterisk :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markAsterisk :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markBDiamond :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markChar :: (Real u, Floating u, FromPtSize u) => Char -> LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markChar :: (Real u, Floating u, InterpretUnit u) => Char -> LocGraphic u
- Wumpus.Drawing.Dots.Marks: markCircle :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markCircle :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markCross :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markCross :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markDiamond :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markDisk :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markDisk :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markFDiamond :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markFOCross :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markFOCross :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markHLine :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markHLine :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markOCross :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markOCross :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markOPlus :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markOPlus :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markPentagon :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markPentagon :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markPlus :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markPlus :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markSquare :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markSquare :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markStar :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markStar :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markText :: (Real u, Floating u, FromPtSize u) => String -> LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markText :: (Real u, Floating u, InterpretUnit u) => String -> LocGraphic u
- Wumpus.Drawing.Dots.Marks: markTriangle :: (Floating u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markTriangle :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markVLine :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markVLine :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markX :: (Fractional u, FromPtSize u) => LocGraphic u
+ Wumpus.Drawing.Dots.Marks: markX :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Shapes.Base: borderedShape :: Num u => Shape u a -> LocImage u a
+ Wumpus.Drawing.Shapes.Base: borderedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)
- Wumpus.Drawing.Shapes.Base: data Shape u a
+ Wumpus.Drawing.Shapes.Base: data Shape t u
- Wumpus.Drawing.Shapes.Base: filledShape :: Num u => Shape u a -> LocImage u a
+ Wumpus.Drawing.Shapes.Base: filledShape :: InterpretUnit u => Shape t u -> LocImage u (t u)
- Wumpus.Drawing.Shapes.Base: makeShape :: Num u => LocThetaCF u a -> LocThetaCF u (Path u) -> Shape u a
+ Wumpus.Drawing.Shapes.Base: makeShape :: InterpretUnit u => LocThetaQuery u (t u) -> LocThetaQuery u (AbsPath u) -> Shape t u
- Wumpus.Drawing.Shapes.Base: makeShapeCTM :: Num u => Point2 u -> Radian -> ShapeCTM u
+ Wumpus.Drawing.Shapes.Base: makeShapeCTM :: Point2 u -> Radian -> ShapeCTM u
- Wumpus.Drawing.Shapes.Base: rborderedShape :: Num u => Shape u a -> LocThetaImage u a
+ Wumpus.Drawing.Shapes.Base: rborderedShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u)
- Wumpus.Drawing.Shapes.Base: rfilledShape :: Num u => Shape u a -> LocThetaImage u a
+ Wumpus.Drawing.Shapes.Base: rfilledShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u)
- Wumpus.Drawing.Shapes.Base: roundCornerShapePath :: (Real u, Floating u, FromPtSize u) => [Point2 u] -> CF (Path u)
+ Wumpus.Drawing.Shapes.Base: roundCornerShapePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> [Point2 u] -> Query (AbsPath u)
- Wumpus.Drawing.Shapes.Base: rstrokedShape :: Num u => Shape u a -> LocThetaImage u a
+ Wumpus.Drawing.Shapes.Base: rstrokedShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u)
- Wumpus.Drawing.Shapes.Base: setDecoration :: LocThetaGraphic u -> Shape u a -> Shape u a
+ Wumpus.Drawing.Shapes.Base: setDecoration :: LocThetaGraphic u -> Shape t u -> Shape t u
- Wumpus.Drawing.Shapes.Base: strokedShape :: Num u => Shape u a -> LocImage u a
+ Wumpus.Drawing.Shapes.Base: strokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)
- Wumpus.Drawing.Shapes.Base: type DShape a = Shape Double a
+ Wumpus.Drawing.Shapes.Base: type DShape t = Shape t Double
- Wumpus.Drawing.Shapes.Base: updatePathAngle :: (Radian -> Radian) -> Shape u a -> Shape u a
+ Wumpus.Drawing.Shapes.Base: updatePathAngle :: (Radian -> Radian) -> Shape t u -> Shape t u
- Wumpus.Drawing.Shapes.Circle: circle :: (Real u, Floating u, FromPtSize u) => u -> Shape u (Circle u)
+ Wumpus.Drawing.Shapes.Circle: circle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> Shape Circle u
- Wumpus.Drawing.Shapes.Diamond: diamond :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (Diamond u)
+ Wumpus.Drawing.Shapes.Diamond: diamond :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Diamond u
- Wumpus.Drawing.Shapes.Ellipse: ellipse :: (Real u, Floating u, FromPtSize u, Ord u) => u -> u -> Shape u (Ellipse u)
+ Wumpus.Drawing.Shapes.Ellipse: ellipse :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) => u -> u -> Shape Ellipse u
- Wumpus.Drawing.Shapes.InvSemicircle: invsemicircle :: (Real u, Floating u, FromPtSize u) => u -> Shape u (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemicircle: invsemicircle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> Shape InvSemicircle u
- Wumpus.Drawing.Shapes.InvSemiellipse: invsemiellipse :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: invsemiellipse :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape InvSemiellipse u
- Wumpus.Drawing.Shapes.InvTriangle: invtriangle :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (InvTriangle u)
+ Wumpus.Drawing.Shapes.InvTriangle: invtriangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape InvTriangle u
- Wumpus.Drawing.Shapes.Parallelogram: parallelogram :: (Real u, Floating u, FromPtSize u) => u -> u -> Radian -> Shape u (Parallelogram u)
+ Wumpus.Drawing.Shapes.Parallelogram: parallelogram :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Shape Parallelogram u
- Wumpus.Drawing.Shapes.Parallelogram: zparallelogram :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (Parallelogram u)
+ Wumpus.Drawing.Shapes.Parallelogram: zparallelogram :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Parallelogram u
- Wumpus.Drawing.Shapes.Rectangle: rectangle :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (Rectangle u)
+ Wumpus.Drawing.Shapes.Rectangle: rectangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Rectangle u
- Wumpus.Drawing.Shapes.Semicircle: semicircle :: (Real u, Floating u, FromPtSize u) => u -> Shape u (Semicircle u)
+ Wumpus.Drawing.Shapes.Semicircle: semicircle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> Shape Semicircle u
- Wumpus.Drawing.Shapes.Semiellipse: semiellipse :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: semiellipse :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Semiellipse u
- Wumpus.Drawing.Shapes.Trapezium: trapezium :: (Real u, Floating u, FromPtSize u) => u -> u -> Radian -> Radian -> Shape u (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Radian -> Shape Trapezium u
- Wumpus.Drawing.Shapes.Trapezium: ztrapezium :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (Trapezium u)
+ Wumpus.Drawing.Shapes.Trapezium: ztrapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Trapezium u
- Wumpus.Drawing.Shapes.Triangle: triangle :: (Real u, Floating u, FromPtSize u) => u -> u -> Shape u (Triangle u)
+ Wumpus.Drawing.Shapes.Triangle: triangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Triangle u
Files
- demo/ArrowCircuit.hs +50/−63
- demo/Arrowheads.hs +69/−56
- demo/Automata.hs +107/−0
- demo/ClipPic.hs +59/−54
- demo/ColourCharts.hs +8/−10
- demo/Connectors.hs +58/−44
- demo/DotPic.hs +20/−49
- demo/FeatureModel.hs +28/−50
- demo/FontLoaderUtils.hs +0/−95
- demo/FontPic.hs +27/−23
- demo/LeftRightText.hs +49/−85
- demo/PetriNet.hs +89/−111
- demo/SampleShapes.hs +56/−73
- demo/SingleChar.hs +70/−0
- demo/SingleLine.hs +20/−40
- demo/Symbols.hs +10/−11
- demo/TableChains.hs +5/−29
- src/Wumpus/Drawing/Arrows.hs +0/−28
- src/Wumpus/Drawing/Arrows/Connectors.hs +0/−104
- src/Wumpus/Drawing/Arrows/Tips.hs +0/−515
- src/Wumpus/Drawing/Chains.hs +0/−29
- src/Wumpus/Drawing/Chains/Base.hs +0/−259
- src/Wumpus/Drawing/Chains/Derived.hs +0/−155
- src/Wumpus/Drawing/Connectors.hs +31/−0
- src/Wumpus/Drawing/Connectors/Arrowheads.hs +464/−0
- src/Wumpus/Drawing/Connectors/Base.hs +172/−0
- src/Wumpus/Drawing/Connectors/BoxConnectors.hs +65/−0
- src/Wumpus/Drawing/Connectors/ConnectorPaths.hs +499/−0
- src/Wumpus/Drawing/Connectors/Loop.hs +86/−0
- src/Wumpus/Drawing/Dots/AnchorDots.hs +33/−31
- src/Wumpus/Drawing/Dots/Marks.hs +56/−57
- src/Wumpus/Drawing/Extras/Axes.hs +49/−0
- src/Wumpus/Drawing/Extras/Grids.hs +229/−0
- src/Wumpus/Drawing/Extras/Turtle/TurtleClass.hs +91/−0
- src/Wumpus/Drawing/Extras/Turtle/TurtleMonad.hs +132/−0
- src/Wumpus/Drawing/Grids.hs +0/−67
- src/Wumpus/Drawing/Paths.hs +0/−32
- src/Wumpus/Drawing/Paths/Absolute.hs +28/−0
- src/Wumpus/Drawing/Paths/Base.hs +0/−585
- src/Wumpus/Drawing/Paths/Base/AbsBuilder.hs +561/−0
- src/Wumpus/Drawing/Paths/Base/AbsPath.hs +801/−0
- src/Wumpus/Drawing/Paths/Base/BuildCommon.hs +129/−0
- src/Wumpus/Drawing/Paths/Base/RelBuilder.hs +520/−0
- src/Wumpus/Drawing/Paths/Base/RelPath.hs +269/−0
- src/Wumpus/Drawing/Paths/Connectors.hs +0/−253
- src/Wumpus/Drawing/Paths/ControlPoints.hs +0/−189
- src/Wumpus/Drawing/Paths/MonadicConstruction.hs +0/−160
- src/Wumpus/Drawing/Paths/Relative.hs +27/−0
- src/Wumpus/Drawing/Paths/Vamps.hs +56/−0
- src/Wumpus/Drawing/Shapes/Base.hs +108/−83
- src/Wumpus/Drawing/Shapes/Circle.hs +22/−21
- src/Wumpus/Drawing/Shapes/Diamond.hs +36/−30
- src/Wumpus/Drawing/Shapes/Ellipse.hs +41/−30
- src/Wumpus/Drawing/Shapes/InvSemicircle.hs +32/−27
- src/Wumpus/Drawing/Shapes/InvSemiellipse.hs +32/−28
- src/Wumpus/Drawing/Shapes/InvTriangle.hs +39/−35
- src/Wumpus/Drawing/Shapes/Parallelogram.hs +50/−39
- src/Wumpus/Drawing/Shapes/Rectangle.hs +38/−32
- src/Wumpus/Drawing/Shapes/Semicircle.hs +41/−29
- src/Wumpus/Drawing/Shapes/Semiellipse.hs +36/−31
- src/Wumpus/Drawing/Shapes/Trapezium.hs +43/−41
- src/Wumpus/Drawing/Shapes/Triangle.hs +51/−39
- src/Wumpus/Drawing/Text/Base.hs +0/−166
- src/Wumpus/Drawing/Text/Base/Common.hs +143/−0
- src/Wumpus/Drawing/Text/Base/DocTextZero.hs +453/−0
- src/Wumpus/Drawing/Text/Base/Label.hs +133/−0
- src/Wumpus/Drawing/Text/Base/PosChar.hs +73/−0
- src/Wumpus/Drawing/Text/Base/RotTextZero.hs +375/−0
- src/Wumpus/Drawing/Text/CatText.hs +0/−207
- src/Wumpus/Drawing/Text/DirectionZero.hs +27/−0
- src/Wumpus/Drawing/Text/LRText.hs +0/−292
- src/Wumpus/Drawing/Text/SafeFonts.hs +0/−167
- src/Wumpus/Drawing/Text/StandardFontDefs.hs +323/−0
- src/Wumpus/Drawing/Turtle/TurtleClass.hs +0/−91
- src/Wumpus/Drawing/Turtle/TurtleMonad.hs +0/−139
- src/Wumpus/Drawing/VersionNumber.hs +3/−3
- wumpus-drawing.cabal +48/−25
demo/ArrowCircuit.hs view
@@ -5,60 +5,42 @@ -- Acknowledgment - the Arrow diagram is taken from Ross -- Paterson\'s slides /Arrows and Computation/. +-- NOTE - this example now rather out-of-date. Wumpus-Drawing has +-- some new features to make node/connector drawing a bit easier. module ArrowCircuit where -import Wumpus.Drawing.Arrows-import Wumpus.Drawing.Paths +import Wumpus.Drawing.Connectors import Wumpus.Drawing.Shapes-import Wumpus.Drawing.Text.LRText-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core -import FontLoaderUtils --import Data.AffineSpace+import Data.AffineSpace -- package: vector-space import System.Directory main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/"- maybe gs_failk makeGSPicture $ mb_gs- maybe afm_failk makeAfmPicture $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."--makeGSPicture :: FilePath -> IO ()-makeGSPicture font_dir = do - putStrLn "Using GhostScript metrics..."- (base_metrics, msgs) <- loadGSMetrics font_dir ["Times-Roman", "Times-Italic"]- mapM_ putStrLn msgs- let pic1 = runCtxPictureU (makeCtx base_metrics) circuit_pic- writeEPS "./out/arrow_circuit01.eps" pic1- writeSVG "./out/arrow_circuit01.svg" pic1 +main = simpleFontLoader main1 >> return () -makeAfmPicture :: FilePath -> IO ()-makeAfmPicture font_dir = do - putStrLn "Using AFM 4.1 metrics..."- (base_metrics, msgs) <- loadAfmMetrics font_dir ["Times-Roman", "Times-Italic"]- mapM_ putStrLn msgs+main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Right times_roman_family ]+ printLoadErrors base_metrics let pic1 = runCtxPictureU (makeCtx base_metrics) circuit_pic- writeEPS "./out/arrow_circuit02.eps" pic1- writeSVG "./out/arrow_circuit02.svg" pic1 + writeEPS "./out/arrow_circuit.eps" pic1+ writeSVG "./out/arrow_circuit.svg" pic1 -makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fontFace times_roman . metricsContext 11+makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font times_roman . metricsContext 11 @@ -69,8 +51,11 @@ -- Note `at` currently does not work for Shapes. -circuit_pic :: CtxPicture Double -circuit_pic = drawTracing $ do+circuit_pic :: CtxPicture+circuit_pic = drawTracing body ++body :: TraceDrawing Double ()+body = do a1 <- drawi $ rrectangle 12 66 30 `at` P2 0 72 atext a1 "CONST 0" a2 <- drawi $ (strokedShape $ circle 16) `at` P2 120 60@@ -79,44 +64,46 @@ atext a3 "+1" a4 <- drawi $ (strokedShape $ rectangle 66 30) `at` P2 120 0 atext a4 "DELAY 0"- connWith connLine (east a1) (east a1 .+^ hvec 76)- connWith connLine (east a2) (east a2 .+^ hvec 180)- connWith connLine (north a2 .+^ vvec 40) (north a2)- connWith connLine (north a3 .+^ vvec 16) (north a3) - connWith connRightVH (south a3) (east a4)- connWith (connRightHVH (-30)) (west a4) (southwest a2)+ connWith connline (east a1) ((.+^ hvec 76) $ east a1)+ connWith connline (east a2) ((.+^ hvec 180) $ east a2)+ connWith connline ((.+^ vvec 40) $ north a2) (north a2)+ connWith connline ((.+^ vvec 16) $ north a3) (north a3) + connWith connaright (south a3) (east a4)+ connWith connabar (west a4) (southwest a2) ptext (P2 40 10) "next" ptext (P2 152 100) "reset" ptext (P2 252 72) "output" return () -+ -- Note - need a variant of /bar/ that draws UDLR only. -connWith :: ( TraceM m, DrawingCtxM m, u ~ MonUnit m- , Real u, Floating u, FromPtSize u ) - => ConnectorPath u -> Point2 u -> Point2 u -> m ()-connWith con p0 p1 = localize doublesize $ - drawi_ $ apply2R2 (rightArrow tri45 con) p0 p1+connWith :: ( TraceM m, DrawingCtxM m, u ~ MonUnit (m ())+ , Real u, Floating u, InterpretUnit u ) + => Connector u -> Anchor u -> Anchor u -> m ()+connWith con a0 a1 = localize double_point_size $ + drawc a0 a1 (rightArrow tri45 con) -atext :: ( CenterAnchor t, DUnit t ~ u- , Real u, Floating u, FromPtSize u- , TraceM m, DrawingCtxM m, u ~ MonUnit m )- => t -> String -> m ()-atext ancr ss = let pt = center ancr in- drawi_ $ textAlignCenter ss `at` pt+atext :: ( CenterAnchor (t u)+ , Real u, Floating u, InterpretUnit u+ , TraceM m, DrawingCtxM m, u ~ MonUnit (m ()), u ~ DUnit (t u) )+ => t u -> String -> m ()+atext ancr ss = + draw $ ccTextline ss `at` (center ancr) -ptext :: ( Real u, Floating u, FromPtSize u- , TraceM m, DrawingCtxM m, u ~ MonUnit m )+ptext :: ( Real u, Floating u, InterpretUnit u+ , TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) => Point2 u -> String -> m ()-ptext pt ss = localize (fontAttr times_italic 14) $ - drawi_ $ textAlignCenter ss `at` pt+ptext pt ss = localize (font_attr times_italic 14) $ + draw $ ccTextline ss `at` pt -- Note - return type is a LocImage not a shape... ---rrectangle :: (Real u, Floating u, FromPtSize u) - => u -> u -> u -> LocImage u (Rectangle u)-rrectangle r w h = - localize (roundCornerFactor $ realToFrac r) $ strokedShape (rectangle w h)+rrectangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => Double -> u -> u -> LocImage u (Rectangle u)+rrectangle _r w h = strokedShape (rectangle w h)+ -- This should have round corners but they are currently+ -- disabled pending a re-think. + {- localize (round_corner_factor r) $ -}
demo/Arrowheads.hs view
@@ -2,84 +2,97 @@ module Arrowheads where --import Wumpus.Drawing.Arrows-import Wumpus.Drawing.Chains import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Paths hiding ( length )+import Wumpus.Drawing.Connectors+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs + import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace -- package: vector-space import System.Directory main :: IO ()-main = do - createDirectoryIfMissing True "./out/"- let pic1 = runCtxPictureU std_ctx arrow_drawing- writeEPS "./out/arrowheads01.eps" pic1- writeSVG "./out/arrowheads01.svg" pic1+main = simpleFontLoader main1 >> return () -arrow_drawing :: CtxPicture Double-arrow_drawing = drawTracing $ localize (dashPattern unit_dash_pattern) - $ tableGraphic arrtable+main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left helvetica ]+ printLoadErrors base_metrics+ let pic1 = runCtxPictureU (makeCtx base_metrics) arrow_drawing+ writeEPS "./out/arrowheads.eps" pic1+ writeSVG "./out/arrowheads.svg" pic1 -arrtable :: [(Arrowhead Double, Arrowhead Double)]++makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font helvetica . metricsContext 14++++arrow_drawing :: CtxPicture+arrow_drawing = + drawTracing $ localize dotted_line $ tableGraphic arrtable++arrtable :: [(String, ArrowTip Double)] arrtable = - [ (tri90, tri90)- , (tri60, tri60)- , (tri45, tri45)- , (otri90, otri90)- , (otri60, otri60)- , (otri45, otri45)- , (revtri90, revtri90)- , (revtri60, revtri60)- , (revtri45, revtri45)- , (orevtri90, orevtri90)- , (orevtri60, orevtri60)- , (orevtri45, orevtri45)- , (barb90, barb90)- , (barb60, barb60)- , (barb45, barb45)- , (revbarb90, revbarb90)- , (revbarb60, revbarb60)- , (revbarb45, revbarb45)- , (perp, perp)- , (bracket, bracket)- , (diskTip, diskTip)- , (odiskTip, odiskTip)- , (squareTip, squareTip)- , (osquareTip, osquareTip)- , (diamondTip, diamondTip)- , (odiamondTip, odiamondTip)- , (curveTip, curveTip)- , (revcurveTip, revcurveTip)+ [ ("tri90", tri90)+ , ("tri60", tri60)+ , ("tri45", tri45) + , ("otri90", otri90)+ , ("otri60", otri60)+ , ("otri45", otri45)+ , ("revtri90", revtri90)+ , ("revtri60", revtri60)+ , ("revtri45", revtri45)+ , ("orevtri90", orevtri90)+ , ("orevtri60", orevtri60)+ , ("orevtri45", orevtri45)+ , ("barb90", barb90)+ , ("barb60", barb60)+ , ("barb45", barb45)+ , ("revbarb90", revbarb90)+ , ("revbarb60", revbarb60)+ , ("revbarb45", revbarb45)+ , ("perp", perp)+ , ("bracket", bracket)+ , ("diskTip", diskTip)+ , ("odiskTip", odiskTip)+ , ("squareTip", squareTip)+ , ("osquareTip", osquareTip)+ , ("diamondTip", diamondTip)+ , ("odiamondTip", odiamondTip)+ , ("diamondWideTip", diamondWideTip)+ , ("odiamondWideTip", odiamondWideTip)+ , ("curveTip", curveTip)+ , ("revcurveTip", revcurveTip) ] -tableGraphic :: (Real u, Floating u, FromPtSize u) - => [(Arrowhead u, Arrowhead u)] -> TraceDrawing u ()+++tableGraphic :: [(String, ArrowTip Double)] -> TraceDrawing Double () tableGraphic tips = - draw $ unchainZipWith emptyLocGraphic makeArrowDrawing tips chn `at` start+ drawl start $ chain_ chn_alg (map makeArrowDrawing tips) where- chn = tableDown 20 (120,24)- start = P2 0 480+ chn_alg = tableDown 18 (180,24)+ start = P2 0 480 std_ctx :: DrawingContext-std_ctx = fillColour peru $ standardContext 18+std_ctx = fill_colour peru $ standardContext 18 -makeArrowDrawing :: (Real u, Floating u, FromPtSize u) - => (Arrowhead u, Arrowhead u) -> LocGraphic u-makeArrowDrawing (arrl,arrr) = - promoteR1 $ \p0 -> forget $- connect (leftRightArrow arrl arrr connLine) p0 (mkP1 p0)+makeArrowDrawing :: (String, ArrowTip Double) -> LocGraphic Double+makeArrowDrawing (name, utip) = aconn `oplus` lbl where- mkP1 = (.+^ hvec 100)- -- forget needs a better name, then adding to Wumpus-Basic.- forget = fmap (replaceL uNil) + aconn = promoteR1 $ \pt -> fmap ignoreAns $ + connect (uniformArrow utip connline) pt (displaceH 60 pt)++ lbl = promoteR1 $ \pt -> fmap ignoreAns $ + atStartAddr (textline name) (displaceH 66 pt) WW
+ demo/Automata.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++module Automata where++import Wumpus.Drawing.Connectors+import Wumpus.Drawing.Paths.Absolute+import Wumpus.Drawing.Shapes+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs+import Wumpus.Drawing.Text.Base.Label+++import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Basic.System.FontLoader++import Wumpus.Core -- package: wumpus-core++import System.Directory++++main :: IO ()+main = simpleFontLoader main1 >> return ()++main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Right times_roman_family ]+ printLoadErrors base_metrics+ let pic1 = runCtxPictureU (makeCtx base_metrics) automata+ writeEPS "./out/automata.eps" pic1+ writeSVG "./out/automata.svg" pic1 +++makeCtx :: FontLoadResult -> DrawingContext+makeCtx = + snap_grid_factors 60.0 60.0 . set_font times_roman . metricsContext 14+++automata :: CtxPicture+automata = udrawTracing (0::Double) $ do+ q0 <- nodei (8,0) $ state "q0"+ q1 <- drawi $ state "q1" `mat` above_right_of q0+ q2 <- drawi $ state "q2" `mat` below_right_of q0+ q3 <- drawi $ stopstate "q3" `mat` below_right_of q1++ s0 <- evalQuery $ left_of q0++ draw $ label_midway_of SE (textline "0") $ straightconn q0 q1+ draw $ label_midway_of SS (textline "0") $ arrloop (center q1) (north q1) + draw $ label_midway_of SW (textline "1") $ straightconn q1 q3+ draw $ label_midway_of NE (textline "1") $ straightconn q0 q2+ draw $ label_midway_of NW (textline "0") $ straightconn q2 q3+ draw $ label_midway_of NN (textline "1") $ arrloop (center q2) (south q2) + draw $ label_atstart_of EE (textline "start") $ astraightconn s0 (west q0) ++ return ()+++infixr 1 `mat`++mat :: LocImage u a -> Query (Point2 u) -> Image u a+mat img mq = mq >>= \pt -> img `at` pt++state :: String -> DLocImage DCircle+state ss = + localize (set_font times_italic) $ + label_center_of (textline ss) $ strokedShape $ circle 20+++stopstate :: String -> DLocImage DCircle +stopstate ss = + localize (set_font times_italic) $ + label_center_of (textline ss) $ dblStrokedShape $ circle 20++++straightconn :: ( Real u, Floating u, InterpretUnit u+ , u ~ DUnit a, u ~ DUnit b+ , CenterAnchor a, RadialAnchor a+ , CenterAnchor b, RadialAnchor b+ )+ => a -> b -> Image u (AbsPath u)+straightconn a b =+ let (p0,p1) = radialConnectorPoints a b+ in connect (rightArrow tri45 connline) p0 p1+++astraightconn :: ( Real u, Floating u, InterpretUnit u)+ => Anchor u -> Anchor u -> Image u (AbsPath u)+astraightconn p0 p1 = connect (rightArrow tri45 connline) p0 p1+++-- Note - there is a problem with @rightArrow@ as @loop@+-- manufactures the start and end points...+--+arrloop :: ( Real u, Floating u, InterpretUnit u, Tolerance u)+ => Anchor u -> Anchor u -> Image u (AbsPath u)+arrloop p0 p1 = connect (rightArrow barb45 loop) p0 p1+++++++
demo/ClipPic.hs view
@@ -12,11 +12,9 @@ module ClipPic where -import Wumpus.Drawing.Chains import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Paths-import Wumpus.Drawing.Paths.MonadicConstruction-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Paths.Absolute+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic @@ -30,76 +28,83 @@ main :: IO () main = do createDirectoryIfMissing True "./out/"- let pic = runCtxPictureU pic_drawing_ctx big_pic- writeEPS "./out/clip_pic.eps" pic- writeSVG "./out/clip_pic.svg" pic+ let pic1 = runCtxPictureU std_ctx $ top_pic `vconcat` clip_pic+ writeEPS "./out/clip_pic.eps" pic1+ writeSVG "./out/clip_pic.svg" pic1 -pic_drawing_ctx :: DrawingContext-pic_drawing_ctx = standardContext 14+std_ctx :: DrawingContext+std_ctx = standardContext 14 -big_pic :: DCtxPicture-big_pic = pic1 `cxpDown` oconcat cpic1 [cpic2, cpic3, cpic4]--fillPath :: Num u => Path u -> Graphic u-fillPath = filledPath . toPrimPath+top_pic :: CtxPicture+top_pic = drawTracing $ localize (fill_colour medium_slate_blue) $ do+ draw $ toPrimPath path01 >>= filledPath+ draw $ localize (fill_colour powder_blue) $ toPrimPath path02 >>= filledPath+ draw $ toPrimPath path03 >>= filledPath+ draw $ toPrimPath path04 >>= filledPath -pic1 :: DCtxPicture-pic1 = drawTracing $ localize (fillColour medium_slate_blue) $ do- draw $ fillPath path01- draw $ localize (fillColour powder_blue) $ fillPath path02- draw $ fillPath path03- draw $ fillPath path04+clip_pic :: CtxPicture+clip_pic = drawTracing $ do+ mapM_ draw $ [ clip1, clip2, clip3, clip4 ] -background :: RGBi -> DCtxPicture-background rgb = drawTracing $ - draw $ localize (strokeColour rgb) $ ihh `at` P2 0 288+background :: RGBi -> Graphic Double+background rgb = + fmap ignoreAns $ localize (text_colour rgb) $ ihh `at` P2 0 288 where- ihh = unchain 112 emptyLocGraphic iheartHaskell $ tableDown 18 (86,16)+ ihh = chain (tableDown 18 (86,16)) (replicate 112 iheartHaskell) -cpic1 :: DCtxPicture -cpic1 = clipCtxPicture (toPrimPath path01) (background black)+-- Wumpus-Basic needs a clip function, but is this the most +-- satisfactory definition?+--+clipGraphic :: PrimPath -> Graphic u -> Graphic u +clipGraphic cp = fmap (clipObject cp)+++clip1 :: Graphic Double+clip1 = toPrimPath path01 >>= \pp -> clipGraphic pp (background black) -cpic2 :: DCtxPicture-cpic2 = clipCtxPicture (toPrimPath path02) (background medium_violet_red)+clip2 :: Graphic Double+clip2 = toPrimPath path02 >>= \pp -> clipGraphic pp (background medium_violet_red) -cpic3 :: DCtxPicture -cpic3 = clipCtxPicture (toPrimPath path03) (background black)+clip3 :: Graphic Double+clip3 = toPrimPath path03 >>= \pp -> clipGraphic pp (background black) -cpic4 :: DCtxPicture -cpic4 = clipCtxPicture (toPrimPath path04) (background black)+clip4 :: Graphic Double+clip4 = toPrimPath path04 >>= \pp -> clipGraphic pp (background black) -iheartHaskell :: Num u => FromPtSize u => LocGraphic u+iheartHaskell :: LocGraphic Double iheartHaskell = promoteR1 $ \pt -> - let body = textline "I Haskell" `at` pt- heart = localize (fontFace symbol) $ - textline "&heart;" `at` (pt .+^ hvec 7)+ let body = plainTextLine "I Haskell" `at` pt+ heart = localize (set_font symbol) $ + plainTextLine "&heart;" `at` (pt .+^ hvec 7) in body `oplus` heart -path01 :: Floating u => Path u-path01 = execPath zeroPt $ hline 80 >> rlineto (vec 112 160) - >> rlineto (vec (-112) 160)- >> hline (-80)- >> rlineto (vec 112 (-160))- >> rlineto (vec (-112) (-160))+path01 :: AbsPath Double+path01 = evalAbsBuild zeroPt $ hline 80 + >> relline (vec 112 160) + >> relline (vec (-112) 160)+ >> hline (-80)+ >> relline (vec 112 (-160))+ >> relline (vec (-112) (-160)) -path02 :: Floating u => Path u-path02 = execPath (P2 112 0) $ hline 80 >> rlineto (vec 72 112)- >> rlineto (vec 72 (-112))- >> hline 80- >> rlineto (vec (-224) 320)- >> hline (-80)- >> rlineto (vec 112 (-160))- >> rlineto (vec (-112) (-160))+path02 :: AbsPath Double+path02 = evalAbsBuild (P2 112 0) $ hline 80 + >> relline (vec 72 112)+ >> relline (vec 72 (-112))+ >> hline 80+ >> relline (vec (-224) 320)+ >> hline (-80)+ >> relline (vec 112 (-160))+ >> relline (vec (-112) (-160)) -path03 :: Floating u => Path u-path03 = execPath (P2 384 96) $ hline 96 >> vline 56 >> hline (-136) +path03 :: AbsPath Double+path03 = evalAbsBuild (P2 384 96) $ hline 96 >> vline 56 >> hline (-136) -path04 :: Floating u => Path u-path04 = execPath (P2 328 192) $ hline 152 >> vline 56 >> hline (-192) +path04 :: AbsPath Double+path04 = evalAbsBuild (P2 328 192) $ hline 152 >> vline 56 >> hline (-192)
demo/ColourCharts.hs view
@@ -4,7 +4,6 @@ import ColourChartUtils -import Wumpus.Drawing.Chains import Wumpus.Basic.Kernel -- package: wumpus-basic @@ -22,28 +21,27 @@ writeSVG "./out/SVGcolours.svg" svg_pic -- let x11_p = runCtxPictureU draw_ctx x11_portrait- writeEPS "./out/X11colours.eps" $ uniformScale 0.75 x11_p+ writeEPS "./out/X11colours.eps" $ scale 0.75 0.75 x11_p let x11_l = runCtxPictureU draw_ctx x11_landscape writeSVG "./out/X11colours.svg" x11_l draw_ctx :: DrawingContext draw_ctx = (standardContext 9) -svg :: CtxPicture Double+svg :: CtxPicture svg = makeDrawing 52 all_svg_colours -x11_landscape :: CtxPicture Double+x11_landscape :: CtxPicture x11_landscape = makeDrawing 52 all_x11_colours -x11_portrait :: CtxPicture Double+x11_portrait :: CtxPicture x11_portrait = makeDrawing 72 all_x11_colours -makeDrawing :: Int -> [(String,RGBi)] -> DCtxPicture+makeDrawing :: Int -> [(String,RGBi)] -> CtxPicture makeDrawing row_count xs = drawTracing $ tableGraphic row_count xs tableGraphic :: Int -> [(String,RGBi)] -> TraceDrawing Double ()-tableGraphic row_count xs = - draw $ unchainZip emptyLocGraphic gs chn `at` pt+tableGraphic row_count xs = draw $ (chain_ chn gs) `at` pt where chn = tableDown row_count (152,11) pt = displaceV (fromIntegral $ 11 * row_count) zeroPt @@ -51,9 +49,9 @@ colourSample :: String -> RGBi -> LocGraphic Double-colourSample name rgb = localize (fillColour rgb) $ +colourSample name rgb = localize (fill_colour rgb) $ promoteR1 $ \pt -> oplus (borderedRectangle 15 10 `at` pt)- (textline name `at` displace 20 2 pt)+ (plainTextLine name `at` displace 20 2 pt)
demo/Connectors.hs view
@@ -2,73 +2,87 @@ module Connectors where --import Wumpus.Drawing.Arrows-import Wumpus.Drawing.Chains import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Paths hiding ( length )+import Wumpus.Drawing.Connectors+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core ++ import System.Directory + main :: IO ()-main = do - createDirectoryIfMissing True "./out/"- let pic1 = runCtxPictureU std_ctx conn_pic- writeEPS "./out/connectors01.eps" pic1- writeSVG "./out/connectors01.svg" pic1+main = simpleFontLoader main1 >> return () +main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left helvetica ]+ printLoadErrors base_metrics+ let pic1 = runCtxPictureU (makeCtx base_metrics) conn_pic+ writeEPS "./out/connectors.eps" pic1+ writeSVG "./out/connectors.svg" pic1 + +makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font helvetica . metricsContext 11 -conn_pic :: CtxPicture Double-conn_pic = drawTracing $ tableGraphic $ conntable+conn_pic :: CtxPicture +conn_pic = drawTracing $ localize (dest_arm_len (0.75::Em))+ $ tableGraphic conntable -conntable :: [ConnectorPath Double]+conntable :: [(String, Connector Double)] conntable = - [ connLine- , connRightVH- , connRightHV- , connRightVHV 15- , connRightHVH 15- , connIsosceles 25- , connIsosceles (-25)- , connIsosceles2 15- , connIsosceles2 (-15)- , connLightningBolt 15- , connLightningBolt (-15)- , connIsoscelesCurve 25- , connIsoscelesCurve (-25)- , connSquareCurve- , connUSquareCurve- , connTrapezoidCurve 40 0.5- , connTrapezoidCurve (-40) 0.5- , connZSquareCurve - , connUZSquareCurve + [ ("connline", connline)+ , ("connarc", connarc)+ , ("connhdiagh", connhdiagh)+ , ("connvdiagv", connvdiagv)+ , ("conndiagh", conndiagh)+ , ("conndiagv", conndiagv)+ , ("connhdiag", connhdiag)+ , ("connvdiag", connvdiag)+ , ("connabar", connabar)+ , ("connbbar", connbbar)+ , ("connaright", connaright)+ , ("connbright", connbright)+ , ("connhrr", connhrr)+ , ("connrrh", connrrh)+ , ("connvrr", connvrr)+ , ("connrrv", connrrv)+ , ("connaloop", connaloop)+ , ("connbloop", connbloop)+ , ("connhbezier", connhbezier)+ , ("connvbezier", connvbezier) ] -tableGraphic :: (Real u, Floating u, FromPtSize u) - => [ConnectorPath u] -> TraceDrawing u ()+tableGraphic :: [(String, Connector Double)] -> TraceDrawing Double () tableGraphic conns = - draw $ unchainZipWith emptyLocGraphic makeConnDrawing conns chn `at` start+ draw $ chain_ chn_alg (map makeConnDrawing conns) `at` start where- chn = tableDown 10 (120,52) - start = P2 0 520 + chn_alg = tableDown 8 (180,64) + start = P2 0 520 std_ctx :: DrawingContext-std_ctx = fillColour peru $ standardContext 18+std_ctx = fill_colour peru $ standardContext 18 -makeConnDrawing :: (Real u, Floating u, FromPtSize u) - => ConnectorPath u -> LocGraphic u-makeConnDrawing conn = - promoteR1 $ \p0 -> fmap (replaceL uNil) $ - connect (uniformArrow curveTip conn) p0 (mkP1 p0)+makeConnDrawing :: (String, Connector Double) -> DLocGraphic +makeConnDrawing (ss,conn) = + promoteR1 $ \p0 -> fn p0 (displace 60 40 p0) where- mkP1 = displace 100 40- + fn p0 p1 = disk p0 `oplus` disk p1 `oplus` dcon p0 p1 `oplus` lbl p1++ disk pt = localize (fill_colour red) $ filledDisk 2 `at` pt+ dcon p0 p1 = fmap ignoreAns $ connect (uniformArrow curveTip conn) p0 p1++ lbl pt = fmap ignoreAns $ atStartAddr (textline ss) (displaceH 10 pt) WW+
demo/DotPic.hs view
@@ -2,18 +2,12 @@ module DotPic where ---import Wumpus.Drawing.Chains import Wumpus.Drawing.Colour.SVGColours import Wumpus.Drawing.Dots.AnchorDots-import Wumpus.Drawing.Text.SafeFonts--import FontLoaderUtils+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core @@ -21,45 +15,25 @@ import System.Directory -- main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/"- maybe gs_failk makeGSPicture $ mb_gs- maybe afm_failk makeAfmPicture $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."-+main = simpleFontLoader main1 >> return () -makeGSPicture :: FilePath -> IO ()-makeGSPicture font_dir = do - putStrLn "Using GhostScript metrics..."- (base_metrics, msgs) <- loadGSMetrics font_dir ["Helvetica"]- mapM_ putStrLn msgs+main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left helvetica ]+ printLoadErrors base_metrics let pic1 = runCtxPictureU (makeCtx base_metrics) dot_pic- writeEPS "./out/dot_pic01_gs.eps" pic1- writeSVG "./out/dot_pic01_gs.svg" pic1+ writeEPS "./out/dot_pic.eps" pic1+ writeSVG "./out/dot_pic.svg" pic1 --makeAfmPicture :: FilePath -> IO ()-makeAfmPicture font_dir = do - putStrLn "Using AFM 4.1 metrics..."- (base_metrics, msgs) <- loadAfmMetrics font_dir ["Helvetica"]- mapM_ putStrLn msgs- let pic1 = runCtxPictureU (makeCtx base_metrics) dot_pic- writeEPS "./out/dot_pic01_afm.eps" pic1- writeSVG "./out/dot_pic01_afm.svg" pic1- -makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fillColour peru . fontFace helvetica . metricsContext 24+makeCtx :: FontLoadResult -> DrawingContext+makeCtx = fill_colour peru . set_font helvetica . metricsContext 24 -dot_pic :: CtxPicture Double+dot_pic :: CtxPicture dot_pic = drawTracing $ tableGraphic $ [ dotHLine , dotVLine@@ -82,13 +56,12 @@ ] -tableGraphic :: (Real u, Floating u, FromPtSize u) - => [DotLocImage u] -> TraceDrawing u ()+tableGraphic :: [DotLocImage Double] -> TraceDrawing Double () tableGraphic imgs = - draw $ unchainZipWith emptyLocGraphic makeDotDrawing imgs chn `at` pt+ draw $ chain_ chn_alg (map makeDotDrawing imgs) `at` pt where row_count = length imgs- chn = tableDown row_count (1,36)+ chn_alg = tableDown row_count (1,36) pt = displaceV (fromIntegral $ 36 * row_count) zeroPt @@ -96,20 +69,18 @@ -- This is a bit convoluted - maybe there should be chain-run -- functions for TraceDrawings as well as LocGraphics? -makeDotDrawing :: (Real u, Floating u, FromPtSize u) +makeDotDrawing :: (Real u, Floating u, InterpretUnit u) => DotLocImage u -> LocGraphic u makeDotDrawing dotF = promoteR1 $ \pt -> let all_points = map (pt .+^) displacements in oconcat (dashline all_points)- (map (\p1 -> ignoreL $ dotF `at` p1) all_points)+ (map (\p1 -> fmap ignoreAns $ dotF `at` p1) all_points) where- dashline = \ps -> localize attrUpd (openStroke $ vertexPath ps)+ dashline = \ps -> localize attrUpd $ vertexPP ps >>= openStroke attrUpd :: DrawingContext -> DrawingContext- attrUpd = dashPattern (evenDashes 1) . strokeColour cadet_blue-- ignoreL = fmap (replaceL uNil) + attrUpd = packed_dotted . stroke_colour cadet_blue displacements :: Num u => [Vec2 u] displacements = [V2 0 0, V2 64 20, V2 128 0, V2 192 20]
demo/FeatureModel.hs view
@@ -1,66 +1,45 @@-{-# LANGUAGE TypeFamilies #-} {-# OPTIONS -Wall #-} module FeatureModel where -import Wumpus.Drawing.Arrows-import Wumpus.Drawing.Paths +import Wumpus.Drawing.Connectors+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes-import Wumpus.Drawing.Text.LRText-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core -import FontLoaderUtils-- import System.Directory main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/"- maybe gs_failk makeGSPicture $ mb_gs- maybe afm_failk makeAfmPicture $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."+main = simpleFontLoader main1 >> return () -makeGSPicture :: FilePath -> IO ()-makeGSPicture font_dir = do - putStrLn "Using GhostScript metrics..."- (base_metrics, msgs) <- loadGSMetrics font_dir ["Courier-Bold"]- mapM_ putStrLn msgs+main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left courier_bold ]+ printLoadErrors base_metrics let pic1 = runCtxPictureU (makeCtx base_metrics) feature_model writeEPS "./out/feature_model01.eps" pic1 writeSVG "./out/feature_model01.svg" pic1 -makeAfmPicture :: FilePath -> IO ()-makeAfmPicture font_dir = do - putStrLn "Using AFM 4.1 metrics..."- (base_metrics, msgs) <- loadAfmMetrics font_dir ["Courier-Bold"]- mapM_ putStrLn msgs- let pic1 = runCtxPictureU (makeCtx base_metrics) feature_model - writeEPS "./out/feature_model02.eps" pic1- writeSVG "./out/feature_model02.svg" pic1 --makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fontFace courier_bold . metricsContext 18+makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font courier_bold . metricsContext 18 -- Note - I haven't worked out how to do @alternative@, @or@ and -- @repetitions@ yet. -- -feature_model :: CtxPicture Double -feature_model = drawTracing $ do+feature_model :: CtxPicture+feature_model = udrawTracing (0::Double) $ do lea <- widebox "e" $ P2 150 160 lra <- widebox "r" $ P2 60 80 lsa <- widebox "s" $ P2 240 80@@ -91,46 +70,45 @@ -- Note - ctrCenterLine does not seem to be working well... -makeBox :: (Real u, Floating u, FromPtSize u) +makeBox :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> String -> Point2 u -> TraceDrawing u (Box u) makeBox w ss pt = do a <- drawi $ (strokedShape $ rectangle w 20) `at` pt- drawi_ $ textAlignCenter ss `at` center a- -- draw $ filledDisk 2 `at` center a+ drawl (center a) $ ccTextline ss return a -box :: (Real u, Floating u, FromPtSize u) +box :: (Real u, Floating u, InterpretUnit u, Tolerance u) => String -> Point2 u -> TraceDrawing u (Box u) box = makeBox 40 -widebox :: (Real u, Floating u, FromPtSize u) +widebox :: (Real u, Floating u, InterpretUnit u, Tolerance u) => String -> Point2 u -> TraceDrawing u (Box u) widebox = makeBox 60 -connWith :: ( Real u, Floating u, FromPtSize u ) - => Arrowhead u -> Box u -> Box u -> TraceDrawing u (Path u)+connWith :: ( Real u, Floating u, InterpretUnit u ) + => ArrowTip u -> Box u -> Box u -> TraceDrawing u (AbsPath u) connWith arrh b0 b1 = do lw <- getLineWidth let p0 = south b0 let p1 = projectAnchor north (realToFrac lw) b1- drawi $ apply2R2 (rightArrow arrh connLine) p0 p1+ drawi $ connect (rightArrow arrh connline) p0 p1 infixr 4 `cmandatory`, `coptional`, `cmandatory_`, `coptional_` -cmandatory :: ( Real u, Floating u, FromPtSize u ) - => Box u -> Box u -> TraceDrawing u (Path u)+cmandatory :: ( Real u, Floating u, InterpretUnit u ) + => Box u -> Box u -> TraceDrawing u (AbsPath u) cmandatory = connWith diskTip -coptional :: ( Real u, Floating u, FromPtSize u ) - => Box u -> Box u -> TraceDrawing u (Path u)+coptional :: ( Real u, Floating u, InterpretUnit u ) + => Box u -> Box u -> TraceDrawing u (AbsPath u) coptional = connWith odiskTip -cmandatory_ :: ( Real u, Floating u, FromPtSize u ) +cmandatory_ :: ( Real u, Floating u, InterpretUnit u ) => Box u -> Box u -> TraceDrawing u () cmandatory_ p0 p1 = connWith diskTip p0 p1 >> return () -coptional_ :: ( Real u, Floating u, FromPtSize u ) +coptional_ :: ( Real u, Floating u, InterpretUnit u ) => Box u -> Box u -> TraceDrawing u () coptional_ p0 p1 = connWith odiskTip p0 p1 >> return ()
− demo/FontLoaderUtils.hs
@@ -1,95 +0,0 @@-{-# OPTIONS -Wall #-}---module FontLoaderUtils- (- processCmdLine- , default_font_loader_help- ) where---import Control.Applicative-import Control.Monad-import System.Directory-import System.Console.GetOpt-import System.Environment-import System.IO.Error---wumpus_gs_font_dir :: String-wumpus_gs_font_dir = "WUMPUS_GS_FONT_DIR"--wumpus_afm_font_dir :: String-wumpus_afm_font_dir = "WUMPUS_AFM_FONT_DIR"---default_font_loader_help :: String-default_font_loader_help = unlines $ - [ "This example uses glyph metrics loaded at runtime."- , "It can use either the metrics files supplied with GhostScript,"- , "or the AFM v4.1 metrics for the Core 14 fonts available from"- , "Adobe's website."- , "" - , "To use GhostScripts font metrics set the environemt variable"- , wumpus_gs_font_dir ++ " to point to the GhostScript fonts"- , "directory (e.g. /usr/share/ghostscript/fonts) or use the command"- , "line flag --gs=PATH_TO_GHOSTSCRIPT_FONTS"- , ""- , "To use the Adode Core 14 font metrics download the archive from"- , "the Adobe website and set the environment variable "- , wumpus_afm_font_dir ++ " to point to it, or use the command line"- , "flag -- afm=PATH_TO_AFM_CORE14_FONTS"- ]---data CmdLineFlag = Help- | GS_FontDir String- | AFM_FontDir String- deriving (Eq,Ord,Show)--processCmdLine :: String -> IO (Maybe FilePath, Maybe FilePath)-processCmdLine help_message = - let options = makeCmdLineOptions help_message in do- args <- getArgs- let (opts, _, _) = getOpt Permute options args- if Help `elem` opts then failk help_message- else succk opts- where- failk msg = putStr msg >> return (Nothing,Nothing) - succk flags = (,) <$> gsFontDirectory flags <*> afmFontDirectory flags - --makeCmdLineOptions :: String -> [OptDescr CmdLineFlag]-makeCmdLineOptions help_message =- [ Option ['h'] ["help"] (NoArg Help) help_message- , Option [] ["afm"] (ReqArg AFM_FontDir "DIR") "AFM v4.1 metrics dir"- , Option [] ["gs"] (ReqArg GS_FontDir "DIR") "GhoshScript font dir"- ]---gsFontDirectory :: [CmdLineFlag] -> IO (Maybe FilePath)-gsFontDirectory = step - where- step (GS_FontDir p:xs) = doesDirectoryExist p >>= \check -> - if check then return (Just p) else step xs-- step (_:xs) = step xs- step [] = envLookup wumpus_gs_font_dir- --afmFontDirectory :: [CmdLineFlag] -> IO (Maybe FilePath)-afmFontDirectory = step - where- step (AFM_FontDir p:xs) = doesDirectoryExist p >>= \check -> - if check then return (Just p) else step xs-- step (_:xs) = step xs- step [] = envLookup wumpus_afm_font_dir---envLookup :: String -> IO (Maybe String)-envLookup name = liftM fn $ try $ getEnv name- where- fn (Left _) = Nothing- fn (Right a) = Just a-
demo/FontPic.hs view
@@ -2,10 +2,9 @@ module FontPic where -import Wumpus.Drawing.Chains import Wumpus.Drawing.Colour.SVGColours ( steel_blue ) import Wumpus.Drawing.Colour.X11Colours ( indian_red1 )-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic @@ -35,16 +34,17 @@ writeSVG "./out/font_symbol.svg" symbol_pic -fontMsg :: FontFace -> Int -> String-fontMsg ff sz = msgF []+fontMsg :: FontDef -> Int -> String+fontMsg ft sz = msgF [] where- msgF = showString (ps_font_name ff) . showChar ' ' . shows sz . showString "pt"+ msgF = showString name . showChar ' ' . shows sz . showString "pt"+ name = ps_font_name $ font_def_face ft -makeLabel :: RGBi -> FontFace -> Int -> DLocGraphic-makeLabel rgb ff sz = localize upd (textline $ fontMsg ff sz)+makeLabel :: RGBi -> FontDef -> Int -> DLocGraphic+makeLabel rgb ft sz = localize upd (plainTextLine $ fontMsg ft sz) where- upd = fillColour rgb . fontAttr ff sz + upd = text_colour rgb . font_attr ft sz -- indian_red1 -- steel_blue@@ -55,35 +55,39 @@ positions :: [Int] positions = [0, 12, 27, 49, 78, 122] --pointChain :: LocChain Double-pointChain = verticalSteps $ map (fromIntegral . (+2)) point_sizes+-- Note - this chain might be worth putting in a library...+pointChain :: (Int -> DLocGraphic) -> DLocImage DPoint2+pointChain fn = chain chn_alg $ map fn point_sizes+ where+ chn_alg = linear $ iterationScheme start step+ start = \pt -> (pt,point_sizes) + step (pt,[]) = ((displaceV 50 pt, []), pt)+ step (pt,(y:ys)) = ((displaceV (fromIntegral $ 2 + y) pt, ys), pt) -fontGraphic :: RGBi -> FontFace -> DLocGraphic -fontGraphic rgb ff = - unchainZipWith emptyLocGraphic mkGF point_sizes pointChain +fontGraphic :: RGBi -> FontDef -> DLocGraphic +fontGraphic rgb ft = locGraphic_ $ pointChain mkGF where- mkGF sz = makeLabel rgb ff sz+ mkGF sz = makeLabel rgb ft sz std_ctx :: DrawingContext std_ctx = standardContext 10 -fontDrawing :: [(RGBi,FontFace)] -> DCtxPicture+fontDrawing :: [(RGBi,FontDef)] -> CtxPicture fontDrawing xs = drawTracing $ - draw $ unchainZipWith emptyLocGraphic (uncurry fontGraphic) xs chn `at` start+ draw $ chain_ chn_alg (map (uncurry fontGraphic) xs) `at` start where- chn = tableDown 4 (1,180)- start = P2 0 (4*180)+ chn_alg = tableDown 4 (1,180)+ start = P2 0 (4*180) -------------------------------------------------------------------------------- -- Times -times_cxpic :: CtxPicture Double+times_cxpic :: CtxPicture times_cxpic = fontDrawing [ (steel_blue, times_roman) , (indian_red1, times_italic)@@ -91,7 +95,7 @@ , (indian_red1, times_bold_italic) ] -helvetica_cxpic :: CtxPicture Double+helvetica_cxpic :: CtxPicture helvetica_cxpic = fontDrawing [ (steel_blue, helvetica) , (indian_red1, helvetica_oblique)@@ -103,7 +107,7 @@ -------------------------------------------------------------------------------- -courier_cxpic :: CtxPicture Double+courier_cxpic :: CtxPicture courier_cxpic = fontDrawing [ (steel_blue, courier) , (indian_red1, courier_oblique)@@ -115,6 +119,6 @@ -------------------------------------------------------------------------------- -symbol_cxpic :: CtxPicture Double+symbol_cxpic :: CtxPicture symbol_cxpic = fontDrawing [ (steel_blue, symbol) ]
demo/LeftRightText.hs view
@@ -15,79 +15,54 @@ module LeftRightText where -import FontLoaderUtils import Wumpus.Drawing.Colour.SVGColours import Wumpus.Drawing.Dots.Marks-import Wumpus.Drawing.Text.LRText-import Wumpus.Drawing.Text.SafeFonts-+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core import System.Directory - main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/"- maybe gs_failk makeGSPicture $ mb_gs- maybe afm_failk makeAfmPicture $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."---makeGSPicture :: FilePath -> IO ()-makeGSPicture font_dir = do- putStrLn "Using GhostScript metrics..."- (gs_metrics, msgs) <- loadGSMetrics font_dir ["Helvetica"]- mapM_ putStrLn msgs- let pic1 = runCtxPictureU (makeCtx gs_metrics) text_pic- writeEPS "./out/lr_text01.eps" pic1- writeSVG "./out/lr_text01.svg" pic1--makeAfmPicture :: FilePath -> IO ()-makeAfmPicture font_dir = do- putStrLn "Using AFM 4.1 metrics..."- (afm_metrics, msgs) <- loadAfmMetrics font_dir ["Helvetica"]- mapM_ putStrLn msgs- let pic2 = runCtxPictureU (makeCtx afm_metrics) text_pic- writeEPS "./out/lr_text02.eps" pic2- writeSVG "./out/lr_text02.svg" pic2+main = simpleFontLoader main1 >> return () +main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left helvetica ]+ printLoadErrors base_metrics+ let pic1 = runCtxPictureU (makeCtx base_metrics) text_pic+ writeEPS "./out/left_right_text.eps" pic1+ writeSVG "./out/left_right_text.svg" pic1 -makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fontFace helvetica . metricsContext 14+makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font helvetica . metricsContext 15 -text_pic :: CtxPicture Double-text_pic = drawTracing $ do - drawi_ $ (fn left_text) `at` P2 0 400- drawi_ $ (fn center_text) `at` P2 150 400- drawi_ $ (fn right_text) `at` P2 300 400- drawi_ $ (fn blank_text) `at` P2 0 300- drawi_ $ (fn ne_oneline) `at` P2 150 300 - drawi_ $ (fn cc_oneline) `at` P2 300 300+text_pic :: CtxPicture+text_pic = udrawTracing (0::Double) $ localize text_margin_loose $ do + draw $ (fn left_text) `at` P2 0 400+ draw $ (fn center_text) `at` P2 150 400+ draw $ (fn right_text) `at` P2 300 400+ draw $ (fn blank_text) `at` P2 0 300+ draw $ (fn ne_oneline) `at` P2 150 300 + draw $ (fn cc_oneline) `at` P2 300 300 - drawi_ $ (fn sw_oneline) `at` P2 0 200- drawi_ $ (fn ss_oneline) `at` P2 150 200- drawi_ $ (fn se_oneline) `at` P2 300 200- drawi_ $ (fn swr_multi) `at` P2 0 100- drawi_ $ (fn ssr_multi) `at` P2 150 100- drawi_ $ (fn ner_multi) `at` P2 300 100- drawi_ $ (fn rleft_text) `at` P2 0 (-75)- drawi_ $ (fn rcenter_text) `at` P2 150 (-75)- drawi_ $ (fn rright_text) `at` P2 300 (-75)+ draw $ (fn sw_oneline) `at` P2 0 200+ draw $ (fn ss_oneline) `at` P2 150 200+ draw $ (fn se_oneline) `at` P2 300 200+ draw $ (fn swr_single) `at` P2 0 100+ draw $ (fn ssr_single) `at` P2 150 100+ draw $ (fn ner_single) `at` P2 300 100 draw $ redPlus `at` P2 0 400 draw $ redPlus `at` P2 150 400@@ -108,78 +83,67 @@ where fn = illustrateBoundedLocGraphic -redPlus :: (Fractional u, FromPtSize u) => LocGraphic u-redPlus = localize (strokeColour red) markPlus+redPlus :: (Fractional u, InterpretUnit u) => LocGraphic u+redPlus = localize (stroke_colour red) markPlus -- single line -- ne_oneline :: BoundedLocGraphic Double-ne_oneline = singleLine "north east" `startPos` NE+ne_oneline = textline "north east" `startAddr` NE -- single line -- se_oneline :: BoundedLocGraphic Double-se_oneline = singleLine "south east" `startPos` SE+se_oneline = textline "south east" `startAddr` SE -- single line -- ss_oneline :: BoundedLocGraphic Double-ss_oneline = singleLine "south" `startPos` SS+ss_oneline = textline "south" `startAddr` SS -- single line -- sw_oneline :: BoundedLocGraphic Double-sw_oneline = singleLine "south west" `startPos` SW+sw_oneline = textline "south west" `startAddr` SW --- multi line++-- single line rot ---ssr_multi :: BoundedLocGraphic Double-ssr_multi = multiAlignCenter (0.25*pi) "south rot45" `startPos` SS+ssr_single :: BoundedLocGraphic Double+ssr_single = rtextline (0.25*pi) "south rot45" `startAddr` SS --- multi line+-- single line rot ---swr_multi :: BoundedLocGraphic Double-swr_multi = multiAlignCenter (0.25*pi) "south west rot45" `startPos` SW+swr_single :: BoundedLocGraphic Double+swr_single = rtextline (0.25*pi) "south west rot45" `startAddr` SW --- multi line+-- single line rot ---ner_multi :: BoundedLocGraphic Double-ner_multi = multiAlignCenter (0.25*pi) "north east rot45" `startPos` NE+ner_single :: BoundedLocGraphic Double+ner_single = rtextline (0.25*pi) "north east rot45" `startAddr` NE cc_oneline :: BoundedLocGraphic Double-cc_oneline = rsingleLine 0 "Center-center..." `startPos` CENTER+cc_oneline = ccTextline "Center-center..." blank_text :: BoundedLocGraphic Double-blank_text = multiAlignCenter 0 "" `startPos` CENTER+blank_text = blcTextline "" left_text :: BoundedLocGraphic Double-left_text = multiAlignLeft 0 dummy_text `startPos` CENTER+left_text = multiAlignLeft dummy_text `startAddr` CENTER right_text :: BoundedLocGraphic Double-right_text = multiAlignRight 0 dummy_text `startPos` CENTER+right_text = multiAlignRight dummy_text `startAddr` CENTER center_text :: BoundedLocGraphic Double-center_text = multiAlignCenter 0 dummy_text `startPos` CENTER---rleft_text :: BoundedLocGraphic Double-rleft_text = multiAlignLeft (0.25*pi) dummy_text `startPos` CENTER---rright_text :: BoundedLocGraphic Double-rright_text = multiAlignRight (0.25*pi) dummy_text `startPos` CENTER--rcenter_text :: BoundedLocGraphic Double-rcenter_text = multiAlignCenter (0.25*pi) dummy_text `startPos` CENTER-+center_text = multiAlignCenter dummy_text `startAddr` CENTER dummy_text :: String dummy_text = unlines $ [ "The quick brown"
demo/PetriNet.hs view
@@ -7,18 +7,14 @@ module PetriNet where -import Wumpus.Drawing.Arrows import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Paths+import Wumpus.Drawing.Connectors import Wumpus.Drawing.Shapes-import Wumpus.Drawing.Text.SafeFonts-import Wumpus.Drawing.Text.LRText--import FontLoaderUtils+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core @@ -26,135 +22,117 @@ import System.Directory -- main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/"- maybe gs_failk makeGSPicture $ mb_gs- maybe afm_failk makeAfmPicture $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."+main = simpleFontLoader main1 >> return () -makeGSPicture :: FilePath -> IO ()-makeGSPicture font_dir = do - putStrLn "Using GhostScript metrics..."- (base_metrics, msgs) <- loadGSMetrics font_dir ["Helvetica", "Helvetica-Bold"]- mapM_ putStrLn msgs+main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Right helvetica_family ]+ printLoadErrors base_metrics let pic1 = runCtxPictureU (makeCtx base_metrics) petri_net- writeEPS "./out/petri_net01.eps" pic1- writeSVG "./out/petri_net01.svg" pic1 + writeEPS "./out/petri_net.eps" pic1+ writeSVG "./out/petri_net.svg" pic1 -makeAfmPicture :: FilePath -> IO ()-makeAfmPicture font_dir = do - putStrLn "Using AFM 4.1 metrics..."- (base_metrics, msgs) <- loadAfmMetrics font_dir ["Helvetica", "Helvetica-Bold"]- mapM_ putStrLn msgs- let pic1 = runCtxPictureU (makeCtx base_metrics) petri_net- writeEPS "./out/petri_net02.eps" pic1- writeSVG "./out/petri_net02.svg" pic1 +makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font helvetica . metricsContext 14 -makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fontFace helvetica . metricsContext 14-+petri_net :: CtxPicture+petri_net = udrawTracing (0::Double) $ do+ pw <- drawi $ place `at` (P2 0 140)+ tu1 <- drawi $ transition `at` (P2 70 140) + rtw <- drawi $ place `at` (P2 140 140)+ tu2 <- drawi $ transition `at` (P2 210 140)+ w <- drawi $ place `at` (P2 280 140)+ tu3 <- drawi $ transition `at` (P2 350 140)+ res <- drawi $ place `at` (P2 280 70)+ pr <- drawi $ place `at` (P2 0 0)+ tl1 <- drawi $ transition `at` (P2 70 0)+ rtr <- drawi $ place `at` (P2 140 0)+ tl2 <- drawi $ transition `at` (P2 210 0)+ r <- drawi $ place `at` (P2 280 0)+ tl3 <- drawi $ transition `at` (P2 350 0) -petri_net :: DCtxPicture-petri_net = drawTracing $ do- pw <- place 0 140- tu1 <- transition 70 140- rtw <- place 140 140- tu2 <- transition 210 140- w <- place 280 140- tu3 <- transition 350 140- res <- place 280 70- pr <- place 0 0- tl1 <- transition 70 0- rtr <- place 140 0- tl2 <- transition 210 0- r <- place 280 0- tl3 <- transition 350 0- connector' (east pw) (west tu1) - connector' (east tu1) (west rtw)- connector' (east rtw) (west tu2)- connector' (east tu2) (west w)- connector' (east w) (west tu3)- connectorC 32 (north tu3) (north pw)- connector' (east pr) (west tl1) - connector' (east tl1) (west rtr)- connector' (east rtr) (west tl2)- connector' (east tl2) (west r)- connector' (east r) (west tl3)- connectorC (-32) (south tl3) (south pr)- connector' (southwest res) (northeast tl2)- connector' (northwest tl3) (southeast res)- connectorD 6 (southwest tu3) (northeast res)- connectorD (-6) (southwest tu3) (northeast res) - connectorD 6 (northwest res) (southeast tu2)- connectorD (-6) (northwest res) (southeast tu2) + drawc (east pw) (west tu1) $ straightconn+ drawc (east tu1) (west rtw) $ straightconn+ drawc (east rtw) (west tu2) $ straightconn+ drawc (east tu2) (west w) $ straightconn+ drawc (east w) (west tu3) $ straightconn+ drawc (north tu3) (north pw) $ connectorC + drawc (east pr) (west tl1) $ straightconn+ drawc (east tl1) (west rtr) $ straightconn+ drawc (east rtr) (west tl2) $ straightconn+ drawc (east tl2) (west r) $ straightconn+ drawc (east r) (west tl3) $ straightconn+ drawc (south tl3) (south pr) $ connectorC'+ drawc (southwest res) (northeast tl2) $ straightconn+ drawc (northwest tl3) (southeast res) $ straightconn+ drawc (southwest tu3) (northeast res) $ connectorD+ drawc (southwest tu3) (northeast res) $ connectorD'+ drawc (northwest res) (southeast tu2) $ connectorD+ drawc (northwest res) (southeast tu2) $ connectorD' draw $ lblParensParens `at` (P2 (-36) 150) draw $ lblParensParens `at` (P2 300 60) draw $ lblParensParensParens `at` (P2 (-52) (-14))- draw $ lblBold "processing_w" `at` (projectAnchor south 12 pw)- draw $ lblBold "ready_to_write" `at` (projectAnchor south 12 rtw)- draw $ lblBold "writing" `at` (projectAnchor south 12 w)- draw $ lblBold' "resource" `at` (P2 300 72)- draw $ lblBold "processing_r" `at` (projectAnchor north 12 pr)- draw $ lblBold "ready_to_read" `at` (projectAnchor north 12 rtr)- draw $ lblBold "reading" `at` (projectAnchor north 12 r)+ drawl (projectAnchor south 12 pw) $ lblBold "processing_w"+ drawl (projectAnchor south 12 rtw) $ lblBold "ready_to_write"+ drawl (projectAnchor south 12 w) $ lblBold "writing"+ draw $ lblBold "resource" `at` (P2 300 72)+ drawl (projectAnchor north 12 pr) $ lblBold "processing_r"+ drawl (projectAnchor north 12 rtr) $ lblBold "ready_to_read"+ drawl (projectAnchor north 12 r) $ lblBold "reading"+ return () -greenFill :: DrawingCtxM m => m a -> m a-greenFill = localize (fillColour lime_green)+greenFill :: LocImage u a -> LocImage u a+greenFill = localize (fill_colour lime_green) -place :: ( Real u, Floating u, FromPtSize u- , DrawingCtxM m, TraceM m, u ~ MonUnit m ) - => u -> u -> m (Circle u)-place x y = greenFill $ drawi $ (borderedShape $ circle 14) `at` P2 x y -transition :: ( Real u, Floating u, FromPtSize u- , DrawingCtxM m, TraceM m, u ~ MonUnit m ) - => u -> u -> m (Rectangle u)-transition x y = - greenFill $ drawi $ (borderedShape $ rectangle 32 22) `at` P2 x y+place :: DLocImage (Circle Double)+place = greenFill $ borderedShape $ circle 14 +transition :: DLocImage (Rectangle Double)+transition = greenFill $ borderedShape $ rectangle 32 22 -connector' :: ( TraceM m, DrawingCtxM m, u ~ MonUnit m- , Real u, Floating u, FromPtSize u ) - => Point2 u -> Point2 u -> m ()-connector' p0 p1 = - drawi_ $ apply2R2 (rightArrow tri45 connLine) p0 p1 -connectorC :: ( Real u, Floating u, FromPtSize u- , DrawingCtxM m, TraceM m, u ~ MonUnit m )- => u -> Point2 u -> Point2 u -> m ()-connectorC v p0 p1 = - drawi_ $ apply2R2 (rightArrow tri45 (connRightVHV v)) p0 p1+straightconn :: ConnectorGraphic Double+straightconn = connectorGraphic_ $ rightArrow tri45 connline -connectorD :: ( Real u, Floating u, FromPtSize u- , DrawingCtxM m, TraceM m, u ~ MonUnit m )- => u -> Point2 u -> Point2 u -> m ()-connectorD u p0 p1 = - drawi_ $ apply2R2 (rightArrow tri45 (connIsosceles u)) p0 p1 +connectorC :: ConnectorGraphic Double+connectorC = + connectorGraphic_ $ localize (uniform_arm_len (30::Double)) + $ rightArrow tri45 connbbar -lblParensParens :: Num u => LocGraphic u-lblParensParens = localize (fontFace helvetica) $ textline "(),()"+connectorC' :: ConnectorGraphic Double+connectorC' = + connectorGraphic_ $ localize (uniform_arm_len (30::Double)) + $ rightArrow tri45 connabar -lblParensParensParens :: Num u => LocGraphic u-lblParensParensParens = localize (fontFace helvetica) $ textline "(),(),()"+connectorD :: ConnectorGraphic Double+connectorD = connectorGraphic_ $ rightArrow tri45 connarc +connectorD' :: ConnectorGraphic Double+connectorD' = + connectorGraphic_ $ localize (conn_arc_angle $ negate $ pi / 12) + $ rightArrow tri45 connarc -lblBold' :: Num u => String -> LocGraphic u-lblBold' ss = localize (fontFace helvetica_bold) $ textline ss +lblParensParens :: DLocGraphic+lblParensParens = + locGraphic_ $ localize (set_font helvetica) $ ccTextline "(),()" -lblBold :: (Real u, Floating u, FromPtSize u) => String -> LocGraphic u-lblBold ss = localize (fontFace helvetica_bold) $ - ignoreAns $ textAlignCenter ss+lblParensParensParens :: DLocGraphic+lblParensParensParens = + locGraphic_ $ localize (set_font helvetica) $ ccTextline "(),(),()"++++lblBold :: String -> DLocGraphic+lblBold ss = + locGraphic_ $ localize (set_font helvetica_bold) $ ccTextline ss
demo/SampleShapes.hs view
@@ -1,66 +1,43 @@ {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} module SampleShapes where -import FontLoaderUtils- import Wumpus.Drawing.Colour.SVGColours import Wumpus.Drawing.Dots.Marks import Wumpus.Drawing.Shapes-import Wumpus.Drawing.Text.LRText-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript-+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core import Control.Monad import System.Directory - main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/shapes/"- maybe gs_failk (makeGSPicture shape_list) $ mb_gs- maybe afm_failk (makeAfmPicture shape_list) $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."-+main = simpleFontLoader main1 >> return () -makeGSPicture :: ShapeList -> FilePath -> IO ()-makeGSPicture shapes font_dir = do- putStrLn "Using GhostScript metrics..."- (gs_metrics, msgs) <- loadGSMetrics font_dir ["Courier"]- mapM_ putStrLn msgs- mapM_ (out1 gs_metrics) shapes +main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/shapes/" + base_metrics <- loader [ Left courier ]+ printLoadErrors base_metrics+ let ctx = makeCtx base_metrics+ mapM_ (out1 ctx) shape_list where- out1 gs_metrics (name, shape_pic) = do - let pic1 = runCtxPictureU (makeCtx gs_metrics) $ shape_pic name+ out1 ctx (name, shape_pic) = do + let pic1 = runCtxPictureU ctx $ shape_pic name writeEPS ("./out/shapes/" ++ name ++ "01.eps") pic1 writeSVG ("./out/shapes/" ++ name ++ "01.svg") pic1 -makeAfmPicture :: ShapeList -> FilePath -> IO ()-makeAfmPicture shapes font_dir = do- putStrLn "Using AFM 4.1 metrics..."- (afm_metrics, msgs) <- loadAfmMetrics font_dir ["Courier"]- mapM_ putStrLn msgs- mapM_ (out1 afm_metrics) shapes - where- out1 afm_metrics (name, shape_pic) = do - let pic1 = runCtxPictureU (makeCtx afm_metrics) $ shape_pic name- writeEPS ("./out/shapes/" ++ name ++ "02.eps") pic1- writeSVG ("./out/shapes/" ++ name ++ "02.svg") pic1--type ShapeList = [(String, (String -> DCtxPicture))]+type ShapeList = [(String, (String -> CtxPicture))] shape_list :: ShapeList@@ -96,10 +73,10 @@ triangle 300 150 ) ] -makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fontFace courier . metricsContext 16+makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font courier . metricsContext 16 -rotate05 :: Rotate a => a -> a+rotate05 :: Rotate a => Image u a -> Image u a rotate05 = rotate (d2r (5::Double)) -- Extra elaboration...@@ -107,26 +84,27 @@ voidExtra :: a -> TraceDrawing u () voidExtra _ = return () -apexAnchor :: ( Real u, Floating u, FromPtSize u- , ApexAnchor a- , u ~ DUnit a )+++apexAnchor :: ( Real u, Floating u, InterpretUnit u+ , ApexAnchor a, u ~ DUnit a) => a -> TraceDrawing u a apexAnchor a = do draw $ label EAST "(apex)" `at` apex a return a -bottomCorners :: ( Real u, Floating u, FromPtSize u- , BottomCornerAnchor a- , u ~ DUnit a )+bottomCorners :: ( Real u, Floating u, InterpretUnit u+ , BottomCornerAnchor a, u ~ DUnit a+ ) => a -> TraceDrawing u a bottomCorners a = do draw $ label SOUTH_WEST "(bottom left)" `at` bottomLeftCorner a draw $ label SOUTH_EAST "(bottom right)" `at` bottomRightCorner a return a -topCorners :: ( Real u, Floating u, FromPtSize u- , TopCornerAnchor a- , u ~ DUnit a )+topCorners :: ( Real u, Floating u, InterpretUnit u+ , TopCornerAnchor a, u ~ DUnit a+ ) => a -> TraceDrawing u a topCorners a = do draw $ label NORTH_WEST "(top left)" `at` topLeftCorner a@@ -134,9 +112,9 @@ return a -midPoints :: ( Real u, Floating u, FromPtSize u- , SideMidpointAnchor a- , u ~ DUnit a )+midPoints :: ( Real u, Floating u, InterpretUnit u+ , SideMidpointAnchor a, u ~ DUnit a+ ) => Int -> a -> TraceDrawing u a midPoints n a = mapM_ mf [1..n] >> return a where@@ -146,12 +124,17 @@ -shapePic :: ( CenterAnchor a, CardinalAnchor a, CardinalAnchor2 a- , RadialAnchor a- , Scale a, Rotate a- , DUnit a ~ Double) - => (a -> DTraceDrawing b) -> DShape a -> String -> DCtxPicture-shapePic mf sh name = drawTracing $ do+shapePic :: ( Functor t+ , CenterAnchor (t Double)+ , CardinalAnchor (t Double)+ , CardinalAnchor2 (t Double)+ , RadialAnchor (t Double)+ , Scale (t Double)+ , Rotate (t Double)+ , Double ~ DUnit (t Double)+ ) + => (t Double -> DTraceDrawing a) -> DShape t -> String -> CtxPicture+shapePic mf sh name = udrawTracing (0::Double) $ do a1 <- localize shapeSty $ drawi $ uniformScale 2 $ rotate05 $ shape `at` (P2 100 0) draw $ label NORTH "(center)" `at` center a1@@ -171,7 +154,7 @@ return () where shape = strokedShape $ setDecoration textF sh- textF = lift1R2 $ ignoreAns (multiAlignCenter 0 name `startPos` CENTER)+ textF = lift1R2 $ locGraphic_ (startAddr (multiAlignCenter name) CENTER) deg10 = d2r (10::Double) deg110 = d2r (110::Double)@@ -184,23 +167,23 @@ shapeSty :: DrawingContextF-shapeSty = strokeColour light_steel_blue . ultrathick+shapeSty = stroke_colour light_steel_blue . line_ultra_thick -label :: (Real u, Floating u, FromPtSize u) - => Cardinal -> String -> LocGraphic u+label :: (Real u, Floating u, InterpretUnit u) + => Cardinal -> String -> LocGraphic u label cpos ss = markX `oplus` msg where (rpos,fn) = go cpos- msg = ignoreAns $ moveStart (fn 10) $ - multiAlignCenter 0 ss `startPos` rpos+ msg = locGraphic_ $ moveStart (fn 10) $ + startAddr (multiAlignCenter ss) rpos - go NORTH = (SS, northwards)- go NORTH_EAST = (SW, northeastwards)- go EAST = (WW, eastwards) - go SOUTH_EAST = (NW, southeastwards)- go SOUTH = (NN, southwards)- go SOUTH_WEST = (NE, southwestwards)- go WEST = (EE, westwards)- go NORTH_WEST = (SE, northwestwards)+ go NORTH = (SS, disp_north)+ go NORTH_EAST = (SW, disp_northeast)+ go EAST = (WW, disp_east) + go SOUTH_EAST = (NW, disp_southeast)+ go SOUTH = (NN, disp_south)+ go SOUTH_WEST = (NE, disp_southwest)+ go WEST = (EE, disp_west)+ go NORTH_WEST = (SE, disp_northwest)
+ demo/SingleChar.hs view
@@ -0,0 +1,70 @@+{-# OPTIONS -Wall #-}+++module SingleChar where+++import Wumpus.Drawing.Colour.SVGColours+import Wumpus.Drawing.Dots.Marks+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs++import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Basic.System.FontLoader++import Wumpus.Core -- package: wumpus-core++import System.Directory+++main :: IO ()+main = simpleFontLoader main1 >> return ()++main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left helvetica ]+ printLoadErrors base_metrics+ let pic1 = runCtxPictureU (makeCtx base_metrics) drawing01+ writeEPS "./out/single_char.eps" pic1+ writeSVG "./out/single_char.svg" pic1+++makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font helvetica . metricsContext 18++++drawing01 :: CtxPicture+drawing01 = drawTracing $ localize (fill_colour red) $ mf +++-- Note - Baseline positions not meaningful for multiline text++mf :: TraceDrawing Double ()+mf = localize (text_margin 6.0 6.0) $ do+ draw $ (fn SS $ posChar 'S') `at` zeroPt+ draw $ redPlus `at` zeroPt++ draw $ (fn NN $ posChar 'N') `at` P2 40 0+ draw $ redPlus `at` P2 40 0++ draw $ (fn EE $ posChar 'E') `at` P2 80 0+ draw $ redPlus `at` P2 80 0++ draw $ (fn WW $ posChar 'W') `at` P2 120 0+ draw $ redPlus `at` P2 120 0++ draw $ (fn CENTER $ posChar 'C') `at` P2 160 0+ draw $ redPlus `at` P2 160 0++ draw $ (fn NE $ posChar 'X') `at` P2 200 0+ draw $ redPlus `at` P2 200 0++ where+ fn addr obj = illustrateBoundedLocGraphic (runPosObjectR2 obj `startAddr` addr)+++redPlus :: (Fractional u, InterpretUnit u) => LocGraphic u+redPlus = localize (stroke_colour red) markPlus+
demo/SingleLine.hs view
@@ -3,15 +3,12 @@ module SingleLine where -import FontLoaderUtils- import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Text.LRText-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Text.DirectionZero+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.System.FontLoader.Afm-import Wumpus.Basic.System.FontLoader.GhostScript+import Wumpus.Basic.System.FontLoader import Wumpus.Core -- package: wumpus-core @@ -19,46 +16,29 @@ main :: IO ()-main = do - (mb_gs, mb_afm) <- processCmdLine default_font_loader_help- createDirectoryIfMissing True "./out/"- maybe gs_failk makeGSPicture $ mb_gs- maybe afm_failk makeAfmPicture $ mb_afm- where- gs_failk = putStrLn "No GhostScript font path supplied..."- afm_failk = putStrLn "No AFM v4.1 font path supplied..."---makeGSPicture :: FilePath -> IO ()-makeGSPicture font_dir = do- putStrLn "Using GhostScript metrics..."- (gs_metrics, msgs) <- loadGSMetrics font_dir ["Helvetica"]- mapM_ putStrLn msgs- let pic1 = runCtxPictureU (makeCtx gs_metrics) drawing01- writeEPS "./out/single_line01.eps" pic1- writeSVG "./out/single_line01.svg" pic1+main = simpleFontLoader main1 >> return () -makeAfmPicture :: FilePath -> IO ()-makeAfmPicture font_dir = do- putStrLn "Using AFM 4.1 metrics..."- (afm_metrics, msgs) <- loadAfmMetrics font_dir ["Helvetica"]- mapM_ putStrLn msgs- let pic2 = runCtxPictureU (makeCtx afm_metrics) drawing01- writeEPS "./out/single_line02.eps" pic2- writeSVG "./out/single_line02.svg" pic2+main1 :: FontLoader -> IO ()+main1 loader = do+ createDirectoryIfMissing True "./out/" + base_metrics <- loader [ Left helvetica ]+ printLoadErrors base_metrics+ let pic1 = runCtxPictureU (makeCtx base_metrics) drawing01+ writeEPS "./out/single_line.eps" pic1+ writeSVG "./out/single_line.svg" pic1 -makeCtx :: GlyphMetrics -> DrawingContext-makeCtx = fontFace helvetica . metricsContext 12+makeCtx :: FontLoadResult -> DrawingContext+makeCtx = set_font helvetica . metricsContext 12 -drawing01 :: DCtxPicture-drawing01 = drawTracing $ localize (fillColour red) $ mf +drawing01 :: CtxPicture+drawing01 = drawTracing $ localize (fill_colour red) $ mf -mf :: (Real u, Floating u, FromPtSize u) => TraceDrawing u ()+mf :: TraceDrawing Double () mf = do draw $ testDraw NN `at` (P2 0 200) draw $ testDraw SS `at` (P2 75 200)@@ -71,10 +51,10 @@ draw $ testDraw CENTER `at` (P2 0 0) -testDraw :: (Real u, Floating u, FromPtSize u) => RectPosition -> LocGraphic u-testDraw rpos = filledDisk 2 `oplus` (ignoreAns ans)+testDraw :: RectAddress -> LocGraphic Double+testDraw rpos = filledDisk 2 `oplus` (locGraphic_ ans) where- ans = singleLine "Qwerty" `startPos` rpos+ ans = textline "Qwerty" `startAddr` rpos
demo/Symbols.hs view
@@ -2,8 +2,7 @@ module Symbols where -import Wumpus.Drawing.Chains-import Wumpus.Drawing.Text.SafeFonts+import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core@@ -21,7 +20,7 @@ std_ctx :: DrawingContext-std_ctx = fontFace times_roman $ standardContext 12+std_ctx = set_font times_roman $ standardContext 12 -- Because the font changes, we draw the all the symbols in one@@ -29,16 +28,16 @@ -- generate better PostScript as there are less changes to the -- /graphics state/. ---symbols :: DCtxPicture-symbols = drawTracing $ do- draw $ localize (fontFace symbol) $ - unchainZipWith emptyLocGraphic sdraw all_letters chn `at` start- draw $ unchainZipWith emptyLocGraphic ldraw all_letters chn `at` start+symbols :: CtxPicture+symbols = udrawTracing (0::Double) $ do+ localize (set_font symbol) $ fontDelta $ draw $+ chain_ chn_alg (map sdraw all_letters) `at` start+ fontDelta $ draw $ chain chn_alg (map ldraw all_letters) `at` start where- chn = tableDown 30 (100,20) + chn_alg = tableDown 30 (100,20) start = P2 0 (30*20)- sdraw (s,_) = textline s- ldraw (_,name) = moveStart (displaceH 16) (textline name)+ sdraw (s,_) = plainTextLine s+ ldraw (_,name) = moveStart (displaceH 16) (plainTextLine name) all_letters :: [(String, String)]
demo/TableChains.hs view
@@ -4,7 +4,7 @@ import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Grids+import Wumpus.Drawing.Extras.Grids import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core@@ -19,32 +19,8 @@ writeSVG "./out/table_chains01.svg" pic1 std_ctx :: DrawingContext-std_ctx = fillColour peru $ standardContext 18--table_drawing :: CtxPicture Double-table_drawing = drawTracing $ do --- tableGraphic- draw $ connect (interiorGrid 10) (P2 (-20) (-20)) (P2 150 80)- draw $ grid (3,2) 20 `at` (P2 300 60)--{--tableGraphic :: (Real u, Floating u, FromPtSize u) - => TraceDrawing u ()-tableGraphic = do - draw $ filledDisk 3 `at` dstart- draw $ filledDisk 3 `at` rstart- zipchainWith (textline . show) [1..20::Int] downs- zipchainWith (textline . show) [1..20::Int] rights- where- downs = tableDown 4 (36,24) dstart- rights = tableRight 5 (36,24) rstart-- dstart = P2 0 200 -- note grows down...- rstart = P2 240 200 -- ditto--}- ----+std_ctx = fill_colour peru $ standardContext 18 +table_drawing :: CtxPicture+table_drawing = udrawTracing (0::Double) $ do + draw $ grid (grid_minor_colour cornflower_blue) (0,0) (4,2)
− src/Wumpus/Drawing/Arrows.hs
@@ -1,28 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Arrows--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Shim module for arrow connectors and arrowheads.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Arrows- ( -- module Wumpus.Drawing.Arrows.Tips- , module Wumpus.Drawing.Arrows.Connectors-- ) where--import Wumpus.Drawing.Arrows.Tips-import Wumpus.Drawing.Arrows.Connectors--
− src/Wumpus/Drawing/Arrows/Connectors.hs
@@ -1,104 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Arrows.Connectors--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Draw arrows.--------------------------------------------------------------------------------------module Wumpus.Drawing.Arrows.Connectors- ( -- ArrowConnector- , leftArrow- , rightArrow- , leftRightArrow- , uniformArrow-- ) where--import Wumpus.Basic.Kernel-import Wumpus.Drawing.Arrows.Tips-import Wumpus.Drawing.Paths------ An arrowhead always know how to draw itself (filled triangle, --- stroked barb, etc.)------ A Path is currently always drawn with openStroke,--- eventually there might be scope for drawing --- e.g. parallel lines ====-------- | A connector with arrow tips. The connector is an /Image/,--- drawing it returns the path - positions can be taken on the --- path (e.g. @midpoint@) for further decoration.----type ArrowConnector u = ConnectorImage u (Path u)----- | Connector with an arrow tip at the start point \/ left.----leftArrow :: (Real u, Floating u) - => Arrowhead u -> ConnectorPath u -> ArrowConnector u-leftArrow arrh conn = promoteR2 $ \p0 p1 -> - connect conn p0 p1 >>= \cpath -> - arrowhead_retract_dist arrh >>= \dl -> - let path1 = shortenL dl cpath- ang = directionL path1- g1 = openStroke $ toPrimPath path1- g2 = atRot (arrowhead_draw arrh) p0 ang- in fmap (replaceL cpath) $ g1 `oplus` g2 ---- Note - returns original path- ---- | Connector with an arrow tip at the end point \/ right.----rightArrow :: (Real u, Floating u) - => Arrowhead u -> ConnectorPath u -> ArrowConnector u-rightArrow arrh conn = promoteR2 $ \p0 p1 -> - connect conn p0 p1 >>= \cpath -> - arrowhead_retract_dist arrh >>= \dr -> - let path1 = shortenR dr cpath- ang = directionR path1- g1 = openStroke $ toPrimPath path1- g2 = atRot (arrowhead_draw arrh) p1 ang- in fmap (replaceL cpath) $ g1 `oplus` g2------ | Connector with two arrow tips, possibly different.----leftRightArrow :: (Real u, Floating u) - => Arrowhead u -> Arrowhead u -> ConnectorPath u - -> ArrowConnector u-leftRightArrow arrL arrR conn = promoteR2 $ \p0 p1 -> - connect conn p0 p1 >>= \cpath -> - arrowhead_retract_dist arrL >>= \dL -> - arrowhead_retract_dist arrR >>= \dR -> - let path1 = shortenPath dL dR cpath- angL = directionL path1- angR = directionR path1- g1 = openStroke $ toPrimPath path1- gL = atRot (arrowhead_draw arrL) p0 angL- gR = atRot (arrowhead_draw arrR) p1 angR- in fmap (replaceL cpath) $ g1 `oplus` gL `oplus` gR----- | Connector with the same arrow tip at both ends.----uniformArrow :: (Real u, Floating u) - => Arrowhead u -> ConnectorPath u -> ArrowConnector u-uniformArrow arrh cp = leftRightArrow arrh arrh cp-
− src/Wumpus/Drawing/Arrows/Tips.hs
@@ -1,515 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Arrows.Tips--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Anchor points on shapes.------ \*\* WARNING \*\* this module is an experiment, and may --- change significantly in future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Arrows.Tips- ( --- Arrowhead(..)-- - , tri90- , tri60- , tri45- , otri90- , otri60- , otri45-- , revtri90- , revtri60- , revtri45- , orevtri90- , orevtri60- , orevtri45-- , barb90- , barb60- , barb45- , revbarb90- , revbarb60- , revbarb45-- , perp-- , bracket-- , diskTip- , odiskTip- , squareTip- , osquareTip- , diamondTip- , odiamondTip-- , curveTip- , revcurveTip-- ) where--import Wumpus.Basic.Kernel-import Wumpus.Drawing.Paths--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space--import Control.Applicative----- | Encode an arrowhead as a Graphic and a retract distance - --- lines should be shortened for certain drawings (e.g. open--- triangles).------ The retract distance is context sensitive - usually just on--- the markHeight (or halfMarkHeight) so it has to be calculated--- w.r.t. the DrawingCtx.----data Arrowhead u = Arrowhead - { arrowhead_retract_dist :: DrawingInfo u- , arrowhead_draw :: LocThetaGraphic u - }----- Design note - this used to be a newtype wrapper over a --- LocThetaImage that returned retract distance. But, considering --- the dataflow / evaluation, in some respects Arrowhead is not an --- ideal LocThetaImage as we want the retract distance to work out --- how to draw the image.------ Images do not inherently encode objects that should be drawn --- and evaluated at the same time (and lazy eval permits this) but --- it seems to helpful to think that Images should be evaluated as --- they are drawn.-------- | Tiplen is length of the tip \*along the line it follows\*. ------ > |\--- > | \--- > | /--- > |/--- > --- > | | -- tip len------- | Tip width is the distance between upper and lower --- arrow points.------ > __--- > |\ --- > | \ tip--- > | / width--- > |/ __--- > ------ | This one is for triangular tips defined by their tip angle--- e.g. 90deg, 60deg, 45deg.------ The tip width will be variable (tip length should be the --- markHeight).--- -triVecsByAngle :: Floating u => u -> Radian -> Radian -> (Vec2 u, Vec2 u)-triVecsByAngle tiplen halfang theta = (vec_to_upper, vec_to_lower)- where- hypo_len = tiplen / (fromRadian $ cos halfang)- rtheta = pi + theta -- theta in the opposite direction- vec_to_upper = avec (circularModulo $ rtheta - halfang) hypo_len- vec_to_lower = avec (circularModulo $ rtheta + halfang) hypo_len ------ | This one is for triangles when the tip height and tip width--- are known.----triVecsByDist :: (Real u, Floating u) - => u -> u -> Radian -> (Vec2 u, Vec2 u)-triVecsByDist tiplen half_tipwidth theta = (vec_to_upper, vec_to_lower)- where- hypo_len = sqrt $ (tiplen*tiplen) + (half_tipwidth*half_tipwidth)- halfang = toRadian $ atan (half_tipwidth / tiplen) - rtheta = pi + theta -- theta in the opposite direction- vec_to_upper = avec (circularModulo $ rtheta - halfang) hypo_len- vec_to_lower = avec (circularModulo $ rtheta + halfang) hypo_len -----{--markHeightPlusLineWidth :: (Fractional u, FromPtSize u) => DrawingR u-markHeightPlusLineWidth = - (\h lw -> h + realToFrac lw) <$> markHeight <*> lineWidth--}---markHeightLessLineWidth :: (Fractional u, FromPtSize u) => CF u-markHeightLessLineWidth = - (\h lw -> h - realToFrac lw) <$> markHeight <*> getLineWidth----- noRetract ignores both the angle and the point.------ Its common for the rectraction not to care about the angle or --- the point and only care about the DrawingCtx.----noRetract :: Num u => DrawingInfo u-noRetract = pure 0 ----- | Arrow tips are drawn with a sloid line even if the connector--- line is dashed (tips also override round corners)--solidArrTip :: DrawingCtxM m => m a -> m a-solidArrTip mf = localize (dashPattern Solid . roundCornerFactor 0) mf---solidOpenStroke :: Num u => PrimPath u -> Graphic u-solidOpenStroke = solidArrTip . openStroke--solidClosedStroke :: Num u => PrimPath u -> Graphic u-solidClosedStroke = solidArrTip . closedStroke--solidStrokedDisk :: Num u => u -> LocGraphic u-solidStrokedDisk = solidArrTip . strokedDisk------------------------------------------------------------------------------------tipBody :: FromPtSize u => (Point2 u -> Radian -> u -> CF a) -> LocThetaCF u a-tipBody mf = promoteR2 $ \pt theta -> markHeight >>= \h -> mf pt theta h ---- | Tripoints takes the \*tip length\* is the mark height.------ This means that the 90deg tip has a tip width greater-than the--- mark height (but that is okay - seemingly this is how TikZ --- does it).----tripointsByAngle :: (Floating u, FromPtSize u)- => Radian -> LocThetaCF u (Point2 u, Point2 u)-tripointsByAngle triang = - tipBody $ \pt theta h -> - let (vup,vlo) = triVecsByAngle h (0.5*triang) theta- in pure (pt .+^ vup, pt .+^ vlo)- --revtripointsByAngle :: (Floating u, FromPtSize u)- => Radian - -> LocThetaCF u (Point2 u, Point2 u, Point2 u)-revtripointsByAngle triang = - tipBody $ \pt theta h -> - let theta' = circularModulo $ pi+theta - (vup,vlo) = triVecsByAngle h (0.5*triang) theta'- back_tip = pt .-^ avec theta h - in pure (back_tip .+^ vup, back_tip, back_tip .+^ vlo)----tripointsByDist :: (Real u, Floating u, FromPtSize u)- => LocThetaCF u (Point2 u, Point2 u)-tripointsByDist = - tipBody $ \pt theta h -> - let (vup,vlo) = triVecsByDist h (0.5*h) theta- in pure (pt .+^ vup, pt .+^ vlo)- ---revtripointsByDist :: (Real u, Floating u, FromPtSize u)- => LocThetaCF u (Point2 u, Point2 u, Point2 u)-revtripointsByDist = - tipBody $ \pt theta h -> - let theta' = circularModulo $ pi+theta - (vup,vlo) = triVecsByDist h (0.5*h) theta'- back_tip = pt .-^ avec theta h - in pure (back_tip .+^ vup, back_tip, back_tip .+^ vlo)-------- width = xchar_height--- filled with stroke colour!--triTLG :: (Floating u, Real u, FromPtSize u)- => Radian -> (PrimPath u -> Graphic u) -> LocThetaGraphic u-triTLG triang drawF = - promoteR2 $ \pt theta ->- localize bothStrokeColour $ - apply2R2 (tripointsByAngle triang) pt theta >>= \(u,v) -> - drawF $ vertexPath [pt,u,v]----tri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-tri90 = Arrowhead markHeight (triTLG (pi/2) filledPath)---tri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-tri60 = Arrowhead markHeight (triTLG (pi/3) filledPath)---tri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-tri45 = Arrowhead markHeight (triTLG (pi/4) filledPath)--otri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-otri90 = Arrowhead markHeight (triTLG (pi/2) solidClosedStroke)--otri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-otri60 = Arrowhead markHeight (triTLG (pi/3) solidClosedStroke)--otri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-otri45 = Arrowhead markHeight (triTLG (pi/4) solidClosedStroke)----- width = xchar_height--- filled with stroke colour!--revtriTLG :: (Floating u, Real u, FromPtSize u)- => Radian -> (PrimPath u -> Graphic u) -> LocThetaGraphic u-revtriTLG triang drawF = - promoteR2 $ \pt theta -> - localize bothStrokeColour $ - apply2R2 (revtripointsByAngle triang) pt theta >>= \(u,pt',v) -> - drawF $ vertexPath [u,pt',v]----revtri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-revtri90 = Arrowhead markHeightLessLineWidth- (revtriTLG (pi/2) filledPath)--revtri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-revtri60 = Arrowhead markHeightLessLineWidth- (revtriTLG (pi/3) filledPath)--revtri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-revtri45 = Arrowhead markHeightLessLineWidth- (revtriTLG (pi/4) filledPath)---orevtri90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-orevtri90 = Arrowhead markHeightLessLineWidth- (revtriTLG (pi/2) solidClosedStroke)--orevtri60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-orevtri60 = Arrowhead markHeightLessLineWidth- (revtriTLG (pi/3) solidClosedStroke)--orevtri45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-orevtri45 = Arrowhead markHeightLessLineWidth- (revtriTLG (pi/4) solidClosedStroke)----barbTLG :: (Floating u, Real u, FromPtSize u) => Radian -> LocThetaGraphic u-barbTLG ang = - promoteR2 $ \pt theta -> - apply2R2 (tripointsByAngle ang) pt theta >>= \(u,v) -> - solidOpenStroke $ vertexPath [u,pt,v]----barb90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-barb90 = Arrowhead noRetract (barbTLG (pi/2))--barb60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-barb60 = Arrowhead noRetract (barbTLG (pi/3))---barb45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-barb45 = Arrowhead noRetract (barbTLG (pi/4))----revbarbTLG :: (Floating u, Real u, FromPtSize u) => Radian -> LocThetaGraphic u-revbarbTLG ang = - promoteR2 $ \pt theta -> - apply2R2 (revtripointsByAngle ang) pt theta >>= \(u,pt',v) -> - solidOpenStroke $ vertexPath [u,pt',v]--revbarb90 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-revbarb90 = Arrowhead markHeight (revbarbTLG (pi/2))---revbarb60 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-revbarb60 = Arrowhead markHeight (revbarbTLG (pi/3))--revbarb45 :: (Floating u, Real u, FromPtSize u) => Arrowhead u-revbarb45 = Arrowhead markHeight (revbarbTLG (pi/4))---perpTLG :: (Floating u, FromPtSize u) => LocThetaGraphic u-perpTLG = - tipBody $ \pt theta h -> - let hh = 0.5*h in solidOpenStroke $ rperpPath hh pt theta---rperpPath :: Floating u => u -> Point2 u -> Radian -> PrimPath u-rperpPath hh ctr theta = primPath p0 [lineTo p1]- where- p0 = displacePerpendicular hh theta ctr- p1 = displacePerpendicular (-hh) theta ctr - ---perp :: (Floating u, FromPtSize u) => Arrowhead u-perp = Arrowhead noRetract perpTLG----bracketTLG :: (Floating u, FromPtSize u) => LocThetaGraphic u-bracketTLG = - tipBody $ \pt theta h -> - let hh = 0.5*h in solidOpenStroke $ rbracketPath hh pt theta---rbracketPath :: Floating u => u -> Point2 u -> Radian -> PrimPath u-rbracketPath hh pt theta = vertexPath [p0,p1,p2,p3]- where- p1 = displacePerpendicular hh theta pt- p0 = displaceParallel (-hh) theta p1- p2 = displacePerpendicular (-hh) theta pt- p3 = displaceParallel (-hh) theta p2- ----bracket :: (Floating u, FromPtSize u) => Arrowhead u-bracket = Arrowhead noRetract bracketTLG---diskTLG :: (Floating u, FromPtSize u) - => (u -> Point2 u -> Graphic u) -> LocThetaGraphic u-diskTLG drawF = - tipBody $ \pt theta h -> let hh = 0.5*h - ctr = pt .-^ avec theta hh - in drawF hh ctr---diskTip :: (Floating u, FromPtSize u) => Arrowhead u-diskTip = Arrowhead markHeight (diskTLG drawF)- where- drawF r pt = localize bothStrokeColour $ filledDisk r `at` pt---odiskTip :: (Floating u, FromPtSize u) => Arrowhead u-odiskTip = Arrowhead markHeight (diskTLG drawF)- where- drawF r pt = solidStrokedDisk r `at` pt---squareTLG :: (Floating u, FromPtSize u) - => (PrimPath u -> Graphic u) -> LocThetaGraphic u-squareTLG drawF = - tipBody $ \pt theta h -> drawF $ rsquarePath pt theta (0.5*h)---rsquarePath :: Floating u => Point2 u -> Radian -> u -> PrimPath u-rsquarePath pt theta hh = vertexPath [p0,p1,p2,p3]- where- p0 = displacePerpendicular hh theta pt- p3 = displacePerpendicular (-hh) theta pt- p1 = displaceParallel (-2*hh) theta p0- p2 = displaceParallel (-2*hh) theta p3- --squareTip :: (Floating u, FromPtSize u) => Arrowhead u-squareTip = Arrowhead markHeight (squareTLG drawF)- where- drawF = localize bothStrokeColour . filledPath---osquareTip :: (Floating u, FromPtSize u) => Arrowhead u-osquareTip = Arrowhead markHeight (squareTLG solidClosedStroke)---diamondTLG :: (Floating u, FromPtSize u) - => (PrimPath u -> Graphic u) -> LocThetaGraphic u-diamondTLG drawF = - tipBody $ \pt theta h -> drawF $ rdiamondPath pt theta (0.5*h)- --rdiamondPath :: Floating u => Point2 u -> Radian -> u -> PrimPath u-rdiamondPath pt theta hh = vertexPath [pt,p1,p2,p3]- where- ctr = displaceParallel (-2*hh) theta pt- p1 = displacePerpendicular hh theta ctr- p3 = displacePerpendicular (-hh) theta ctr- p2 = displaceParallel (-4*hh) theta pt- ---diamondTip :: (Floating u, FromPtSize u) => Arrowhead u-diamondTip = Arrowhead (fmap (2*) markHeightLessLineWidth) - (diamondTLG drawF)- where- drawF = localize bothStrokeColour . filledPath---odiamondTip :: (Floating u, FromPtSize u) => Arrowhead u-odiamondTip = Arrowhead (fmap (2*) markHeight) (diamondTLG solidClosedStroke)------- Note - points flipped to get the second trapezium to --- draw /underneath/.----curveTLG :: (Real u, Floating u, FromPtSize u) => LocThetaGraphic u-curveTLG = - tipBody $ \pt theta h -> - cxCurvePath pt theta (0.5*h) >>= \path ->- localize (joinRound . capRound) (solidOpenStroke path)---cxCurvePath :: (Real u, Floating u, FromPtSize u) - => Point2 u -> Radian -> u -> DrawingInfo (PrimPath u)-cxCurvePath pt theta hh =- apply2R2 tripointsByDist pt theta >>= \(tup,tlo) -> - let (u1,u2) = trapezoidFromBasePoints (0.25*hh) 0.5 pt tup- (l2,l1) = trapezoidFromBasePoints (0.25*hh) 0.5 tlo pt - in pure $ toPrimPath $ curve tup u2 u1 pt `append` curve pt l1 l2 tlo-----curveTip :: (Real u, Floating u, FromPtSize u) => Arrowhead u-curveTip = Arrowhead (fmap realToFrac getLineWidth) curveTLG----- Note - points flipped to get the second trapezium to --- draw /underneath/.----revcurveTLG :: (Real u, Floating u, FromPtSize u) => LocThetaGraphic u-revcurveTLG = - tipBody $ \pt theta h ->- cxRevcurvePath pt theta (0.5*h) >>= \path ->- localize (joinRound . capRound) (solidOpenStroke path)--cxRevcurvePath :: (Real u, Floating u, FromPtSize u) - => Point2 u -> Radian -> u -> DrawingInfo (PrimPath u)-cxRevcurvePath pt theta hh = - apply2R2 revtripointsByDist pt theta >>= \(tup,p1,tlo) -> - let (u1,u2) = trapezoidFromBasePoints (0.25*hh) 0.5 p1 tup- (l2,l1) = trapezoidFromBasePoints (0.25*hh) 0.5 tlo p1- in pure $ toPrimPath $ curve tup u2 u1 p1 `append` curve p1 l1 l2 tlo---revcurveTip :: (Real u, Floating u, FromPtSize u) => Arrowhead u-revcurveTip = Arrowhead markHeight revcurveTLG-
− src/Wumpus/Drawing/Chains.hs
@@ -1,29 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Chains--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Shim module.------ WARNING - very unstable.--------------------------------------------------------------------------------------module Wumpus.Drawing.Chains- (- module Wumpus.Drawing.Chains.Base- , module Wumpus.Drawing.Chains.Derived- -- ) where---import Wumpus.Drawing.Chains.Base-import Wumpus.Drawing.Chains.Derived
− src/Wumpus/Drawing/Chains/Base.hs
@@ -1,259 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Chains.Base--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Generate points in an iterated chain.--------------------------------------------------------------------------------------module Wumpus.Drawing.Chains.Base- (-- PointChain- , LocChain- , ConnectorChain-- -- * Unrolling chains- , unchain- , unchainU- , unchainZip- , unchainZipWith- , unconnectorChain-- -- * Building chains- , liftChainF-- ) where--import Wumpus.Basic.Kernel -- package: wumpus-basic--import Wumpus.Core -- package: wumpus-core------ | A 'PointChain' is a list of points. --- --- The list is typically inifinte so some attention must be given --- to choosing a chain drawing function and using it appropriately.--- -type PointChain u = [Point2 u]----- | A LocChain is a function from a starting point to a --- 'PointChain'.------ The list is often expected to be inifinte, but if it was a --- Stream it would loose the ability to use list comprehensions.--- -type LocChain u = LocDrawingInfo u (PointChain u)----- | A ConnectorChain is a function from a start- and end-point --- to a 'Chain'.--- -type ConnectorChain u = ConnectorCF u (PointChain u)------- | 'unchain' : @ unroll_count * alt_fun * draw_fun * chain -> LocCF @--- --- Unroll the chain, applying the @draw_fun@ to each point --- producing a LocCF (usually a 'LocGraphic'). If the chain does --- not produce any points the @alt_fun@ is applied to the start --- point.------ Note - commonly a 'Chain' may be infinite, so it is only --- unrolled a finite number of times - the @unrool_count@.------ This function has a very general type signature commonly it --- will be used at these types:------ > unchain :: (Num u, OPlus a) => --- > Int -> LocImage u a -> LocImage u a -> LocChain u -> LocImage u a--- >--- > unchain :: Num u => --- > Int -> LocGraphic u -> LocGraphic u -> LocChain u -> LocGraphic u----unchain :: (Num u, OPlus a) - => Int - -> LocCF u (ImageAns u a) - -> LocCF u (ImageAns u a) - -> LocChain u - -> LocCF u (ImageAns u a)-unchain i alt _ _ | i <= 0 = alt-unchain i alt gf chn = promoteR1 $ \p0 -> - (chn `at` p0) >>= \pts -> case pts of - [] -> alt `at` p0- [x] -> gf `at` x- (x:xs) -> go x (take (i-1) xs)- where- go x [] = gf `at` x- go x (y:ys) = (gf `at` x) `oplus` go y ys------- | 'unchain' : @ alt_fun * draw_fun * chain -> LocCF @--- --- /Unsafe/ version of 'unchain' - this function assumes the chain--- is finite which is not usually the case.------ This function has a very general type signature commonly it --- will be used at these type:------ > unchainU :: (Num u, OPlus a) => --- > LocImage u a -> LocImage u a -> LocChain u -> LocImage u a--- >--- > unchainU :: Num u => --- > LocGraphic u -> LocGraphic u -> LocChain u -> LocGraphic u------ \*\* WARNING \*\* - if the chain is infinite this function will --- not terminate.----unchainU :: (Num u, OPlus a)- => LocCF u (ImageAns u a) - -> LocCF u (ImageAns u a) - -> LocChain u - -> LocCF u (ImageAns u a)-unchainU alt gf chn = promoteR1 $ \p0 -> - (chn `at` p0) >>= \pts -> case pts of - [] -> alt `at` p0- [x] -> gf `at` x- (x:xs) -> go x xs- where- go x [] = gf `at` x- go x (y:ys) = (gf `at` x) `oplus` go y ys----- | 'unchainZip' : @ alt_fun * [draw_fun] * chain -> LocCF @--- --- Unroll the chain, zipping the list of @draw_funs@ to the list--- of points producing a LocCF (usually a 'LocGraphic'). If the --- chain does not produce any points the @alt_fun@ is applied to --- the start point.------ This function has a very general type signature commonly it --- will be used at these types:------ > unchainZip :: (Num u, OPlus a) => --- > LocImage u a -> [LocImage u a] -> LocChain u -> LocImage u a--- >--- > unchainZip :: Num u => --- > LocGraphic u -> [LocGraphic u] -> LocChain u -> LocGraphic u------ \*\* WARNING \*\* - the list of drawing functions should be --- finite. If both the list of drawing functions and the chain are --- infinite this function will not terminate.--- -unchainZip :: (Num u, OPlus a) - => LocCF u (ImageAns u a) - -> [LocCF u (ImageAns u a)] - -> LocChain u - -> LocCF u (ImageAns u a)-unchainZip alt [] _ = promoteR1 $ \p0 -> alt `at` p0-unchainZip alt (g:gs) chn = promoteR1 $ \p0 -> - (chn `at` p0) >>= \pts -> case pts of - [] -> alt `at` p0- [x] -> g `at` x- (x:xs) -> go (g `at` x) gs xs- where- go acc _ [] = acc- go acc [] _ = acc- go acc (f:fs) (p:ps) = go (acc `oplus` (f `at` p)) fs ps------ | 'unchainZipWith' : @ alt_fun * (a -> draw_fun) * [a] * chain -> LocCF @--- --- Version of 'unchainZip' where the list is some data rather --- than a drawing function and the @(a -> draw_fun)@ builder is --- applied to each element as part of the unrolling.--- --- Approximately this function is a @zipWith@ to the @zip@ of --- @unchainZip@.------ This function has a very general type signature commonly it --- will be used at these type:------ > unchainZipWith :: (Num u, OPlus a) => --- > LocImage u a -> (s -> LocImage u a) -> [s] -> LocChain u -> LocImage u a--- >--- > unchainZipWith :: Num u => --- > LocGraphic u -> (s -> LocGraphic u) -> [s] -> LocChain u -> LocGraphic u------ \*\* WARNING \*\* - if the chain and list are infinite this --- function will not terminate.----unchainZipWith :: (Num u, OPlus a)- => LocCF u (ImageAns u a) - -> (s -> LocCF u (ImageAns u a))- -> [s]- -> LocChain u - -> LocCF u (ImageAns u a)-unchainZipWith alt _ [] _ = promoteR1 $ \p0 -> alt `at` p0-unchainZipWith alt mkGF (s:ss) chn = promoteR1 $ \p0 -> - (chn `at` p0) >>= \pts -> case pts of - [] -> alt `at` p0- [x] -> mkGF s `at` x- (x:xs) -> go (mkGF s `at` x) ss xs- where- go acc _ [] = acc- go acc [] _ = acc- go acc (t:ts) (p:ps) = go (acc `oplus` (mkGF t `at` p)) ts ps------- | 'unconnectorChain' : @ alt_fun * draw_fun * conn_chain -> ConnectorCF @------ Unroll the chain produced between the implicit start and end --- points. Apply the @draw_fun@ to each point producing a --- ConnectorCF (usually a 'ConnectorGraphic'). If the chain does --- not produce any points, the @alt_fun@ is applied to the start --- and end points.------ This function has a very general type signature commonly it --- will be used at these types:------ > unconnectorChain :: (Num u, OPlus a) => --- > ConnectorImage u a -> LocImage u a -> ConnectorChain u -> ConnectorImage u a--- >--- > unconnectorChain :: Num u => --- > ConnectorGraphic u -> LocGraphic u -> ConnectorChain u -> ConnectorGraphic u-------unconnectorChain :: (Num u, OPlus a) - => ConnectorCF u (ImageAns u a) - -> LocCF u (ImageAns u a) - -> ConnectorChain u - -> ConnectorCF u (ImageAns u a)-unconnectorChain alt gf cchn = promoteR2 $ \p0 p1 -> - (connect cchn p0 p1) >>= \pts -> case pts of- [] -> connect alt p0 p1- [x] -> gf `at` x- (x:xs) -> go (gf `at` x) xs- where- go acc [] = acc- go acc (p:ps) = go (acc `oplus` (gf `at` p)) ps----------------------------------------------------------------------------------------- | 'liftChainF' : @ (point -> [point]) -> LocChain @------ Lift a pure chain generating function inot a 'LocChain'.----liftChainF :: (Point2 u -> PointChain u) -> LocChain u-liftChainF fn = promoteR1 $ \pt -> return $ fn pt-
− src/Wumpus/Drawing/Chains/Derived.hs
@@ -1,155 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Chains.Derived--- Copyright : (c) Stephen Tetley 2010-2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Generate points in an iterated chain.------ WARNING - very unstable.--------------------------------------------------------------------------------------module Wumpus.Drawing.Chains.Derived- (- - tableDown- , tableRight-- , horizontalPoints- , verticalPoints-- , horizontalSteps- , verticalSteps-- , innerHorizontals- , innerVerticals-- ) where--import Wumpus.Drawing.Chains.Base--import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Core -- package: wumpus-core---import Data.List ------------------------------------------------------------------------------------- Tables---- Note - for the minor runtime cost, pairing the row_width and --- row_height should make the API more /memorable/...----- | 'tableDown' : @ num_rows * (row_width, row_height) -> LocChain @------ The table grows down and right, the implicit initial point is --- @top-left@.----tableDown :: Num u => Int -> (u,u) -> LocChain u-tableDown n (rw,rh) = liftChainF $ \pt -> map (fn pt) ints- where- ints = iterate (+1) 0- fn pt i = let (x,y) = i `divMod` n - in displace (rw * fromIntegral x) (rh * fromIntegral (-y)) pt----- | 'tableRight' : @ num_cols * row_width * row_height -> LocChain @------ The table grows right and down, the implicit initial point is --- @top-left@.------ This chain is infinite.----tableRight :: Num u => Int -> (u,u) -> LocChain u-tableRight n (rw,rh) = liftChainF $ \pt -> map (fn pt) ints- where- ints = iterate (+1) 0- fn pt i = let (y,x) = i `divMod` n - in displace (rw * fromIntegral x) (rh * fromIntegral (-y)) pt------ | 'horizontalPoints' : @ horizontal_dist -> LocChain @------ The chain grows right by the supplied increment.------ This chain is infinite.----horizontalPoints :: Num u => u -> LocChain u-horizontalPoints dx = liftChainF $ iterate (displaceH dx)----- | 'verticalPoints' : @ vertical_dist -> LocChain @------ The chain grows up by the supplied increment.------ This chain is infinite.----verticalPoints :: Num u => u -> LocChain u-verticalPoints dy = liftChainF $ iterate (displaceV dy)----- | 'horizontalSteps' : @ [horizontal_dist] -> LocChain @------ This is a @scanl@ successive displacing the start point.------ This chain is finite (for finite input list).----horizontalSteps :: Num u => [u] -> LocChain u-horizontalSteps xs = liftChainF $ \pt -> scanl (flip displaceH) pt xs ----- | 'verticalSteps' : @ [vertical_dist] -> LocChain @------ This is a @scanl@ successive displacing the start point.------ This chain is finite (for finite input list).------ \*\* WARNING \*\* - name due to be changed. Current name is --- too general for this function. ----verticalSteps :: Num u => [u] -> LocChain u-verticalSteps ys = liftChainF $ \pt -> scanl (flip displaceV) pt ys---{-# INLINE [0] ceilingi #-}-ceilingi :: RealFrac a => a -> Int-ceilingi = ceiling----- | Note - horizontals are projected from the start point. The --- horizontal component of the second point is ignored.--- --- This chain is finite for well formed input.----innerHorizontals :: RealFrac u => u -> ConnectorChain u-innerHorizontals n = promoteR2 $ \a b -> return $ body a b- where- body (P2 x0 y0) (P2 x1 _) = unfoldr phi (n * fromIntegral z) - where z = ceilingi $ x0 / n- phi x | x < x1 = Just (P2 x y0, x+n)- | otherwise = Nothing-- ---- | Note - verticals are projected from the start point. The --- vertical component of the second point is ignored.--- --- This chain is finite for well formed input.----innerVerticals :: RealFrac u => u -> ConnectorChain u-innerVerticals n = promoteR2 $ \a b -> return $ body a b- where- body (P2 x0 y0) (P2 _ y1) = unfoldr phi (n * fromIntegral z)- where z = ceilingi $ y0 / n- phi y | y < y1 = Just (P2 x0 y, y+n)- | otherwise = Nothing-
+ src/Wumpus/Drawing/Connectors.hs view
@@ -0,0 +1,31 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Connectors+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Shim module for Connectors.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Connectors+ ( + module Wumpus.Drawing.Connectors.Arrowheads+ , module Wumpus.Drawing.Connectors.Base+ , module Wumpus.Drawing.Connectors.BoxConnectors+ , module Wumpus.Drawing.Connectors.ConnectorPaths+ , module Wumpus.Drawing.Connectors.Loop++ ) where++import Wumpus.Drawing.Connectors.Arrowheads+import Wumpus.Drawing.Connectors.Base+import Wumpus.Drawing.Connectors.BoxConnectors+import Wumpus.Drawing.Connectors.ConnectorPaths+import Wumpus.Drawing.Connectors.Loop
+ src/Wumpus/Drawing/Connectors/Arrowheads.hs view
@@ -0,0 +1,464 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Connectors.Arrowheads+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Arrowheads.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Connectors.Arrowheads+ (++ tri90+ , tri60+ , tri45+ , otri90+ , otri60+ , otri45++ , revtri90+ , revtri60+ , revtri45+ , orevtri90+ , orevtri60+ , orevtri45++ , barb90+ , barb60+ , barb45+ , revbarb90+ , revbarb60+ , revbarb45++ , perp+ , bracket++ , diskTip+ , odiskTip++ , squareTip+ , osquareTip++ , diamondTip+ , odiamondTip++ , diamondWideTip+ , odiamondWideTip++ , curveTip+ , revcurveTip++ ) where+++import Wumpus.Drawing.Connectors.Base+import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++import Control.Applicative++++-- | Arrow tips are drawn with a sloid line even if the connector+-- line is dashed (tips also override round corners)++solid_stroke_tip :: DrawingContextF+solid_stroke_tip = reset_drawing_metrics+++type PointGen = Radian -> [Vec2 En]+++filledTipPath :: PointGen -> LocThetaGraphic En+filledTipPath fn = + localize fill_use_stroke_colour $ promoteR2 $ \pt theta ->+ let vs = fn theta in vertexPP (map (pt .+^) vs) >>= filledPath+++closedTipPath :: PointGen -> LocThetaGraphic En+closedTipPath fn = + localize solid_stroke_tip $ promoteR2 $ \pt theta ->+ let vs = fn theta in vertexPP (map (pt .+^) vs) >>= closedStroke+++openTipPath :: PointGen -> LocThetaGraphic En+openTipPath fn = + localize solid_stroke_tip $ promoteR2 $ \pt theta ->+ let vs = fn theta in vertexPP (map (pt .+^) vs) >>= openStroke++++-- | Return @o-a@ and @o-b@:+--+-- > a+-- > .\+-- > . \+-- > .....o+-- > . /+-- > ./+-- > b+--+tripointsFromTip :: En -> Radian -> (Radian -> (Vec2 En, Vec2 En))+tripointsFromTip baselen ang = \theta -> + (avec (theta + au) hyp, avec (theta + ad) hyp)+ where+ half_ang = 0.5 * ang + au = pi - half_ang+ ad = half_ang + pi+ hyp = baselen / (fromRadian $ cos half_ang)++++-- | Return @o-x@ and @o-a@ and @o-b@:+--+-- > a+-- > /.+-- > / .+-- > .. x..o+-- > \ .+-- > \.+-- > b+--+revTripointsFromTip :: En -> Radian -> (Radian -> (Vec2 En, Vec2 En, Vec2 En))+revTripointsFromTip baselen ang = \theta -> + (avec theta (-baselen), oa theta, ob theta)+ where+ half_ang = 0.5 * ang + half_height = baselen * (fromRadian $ tan half_ang)+ oa = \theta -> avec (theta + ang90) half_height+ ob = \theta -> avec (theta - ang90) half_height+++++zeroVec :: Vec2 En+zeroVec = V2 0 0 ++ang90 :: Radian+ang90 = pi / 2++ang60 :: Radian+ang60 = pi / 3++ang45 :: Radian+ang45 = pi / 4+++len_one :: InterpretUnit u => Query u+len_one = uconvertCtx1 (1::En)++len_two :: InterpretUnit u => Query u+len_two = uconvertCtx1 (2::En)++len_half :: InterpretUnit u => Query u+len_half = uconvertCtx1 (0.5::En)++len_zero :: InterpretUnit u => Query u+len_zero = pure 0++retract_one :: InterpretUnit u => Query u+retract_one = uconvertCtx1 (1::En)++retract_two :: InterpretUnit u => Query u+retract_two = uconvertCtx1 (2::En)+++-- retract_half :: InterpretUnit u => Query u+-- retract_half = uconvertCtx1 (0.5::En)++retract_zero :: InterpretUnit u => Query u+retract_zero = pure 0++++filledTri :: InterpretUnit u => Radian -> ArrowTip u+filledTri ang = + makeArrowTip retract_one len_one (filledTipPath spec)+ where+ spec theta = let (v1,v2) = tripointsFromTip 1 ang theta + in [zeroVec, v1, v2]+++tri90 :: InterpretUnit u => ArrowTip u+tri90 = filledTri ang90++tri60 :: InterpretUnit u => ArrowTip u+tri60 = filledTri ang60++tri45 :: InterpretUnit u => ArrowTip u+tri45 = filledTri ang45+++strokedClosedTri :: InterpretUnit u => Radian -> ArrowTip u+strokedClosedTri ang = + makeArrowTip retract_one len_one (closedTipPath spec)+ where+ spec theta = let (v1,v2) = tripointsFromTip 1 ang theta + in [zeroVec, v1, v2]+++otri90 :: InterpretUnit u => ArrowTip u+otri90 = strokedClosedTri ang90++otri60 :: InterpretUnit u => ArrowTip u+otri60 = strokedClosedTri ang60++otri45 :: InterpretUnit u => ArrowTip u+otri45 = strokedClosedTri ang45+++filledRevTri :: InterpretUnit u => Radian -> ArrowTip u+filledRevTri ang = + makeArrowTip retract_one len_one (filledTipPath spec)+ where+ spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta + in [v0, v1, v2]++revtri90 :: InterpretUnit u => ArrowTip u+revtri90 = filledRevTri ang90++revtri60 :: InterpretUnit u => ArrowTip u+revtri60 = filledRevTri ang60++revtri45 :: InterpretUnit u => ArrowTip u+revtri45 = filledRevTri ang45+++strokedClosedRevTri :: InterpretUnit u => Radian -> ArrowTip u+strokedClosedRevTri ang = + makeArrowTip retract_one len_one (closedTipPath spec)+ where+ spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta + in [v0, v1, v2]+++orevtri90 :: InterpretUnit u => ArrowTip u+orevtri90 = strokedClosedRevTri ang90++orevtri60 :: InterpretUnit u => ArrowTip u+orevtri60 = strokedClosedRevTri ang60++orevtri45 :: InterpretUnit u => ArrowTip u+orevtri45 = strokedClosedRevTri ang45++++strokedBarb :: InterpretUnit u => Radian -> ArrowTip u+strokedBarb ang = + makeArrowTip retract_zero len_one (openTipPath spec)+ where+ spec theta = let (v1,v2) = tripointsFromTip 1 ang theta + in [v1,zeroVec,v2]+++barb90 :: InterpretUnit u => ArrowTip u+barb90 = strokedBarb ang90++barb60 :: InterpretUnit u => ArrowTip u+barb60 = strokedBarb ang60++barb45 :: InterpretUnit u => ArrowTip u+barb45 = strokedBarb ang45+++strokedRevBarb :: InterpretUnit u => Radian -> ArrowTip u+strokedRevBarb ang = + makeArrowTip retract_one len_one (openTipPath spec)+ where+ spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta + in [v1,v0,v2]++revbarb90 :: InterpretUnit u => ArrowTip u+revbarb90 = strokedRevBarb ang90++revbarb60 :: InterpretUnit u => ArrowTip u+revbarb60 = strokedRevBarb ang60++revbarb45 :: InterpretUnit u => ArrowTip u+revbarb45 = strokedRevBarb ang45++++perp :: InterpretUnit u => ArrowTip u+perp = + makeArrowTip retract_zero len_zero (openTipPath spec)+ where+ spec theta = let oa = avec (theta + ang90) 0.5+ ob = avec (theta - ang90) 0.5+ in [oa, ob]+++bracket :: InterpretUnit u => ArrowTip u+bracket = + makeArrowTip retract_zero len_half (openTipPath spec)+ where+ spec theta = let oa = avec (theta + ang90) 0.5+ ob = avec (theta - ang90) 0.5+ dv = avec theta (-0.5)+ in [ oa ^+^ dv, oa, ob, ob ^+^ dv ]++++diskTip :: InterpretUnit u => ArrowTip u+diskTip = + makeArrowTip retract_one len_one + (promoteR2 $ \pt theta -> body theta `at` pt)+ where+ body :: Radian -> LocGraphic En+ body theta = let v1 = avec theta (-0.5)+ in localize fill_use_stroke_colour $ + moveStart (displaceVec v1) (filledDisk 0.5)+++odiskTip :: InterpretUnit u => ArrowTip u+odiskTip = + makeArrowTip retract_one len_one + (promoteR2 $ \pt theta -> body theta `at` pt)+ where+ body :: Radian -> LocGraphic En+ body theta = let v1 = avec theta (-0.5)+ in localize solid_stroke_tip $ + moveStart (displaceVec v1) (strokedDisk 0.5)+++-- | squareSpec:+--+-- > +-- > ,-----a+-- > | |+-- > ...v.....o+-- > | | +-- > `-----b+--+squareSpec :: PointGen+squareSpec theta = [ oa ^+^ ov, oa, ob, ob ^+^ ov ]+ where+ oa = avec (theta + ang90) 0.5+ ob = avec (theta - ang90) 0.5+ ov = avec theta (-1)+ ++squareTip :: InterpretUnit u => ArrowTip u+squareTip = + makeArrowTip retract_one len_one (filledTipPath squareSpec)++osquareTip :: InterpretUnit u => ArrowTip u+osquareTip = + makeArrowTip retract_one len_one (closedTipPath squareSpec)++++-- | squareSpec:+--+-- > +-- > a+-- > / \+-- > ...w..v..o+-- > \ / +-- > b+--+diamondSpec :: En -> PointGen+diamondSpec width theta = [ ow, oa, zeroVec, ob ]+ where+ ow = avec theta (-width)+ ov = avec theta (negate $ 0.5 * width)+ oa = ov ^+^ avec (theta + ang90) 0.5+ ob = ov ^+^ avec (theta - ang90) 0.5+++diamondTip :: InterpretUnit u => ArrowTip u+diamondTip = + makeArrowTip retract_one len_one (filledTipPath $ diamondSpec 1)++odiamondTip :: InterpretUnit u => ArrowTip u+odiamondTip = + makeArrowTip retract_one len_one (closedTipPath $ diamondSpec 1)+++diamondWideTip :: InterpretUnit u => ArrowTip u+diamondWideTip = + makeArrowTip retract_two len_two (filledTipPath $ diamondSpec 2)++odiamondWideTip :: InterpretUnit u => ArrowTip u+odiamondWideTip = + makeArrowTip retract_two len_two (closedTipPath $ diamondSpec 2)+++curveTipPath :: Point2 En -> Radian -> AbsPath En+curveTipPath pt theta = + curve1 a b c pt `append` curve1 pt z y x+ where+ ow = avec theta (-1)+ a = pt .+^ ow ^+^ avec (theta + ang90) 0.5+ x = pt .+^ ow ^+^ avec (theta - ang90) 0.5++ (c,b) = trapezoidFromBasePoints 0.125 0.5 pt a+ (y,z) = trapezoidFromBasePoints 0.125 0.5 x pt+++curveTip :: InterpretUnit u => ArrowTip u+curveTip = + makeArrowTip retract_zero len_one+ (promoteR2 $ \pt theta -> + localize (join_bevel . solid_stroke_tip) $ + toPrimPath (curveTipPath pt theta) >>= openStroke)++++curveTipRevPath :: Point2 En -> Radian -> AbsPath En+curveTipRevPath pt theta = + curve1 a b c p2 `append` curve1 p2 z y x+ where+ p2 = pt .+^ avec theta (-1)+ a = pt .+^ avec (theta + ang90) 0.5+ x = pt .+^ avec (theta - ang90) 0.5++ (b,c) = trapezoidFromBasePoints 0.125 0.5 a p2+ (z,y) = trapezoidFromBasePoints 0.125 0.5 p2 x+++revcurveTip :: InterpretUnit u => ArrowTip u+revcurveTip = + makeArrowTip retract_one len_one+ (promoteR2 $ \pt theta -> + localize (join_bevel . solid_stroke_tip) $ + toPrimPath (curveTipRevPath pt theta) >>= openStroke)+++ +-- | 'trapezoidFromBasePoints' : +-- @ altitude * ratio_to_base * start_pt * end_pt -> (top_left, top_right) @+--+-- Control points form an isosceles trapezoid.+--+-- The two manufactured control points form the top corners, +-- so the supplied points map as @start_point == bottom_left@ and +-- @end_point == bottom_right@.+-- +trapezoidFromBasePoints :: (Real u, Floating u) + => u -> u -> Point2 u -> Point2 u + -> (Point2 u, Point2 u) +trapezoidFromBasePoints u ratio_to_base p1 p2 = (cp1, cp2)+ where+ base_vec = pvec p1 p2+ base_len = vlength base_vec+ theta = vdirection base_vec+ half_ulen = 0.5 * ratio_to_base * base_len+ base_mid = displaceParallel (0.5 * base_len) theta p1+ ubase_mid = displacePerpendicular u theta base_mid+ cp1 = displaceParallel (-half_ulen) theta ubase_mid+ cp2 = displaceParallel half_ulen theta ubase_mid
+ src/Wumpus/Drawing/Connectors/Base.hs view
@@ -0,0 +1,172 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Connectors.Base+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Connectors...+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Connectors.Base+ ( ++ Connector + , ArrowConnector+ , ArrowTip+ , makeArrowTip++ , leftArrow+ , rightArrow + , leftRightArrow+ , uniformArrow + + , promoteConn++ ) where++import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+++import Control.Applicative+++-- | The type of Connectors - a query from start and end point to +-- a Path.+--+type Connector u = ConnectorQuery u (AbsPath u)++++type ArrowConnector u = ConnectorImage u (AbsPath u)++type TipDraw = Point2 En -> Radian -> GraphicAns En++-- | TipAns - retract_distance * tip length * TipDraw+--+type TipAns u = (u, u, TipDraw)+++data ArrowTip u = ArrowTip { getArrowTip :: CF (TipAns u) }+++++-- | Connector with an arrow tip at the start point (i.e left).+--+leftArrow :: (Real u, Floating u, InterpretUnit u) + => ArrowTip u -> Connector u -> ArrowConnector u+leftArrow tipl conn = promoteR2 $ \p0 p1 ->+ apply2R2 conn p0 p1 >>= \full_path -> + getArrowTip tipl >>= \(dxl,wl,mkl) -> + uconvertCtxF p0 >>= \emp0 -> + let angl = tipDirectionL wl full_path+ short_path = shortenL dxl full_path+ deco = convertTipAns $ mkl emp0 angl+ in fmap (replaceAns full_path) $ + decorateR0 deco $ toPrimPath short_path >>= openStroke++-- | Connector with an arrow tip at the end point (i.e right).+--+rightArrow :: (Real u, Floating u, InterpretUnit u) + => ArrowTip u -> Connector u -> ArrowConnector u+rightArrow tipr conn = promoteR2 $ \p0 p1 ->+ apply2R2 conn p0 p1 >>= \full_path -> + getArrowTip tipr >>= \(dxr,wr,mkl) -> + uconvertCtxF p1 >>= \emp1 -> + let angr = tipDirectionR wr full_path+ short_path = shortenR dxr full_path+ deco = convertTipAns $ mkl emp1 angr+ in fmap (replaceAns full_path) $ + decorateR0 deco $ toPrimPath short_path >>= openStroke+++-- | Connector with two arrow tips, possibly different.+--+leftRightArrow :: (Real u, Floating u, InterpretUnit u) + => ArrowTip u -> ArrowTip u -> Connector u + -> ArrowConnector u+leftRightArrow tipl tipr conn = promoteR2 $ \p0 p1 ->+ apply2R2 conn p0 p1 >>= \full_path -> + getArrowTip tipl >>= \(dxl,wl,mkl) -> + getArrowTip tipr >>= \(dxr,wr,mkr) -> + uconvertCtxF p0 >>= \emp0 -> + uconvertCtxF p1 >>= \emp1 -> + let angl = tipDirectionL wl full_path+ angr = tipDirectionR wr full_path+ short_path = shortenPath dxl dxr full_path+ deco = convertTipAns $ mkl emp0 angl `oplus` mkr emp1 angr + in fmap (replaceAns full_path) $ + decorateR0 deco $ toPrimPath short_path >>= openStroke+++-- | Connector with the same arrow tip at both ends.+--+uniformArrow :: (Real u, Floating u, InterpretUnit u) + => ArrowTip u -> Connector u -> ArrowConnector u+uniformArrow utip conn = leftRightArrow utip utip conn+++++convertTipAns :: InterpretUnit u => GraphicAns En -> Graphic u+convertTipAns = uconvImageF . pure ++-- | Helper - direction looks best at half the retract distance.+--+tipDirectionL :: (Real u, Floating u) => u -> AbsPath u -> Radian+tipDirectionL u absp | u <= 0 = directionL absp+ |otherwise = directionL $ shortenL (0.5*u) absp+ +tipDirectionR :: (Real u, Floating u) => u -> AbsPath u -> Radian+tipDirectionR u absp | u <= 0 = directionR absp+ |otherwise = directionR $ shortenR (0.5*u) absp+ +++makeArrowTip :: Query u -> Query u -> LocThetaGraphic En -> ArrowTip u+makeArrowTip retractq lengthq gf = ArrowTip body+ where+ body = drawingCtx >>= \ctx -> + let rdist = runCF ctx retractq+ tlen = runCF ctx lengthq+ drawf = runCF ctx gf+ in return (rdist,tlen,drawf)+++-- | Promote a function from source and dest points to a connector +-- function accounting for the separator values in the +-- DrawingContext.+--+-- This should be used instead of @promoteR2@ for functions +-- building connectors.+--+promoteConn :: (Real u, Floating u, InterpretUnit u) + => (Point2 u -> Point2 u -> CF a) + -> CF (Point2 u -> Point2 u -> a)+promoteConn fn = promoteR2 $ \p0 p1 -> + connectorSrcSpace >>= \sep0 ->+ connectorDstSpace >>= \sep1 ->+ connectorSrcOffset >>= \off0 ->+ connectorDstOffset >>= \off1 ->+ let ang = vdirection $ pvec p0 p1+ in fn (displacePerpendicular off0 ang $ p0 .+^ avec ang sep0) + (displacePerpendicular off1 ang $ p1 .-^ avec ang sep1)+ +--+-- CAUTION - promoteConn projects the spacers along the (straight)+-- connector line. This might not be what is wanted for jointed+-- connectors.+--
+ src/Wumpus/Drawing/Connectors/BoxConnectors.hs view
@@ -0,0 +1,65 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Connectors.BoxConnectors+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Box connectors+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Connectors.BoxConnectors+ ( + ConnectorBox+ , connbox++ ) where++-- import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core+++-- NOTE - boxes (currently) seem to only support stroke otherwise+-- they would obliterate what they connect.++++-- | The type of BoxConnectors - a query from start and end point +-- to a Path. +-- +-- Note - unlike a @Connector@, a BoxConnnector is expected to be +-- closed, then filled, stroked or bordered.+--+type ConnectorBox u = ConnectorGraphic u+++--+-- DESIGN NOTE - boxes (probably) should not use source and dest+-- separators.+--+++-- | Draw a stroked, rectangular box around the connector points.+--+-- The rectangle will be inclined to the line.+--+connbox :: (Real u, Floating u, InterpretUnit u) + => ConnectorBox u+connbox = promoteR2 $ \p0 p1 -> + connectorSrcArm >>= \src_arm ->+ connectorDstArm >>= \dst_arm ->+ let ang = vdirection $ pvec p0 p1 + bl = displaceOrtho (V2 (-src_arm) (-src_arm)) ang p0+ tl = displaceOrtho (V2 (-src_arm) src_arm ) ang p0+ br = displaceOrtho (V2 dst_arm (-src_arm)) ang p1+ tr = displaceOrtho (V2 dst_arm src_arm ) ang p1+ in vertexPP [ bl, br, tr, tl ] >>= closedStroke
+ src/Wumpus/Drawing/Connectors/ConnectorPaths.hs view
@@ -0,0 +1,499 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Connectors.ConnectorPaths+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Primitive connectors+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Connectors.ConnectorPaths+ ( ++ connline+ , connarc+ , connhdiagh+ , connvdiagv+ + , conndiagh+ , conndiagv++ , connhdiag+ , connvdiag++ , connabar+ , connbbar++ , connaright+ , connbright++ , connhrr+ , connrrh+ , connvrr+ , connrrv++ , connaloop+ , connbloop++ , connhbezier+ , connvbezier++ ) where++import Wumpus.Drawing.Connectors.Base+import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Geometry.Quadrant -- package: wumpus-basic+import Wumpus.Basic.Kernel hiding ( promoteR2 )++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+++++++-- | Straight line connector.+--+connline :: (Real u, Floating u, InterpretUnit u) => Connector u+connline = promoteConn $ \p0 p1 -> return $ line1 p0 p1++++-- | Form an arc connector.+-- +-- If the conn_arc_angle in the Drawing context is positive the arc+-- will be formed /above/ the straight line joining the points. +-- If the angle is negative it will be drawn below. +-- +-- The notion of /above/ is respective to the line direction, of +-- course.+-- +--+connarc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) + => Connector u+connarc = promoteConn $ \p0 p1 -> + connectorArcAngle >>= \arc_ang ->+ let v1 = pvec p0 p1+ hlen = 0.5 * vlength v1+ ang = vdirection v1+ cp0 = p0 .+^ avec (ang + arc_ang) hlen+ cp1 = p1 .+^ avec (pi + ang - arc_ang) hlen+ in return $ curve1 p0 cp0 cp1 p1+++++-- | Horizontal-diagonal-horizontal connector.+--+-- > --@+-- > /+-- > o--+-- +-- Horizontal /arms/ are drawn from the start and end points, a+-- diagonal segment joins the arms. +-- +connhdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => Connector u+connhdiagh = promoteConn $ \p0 p1 -> + connectorSrcArm >>= \src_arm ->+ connectorDstArm >>= \dst_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> right p0 p1 src_arm dst_arm+ QUAD_SE -> right p0 p1 src_arm dst_arm+ _ -> left p0 p1 src_arm dst_arm+ where+ right p0 p1 h0 h1 = return $ vertexPath [ p0, p0 .+^ hvec h0+ , p1 .-^ hvec h1, p1 ]++ left p0 p1 h0 h1 = return $ vertexPath [ p0, p0 .-^ hvec h0 + , p1 .+^ hvec h1, p1 ]++++-- | Vertical-diagonal-vertical connector.+--+-- > @+-- > |+-- > \+-- > |+-- > o+--+-- Vertical /arms/ are drawn from the start and end points, a+-- diagonal segment joins the arms. +-- +connvdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => Connector u+connvdiagv = promoteConn $ \p0 p1 -> + connectorSrcArm >>= \src_arm ->+ connectorDstArm >>= \dst_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> up p0 p1 src_arm dst_arm+ QUAD_NW -> up p0 p1 src_arm dst_arm+ _ -> down p0 p1 src_arm dst_arm+ where+ up p0 p1 v0 v1 = return $ vertexPath [ p0, p0 .+^ vvec v0+ , p1 .-^ vvec v1, p1 ]++ down p0 p1 v0 v1 = return $ vertexPath [ p0, p0 .-^ vvec v0 + , p1 .+^ vvec v1, p1 ]++++-- | Diagonal-horizontal connector.+--+-- > --@+-- > /+-- > o+-- +-- Restricted variant of 'hconndiag' - a diagonal segment is drawn +-- from the start point joining a horizontal arm drawn from the +-- end point+-- +conndiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => Connector u+conndiagh = promoteConn $ \p0 p1 -> + connectorDstArm >>= \dst_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> right p0 p1 dst_arm+ QUAD_SE -> right p0 p1 dst_arm+ _ -> left p0 p1 dst_arm+ where+ right p0 p1 h1 = return $ vertexPath [ p0, p1 .-^ hvec h1, p1 ]++ left p0 p1 h1 = return $ vertexPath [ p0, p1 .+^ hvec h1, p1 ]+++-- | Diagonal-vertical connector.+--+-- > @+-- > |+-- > /+-- > o+--+-- Restricted variant of 'vconndiag' - a diagonal segment is drawn +-- from the start point joining a vertical arm drawn from the end +-- point.+-- +conndiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => Connector u+conndiagv = promoteConn $ \p0 p1 -> + connectorDstArm >>= \dst_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> up p0 p1 dst_arm+ QUAD_NW -> up p0 p1 dst_arm+ _ -> down p0 p1 dst_arm+ where+ up p0 p1 v1 = return $ vertexPath [ p0, p1 .-^ vvec v1, p1 ]++ down p0 p1 v1 = return $ vertexPath [ p0, p1 .+^ vvec v1, p1 ]++++-- | Horizontal-diagonal connector.+--+-- > @+-- > /+-- > o--+--+-- Restricted variant of 'hconndiag' - a horizontal arm is drawn+-- from the start point joining a diagonal segment drawn from the +-- end point.+-- +connhdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => Connector u+connhdiag = promoteConn $ \p0 p1 -> + connectorSrcArm >>= \src_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> right p0 p1 src_arm+ QUAD_SE -> right p0 p1 src_arm+ _ -> left p0 p1 src_arm+ where+ right p0 p1 h1 = return $ vertexPath [ p0, p0 .+^ hvec h1, p1 ]++ left p0 p1 h1 = return $ vertexPath [ p0, p0 .-^ hvec h1, p1 ]+++-- | Vertical-diagonal connector.+--+-- > @+-- > /+-- > |+-- > o+--+-- Restricted variant of 'vconndiag' - a horizontal arm is drawn+-- from the start point joining a vertical segment drawn from the +-- end point.+-- +connvdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => Connector u+connvdiag = promoteConn $ \p0 p1 -> + connectorSrcArm >>= \src_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> up p0 p1 src_arm+ QUAD_NW -> up p0 p1 src_arm+ _ -> down p0 p1 src_arm+ where+ up p0 p1 v1 = return $ vertexPath [ p0, p0 .+^ vvec v1, p1 ]++ down p0 p1 v1 = return $ vertexPath [ p0, p0 .-^ vvec v1, p1 ]+++-- DESIGN NOTE - should the concept of /above/ and /below/ use +-- quadrants?+--+++-- | Bar connector.+--+-- > ,----, +-- > | |+-- > o @ +--+-- The bar is drawn /above/ the points.+--+connabar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connabar = promoteConn $ \p0 p1 ->+ connectorSrcArm >>= \src_arm ->+ connectorDstArm >>= \dst_arm ->+ let ang = vdirection $ pvec p0 p1+ in return $ vertexPath [ p0, adisp_north src_arm ang p0+ , adisp_north dst_arm ang p1, p1 ]+++-- | Bar connector.+-- +-- > o @ +-- > | |+-- > '----' +--+-- The bar is drawn /below/ the points.+--+connbbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connbbar = promoteConn $ \p0 p1 ->+ connectorSrcArm >>= \src_arm ->+ connectorDstArm >>= \dst_arm ->+ let ang = vdirection $ pvec p0 p1+ in return $ vertexPath [ p0, adisp_south src_arm ang p0+ , adisp_south dst_arm ang p1, p1 ]++++-- | Right angle connector.+-- +-- > ,----@ +-- > | +-- > o +--+-- The bar is drawn /above/ the points.+--+connaright :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connaright = promoteConn $ \ p0@(P2 x0 _) p1@(P2 _ y1) ->+ let mid = P2 x0 y1 in return $ vertexPath [p0, mid, p1]+++-- | Right angle connector.+-- +-- > @ +-- > |+-- > o----' +--+-- The bar is drawn /below/ the points.+--+connbright :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connbright = promoteConn $ \ p0@(P2 _ y0) p1@(P2 x1 _) ->+ let mid = P2 x1 y0 in return $ vertexPath [p0, mid, p1]++++-- Helper ++-- | Derive the direction aka. sign of an arm.+--+directional :: (Num u, Ord u) => u -> u -> u -> u+directional src dst arm = if src < dst then arm else negate arm+ +++-- | Connector with two horizontal segements and a joining +-- vertical segment.+--+-- > ,--@+-- > |+-- > o----' +--+-- The length of the first horizontal segment is the source arm +-- length. The length of the final segment is the remaing +-- horizontal distance. +--+connhrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connhrr = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+ fmap (directional x0 x1) connectorSrcArm >>= \ src_arm -> + let a0 = p0 .+^ hvec src_arm+ a1 = a0 .+^ vvec (y1 - y0)+ in return $ vertexPath [p0, a0, a1, p1]+++-- | Connector with two horizontal segements and a joining +-- vertical segment.+--+-- > ,----@+-- > |+-- > o--' +--+-- The length of the final horizontal segment is the distination +-- arm length. The length of the initial segment is the remaining+-- horizontal distance. +--+connrrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connrrh = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+ fmap (directional x0 x1) connectorDstArm >>= \ dst_arm -> + let a1 = p1 .-^ hvec dst_arm+ a0 = a1 .-^ vvec (y1 - y0)+ in return $ vertexPath [p0, a0, a1, p1]+++-- | Connector with two right angles...+--+-- > @+-- > |+-- > ,----'+-- > |+-- > o +--+connvrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connvrr = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+ fmap (directional y0 y1) connectorSrcArm >>= \ src_arm -> + let a0 = p0 .+^ vvec src_arm+ a1 = a0 .+^ hvec (x1 - x0)+ in return $ vertexPath [p0, a0, a1, p1]+++-- | Connector with two right angles...+--+-- > @+-- > |+-- > ,----'+-- > |+-- > o +--+connrrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connrrv = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+ fmap (directional y0 y1) connectorDstArm >>= \ dst_arm -> + let a1 = p1 .-^ vvec dst_arm+ a0 = a1 .-^ hvec (x1 - x0)+ in return $ vertexPath [p0, a0, a1, p1]+++++-- | Loop connector.+--+-- > ,---------, +-- > | |+-- > '-o @--'+--+-- The loop is drawn /above/ the points.+--+connaloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connaloop = loopbody id++-- | Loop connector.+--+-- > ,-o @--, +-- > | |+-- > '---------'+--+-- The loop is drawn /above/ the points.+--+connbloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => Connector u+connbloop = loopbody negate++-- | Looping just differs on a negate...+--+loopbody :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => (u -> u) -> Connector u+loopbody fn = promoteConn $ \p0 p1 ->+ connectorSrcArm >>= \src_arm ->+ connectorDstArm >>= \dst_arm ->+ connectorLoopSize >>= \loop_len ->+ let ang = vdirection $ pvec p0 p1 + a0 = displaceParallel (negate src_arm) ang p0+ a1 = displacePerpendicular (fn loop_len) ang a0+ z0 = displaceParallel dst_arm ang p1+ z1 = displacePerpendicular (fn loop_len) ang z0+ in return $ vertexPath [ p0, a0, a1, z1, z0, p1 ]++-- | Bezier curve connector - the control points are positioned +-- horizontally respective to the source and dest.+--+-- > *--@ +-- > . +-- > . +-- > o--* +--+-- Note - the source and dest arm lengths are doubled, generally +-- this produces nicer curves.+--+connhbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => Connector u+connhbezier = promoteConn $ \p0 p1 -> + fmap (2*) connectorSrcArm >>= \src_arm ->+ fmap (2*) connectorDstArm >>= \dst_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> right p0 p1 src_arm dst_arm+ QUAD_SE -> right p0 p1 src_arm dst_arm+ _ -> left p0 p1 src_arm dst_arm+ where+ right p0 p1 h0 h1 = return $ curve1 p0 (p0 .+^ hvec h0) (p1 .-^ hvec h1) p1++ left p0 p1 h0 h1 = return $ curve1 p0 (p0 .-^ hvec h0) (p1 .+^ hvec h1) p1+++-- | Bezier curve connector - the control points are positioned +-- vertically respective to the source and dest.+--+-- > @ +-- > .| +-- > * . *+-- > |.+-- > o+--+-- Note - the source and dest arm lengths are doubled, generally +-- this produces nicer curves.+--+connvbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => Connector u+connvbezier = promoteConn $ \p0 p1 -> + fmap (2*) connectorSrcArm >>= \src_arm ->+ fmap (2*) connectorDstArm >>= \dst_arm ->+ case quadrant $ vdirection $ pvec p0 p1 of+ QUAD_NE -> up p0 p1 src_arm dst_arm+ QUAD_NW -> up p0 p1 src_arm dst_arm+ _ -> down p0 p1 src_arm dst_arm+ where+ up p0 p1 v0 v1 = return $ curve1 p0 (p0 .+^ vvec v0) (p1 .-^ vvec v1) p1++ down p0 p1 v0 v1 = return $ curve1 p0 (p0 .-^ vvec v0) (p1 .+^ vvec v1) p1+++
+ src/Wumpus/Drawing/Connectors/Loop.hs view
@@ -0,0 +1,86 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Connectors.Loop+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Open loop for a circle (useful for automata diagrams).+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Connectors.Loop+ ( + loop+ , loopPoints+ ) where+++import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Geometry.Base -- package: wumpus-basic+import Wumpus.Basic.Kernel+import Wumpus.Core -- package: wumpus-core+++import Data.AffineSpace -- package: vector-space++++-- | Note this has problems vis adding tips as the actual start+-- and end points are synthesized.+--+loop :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ConnectorQuery u (AbsPath u)+loop = promoteR2 $ \ctr radpt -> + let incl = lineDirection ctr radpt+ radius = abs $ vlength $ pvec ctr radpt+ ps = loopPoints radius ctr incl+ in return $ curvePath ps++-- | Note - intermediate names and quadrants represent a loop +-- drawn upwards.+-- +loopPoints :: (Real u, Floating u) => u -> Point2 u -> Radian -> [Point2 u]+loopPoints circ_radius circ_ctr incl = + [ startl, cp1, cp2, kitel, cp3, cp4, top, cp5, cp6, kiter, cp7, cp8, startr ]+ where+ hw = 1.25 * circ_radius+ height = 3.8 * circ_radius+ hminor = 2.72 * circ_radius+ hbase = circ_radius / 3+ theta = toRadian $ asin $ hbase / circ_radius+ start_vec = avec (circularModulo $ incl - quarter_pi) (0.26 * circ_radius)+ end_vec = avec (circularModulo $ incl + quarter_pi) (0.26 * circ_radius) + minor_down = negate $ 0.8 * circ_radius + major_up = 0.52 * circ_radius+ top_right = negate $ 0.8 * circ_radius+ top_left = 0.8 * circ_radius++ top = displaceParallel height incl circ_ctr+ kiter = displaceOrtho (V2 hminor (-hw)) incl circ_ctr+ kitel = displaceOrtho (V2 hminor (hw) ) incl circ_ctr+ + startr = circ_ctr .+^ avec (circularModulo $ incl - theta) circ_radius+ startl = circ_ctr .+^ avec (circularModulo $ incl + theta) circ_radius++ -- quadrant III+ cp1 = startl .+^ end_vec + cp2 = displaceParallel minor_down incl kitel++ -- quadrant II + cp3 = displaceParallel major_up incl kitel+ cp4 = displacePerpendicular top_left incl top++ -- quadrant I+ cp5 = displacePerpendicular top_right incl top+ cp6 = displaceParallel major_up incl kiter++ -- quadrant IV + cp7 = displaceParallel minor_down incl kiter+ cp8 = startr .+^ start_vec
src/Wumpus/Drawing/Dots/AnchorDots.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -58,9 +59,10 @@ import Wumpus.Drawing.Dots.Marks-import Wumpus.Drawing.Text.LRText+import Wumpus.Drawing.Text.Base.RotTextZero -import Wumpus.Basic.Geometry.Intersection -- package: wumpus-basic+import Wumpus.Basic.Geometry.Base -- package: wumpus-basic+import Wumpus.Basic.Geometry.Intersection import Wumpus.Basic.Geometry.Paths import Wumpus.Basic.Geometry.Quadrant import Wumpus.Basic.Kernel @@ -84,7 +86,6 @@ , radial_anchor :: Radian -> Point2 u , cardinal_anchor :: Cardinal -> Point2 u } - type instance DUnit (DotAnchor u) = u instance CenterAnchor (DotAnchor u) where@@ -153,7 +154,7 @@ fn theta = displaceVec (rectRadialVector hw hh theta) ctr -polygonAnchor :: (Real u, Floating u, FromPtSize u) +polygonAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) => [Point2 u] -> Point2 u -> DotAnchor u polygonAnchor ps ctr = DotAnchor { center_anchor = ctr@@ -172,7 +173,7 @@ in rectangleAnchor hw hh (bl .+^ vec hw hh) rectangleLDO :: (Real u, Floating u) - => u -> u -> LocDrawingInfo u (DotAnchor u)+ => u -> u -> LocQuery u (DotAnchor u) rectangleLDO w h = promoteR1 $ \pt -> pure $ rectangleAnchor (w*0.5) (h*0.5) pt @@ -182,7 +183,7 @@ (\theta -> ctr .+^ (avec theta rad)) (radialCardinal rad ctr) -circleLDO :: (Floating u, FromPtSize u) => LocDrawingInfo u (DotAnchor u)+circleLDO :: (Floating u, InterpretUnit u) => LocQuery u (DotAnchor u) circleLDO = promoteR1 $ \pt -> markHeight >>= \diam -> pure $ circleAnchor (diam * 0.5) pt@@ -191,8 +192,8 @@ -- This might be better taking a function: ctr -> poly_points -- ... ---polygonLDO :: (Real u, Floating u, FromPtSize u) - => (u -> Point2 u -> [Point2 u]) -> LocDrawingInfo u (DotAnchor u)+polygonLDO :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => (u -> Point2 u -> [Point2 u]) -> LocQuery u (DotAnchor u) polygonLDO mk = promoteR1 $ \ctr -> markHeight >>= \h -> let ps = mk h ctr in pure $ polygonAnchor ps ctr@@ -201,11 +202,11 @@ -------------------------------------------------------------------------------- -type DotLocImage u = LocImage u (DotAnchor u) +type DotLocImage u = LocImage u (DotAnchor u) type DDotLocImage = DotLocImage Double -dotChar :: (Floating u, Real u, FromPtSize u) => Char -> DotLocImage u+dotChar :: (Floating u, Real u, InterpretUnit u) => Char -> DotLocImage u dotChar ch = dotText [ch] @@ -216,73 +217,74 @@ -- -dotText :: (Floating u, Real u, FromPtSize u) => String -> DotLocImage u -dotText ss = fmap (bimapL bboxRectAnchor) (textAlignCenter ss)+dotText :: (Floating u, Real u, InterpretUnit u) => String -> DotLocImage u +dotText ss = pushR1 (mapAns bboxRectAnchor) $ ccTextline ss -- Note - maybe Wumpus-Basic should have a @swapAns@ function? -dotHLine :: (Floating u, FromPtSize u) => DotLocImage u+dotHLine :: (Floating u, InterpretUnit u) => DotLocImage u dotHLine = intoLocImage circleLDO markHLine -dotVLine :: (Floating u, FromPtSize u) => DotLocImage u+dotVLine :: (Floating u, InterpretUnit u) => DotLocImage u dotVLine = intoLocImage circleLDO markVLine -dotX :: (Floating u, FromPtSize u) => DotLocImage u+dotX :: (Floating u, InterpretUnit u) => DotLocImage u dotX = intoLocImage circleLDO markX -dotPlus :: (Floating u, FromPtSize u) => DotLocImage u+dotPlus :: (Floating u, InterpretUnit u) => DotLocImage u dotPlus = intoLocImage circleLDO markPlus -dotCross :: (Floating u, FromPtSize u) => DotLocImage u+dotCross :: (Floating u, InterpretUnit u) => DotLocImage u dotCross = intoLocImage circleLDO markCross -dotDiamond :: (Floating u, FromPtSize u) => DotLocImage u+dotDiamond :: (Floating u, InterpretUnit u) => DotLocImage u dotDiamond = intoLocImage circleLDO markDiamond -dotFDiamond :: (Floating u, FromPtSize u) => DotLocImage u+dotFDiamond :: (Floating u, InterpretUnit u) => DotLocImage u dotFDiamond = intoLocImage circleLDO markFDiamond -dotDisk :: (Floating u, FromPtSize u) => DotLocImage u+dotDisk :: (Floating u, InterpretUnit u) => DotLocImage u dotDisk = intoLocImage circleLDO markDisk -dotSquare :: (Floating u, Real u, FromPtSize u) => DotLocImage u+dotSquare :: (Floating u, Real u, InterpretUnit u) => DotLocImage u dotSquare = - lift0R1 markHeight >>= \h -> intoLocImage (rectangleLDO h h) markSquare+ markHeight >>= \h -> intoLocImage (rectangleLDO h h) markSquare -dotCircle :: (Floating u, FromPtSize u) => DotLocImage u+dotCircle :: (Floating u, InterpretUnit u) => DotLocImage u dotCircle = intoLocImage circleLDO markCircle -dotPentagon :: (Floating u, FromPtSize u) => DotLocImage u+dotPentagon :: (Floating u, InterpretUnit u) => DotLocImage u dotPentagon = intoLocImage circleLDO markPentagon -dotStar :: (Floating u, FromPtSize u) => DotLocImage u+dotStar :: (Floating u, InterpretUnit u) => DotLocImage u dotStar = intoLocImage circleLDO markStar -dotAsterisk :: (Floating u, FromPtSize u) => DotLocImage u+dotAsterisk :: (Floating u, InterpretUnit u) => DotLocImage u dotAsterisk = intoLocImage circleLDO markAsterisk -dotOPlus :: (Floating u, FromPtSize u) => DotLocImage u+dotOPlus :: (Floating u, InterpretUnit u) => DotLocImage u dotOPlus = intoLocImage circleLDO markOPlus -dotOCross :: (Floating u, FromPtSize u) => DotLocImage u+dotOCross :: (Floating u, InterpretUnit u) => DotLocImage u dotOCross = intoLocImage circleLDO markOCross -dotFOCross :: (Floating u, FromPtSize u) => DotLocImage u+dotFOCross :: (Floating u, InterpretUnit u) => DotLocImage u dotFOCross = intoLocImage circleLDO markFOCross -dotTriangle :: (Real u, Floating u, FromPtSize u) => DotLocImage u+dotTriangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => DotLocImage u dotTriangle = intoLocImage (polygonLDO fn) markTriangle where fn h ctr = let (bl,br,top) = equilateralTrianglePoints h ctr in [bl,br,top]
src/Wumpus/Drawing/Dots/Marks.hs view
@@ -50,7 +50,7 @@ ) where -import Wumpus.Drawing.Text.LRText+import Wumpus.Drawing.Text.Base.RotTextZero import Wumpus.Basic.Geometry.Paths -- package: wumpus-basic import Wumpus.Basic.Kernel @@ -60,7 +60,6 @@ import Data.AffineSpace -- package: vector-space import Data.VectorSpace -import Control.Applicative -- Marks should be the height of a lower-case letter... @@ -75,52 +74,52 @@ infixr 9 `renderPathWith` -renderPathWith :: LocDrawingInfo u (PrimPath u) - -> (PrimPath u -> Graphic u) +renderPathWith :: LocQuery u PrimPath + -> (PrimPath -> Graphic u) -> LocGraphic u-renderPathWith m k = m >>= (lift0R1 . k)+renderPathWith qy mk = promoteR1 $ \pt -> apply1R1 qy pt >>= mk -markChar :: (Real u, Floating u, FromPtSize u) => Char -> LocGraphic u+markChar :: (Real u, Floating u, InterpretUnit u) => Char -> LocGraphic u markChar ch = markText [ch] -markText :: (Real u, Floating u, FromPtSize u) => String -> LocGraphic u-markText ss = fmap (replaceL uNil) $ textAlignCenter ss+markText :: (Real u, Floating u, InterpretUnit u) => String -> LocGraphic u+markText ss = pushR1 ignoreAns $ ccTextline ss -- | Supplied point is the center. ---axialLine :: Fractional u => Vec2 u -> LocGraphic u-axialLine v = moveStart (\ctr -> ctr .-^ (0.5 *^ v)) (straightLine v)+axialLine :: (Fractional u, InterpretUnit u) => Vec2 u -> LocGraphic u+axialLine v = moveStart (\ctr -> ctr .-^ (0.5 *^ v)) (locStraightLine v) -markHLine :: (Fractional u, FromPtSize u) => LocGraphic u -markHLine = lift0R1 markHeight >>= \h -> axialLine (hvec h)+markHLine :: (Fractional u, InterpretUnit u) => LocGraphic u +markHLine = markHeight >>= \h -> axialLine (hvec h) -markVLine :: (Fractional u, FromPtSize u) => LocGraphic u -markVLine = lift0R1 markHeight >>= \h -> axialLine (vvec h) +markVLine :: (Fractional u, InterpretUnit u) => LocGraphic u +markVLine = markHeight >>= \h -> axialLine (vvec h) -markX :: (Fractional u, FromPtSize u) => LocGraphic u-markX = lift0R1 markHeight >>= mkX +markX :: (Fractional u, InterpretUnit u) => LocGraphic u+markX = markHeight >>= mkX where mkX h = let w = 0.75 * h in axialLine (vec w h) `oplus` axialLine (vec (-w) h) -markPlus :: (Fractional u, FromPtSize u) => LocGraphic u+markPlus :: (Fractional u, InterpretUnit u) => LocGraphic u markPlus = markVLine `oplus` markHLine -markCross :: (Floating u, FromPtSize u) => LocGraphic u+markCross :: (Floating u, InterpretUnit u) => LocGraphic u markCross = markHeight >>= mkCross where mkCross h = axialLine (avec ang h) `oplus` axialLine (avec (-ang) h)@@ -128,12 +127,11 @@ -- Note - height is extended slightly to look good... -pathDiamond :: (Fractional u, FromPtSize u) - => LocDrawingInfo u (PrimPath u)-pathDiamond = - promoteR1 $ \pt -> - markHeight >>= \h -> let cp = diamondCoordPath (0.5*h) (0.66*h) - in return $ coordinatePrimPath pt cp+pathDiamond :: (Fractional u, InterpretUnit u) + => LocQuery u PrimPath+pathDiamond = promoteR1 $ \pt -> + markHeight >>= \h -> let cp = diamondCoordPath (0.5*h) (0.66*h) + in coordinatePrimPath cp pt @@ -141,10 +139,10 @@ -- pathDiamond :: (ctx -> pt -> a) -- ans :: (ctx -> pt -> prim) -markDiamond :: (Fractional u, FromPtSize u) => LocGraphic u+markDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u markDiamond = pathDiamond `renderPathWith` closedStroke -markFDiamond :: (Fractional u, FromPtSize u) => LocGraphic u+markFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u markFDiamond = pathDiamond `renderPathWith` filledPath @@ -155,60 +153,60 @@ -- A named combinator might be better. -- -markBDiamond :: (Fractional u, FromPtSize u) => LocGraphic u+markBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u markBDiamond = pathDiamond `renderPathWith` borderedPath -- | Note disk is filled. ---markDisk :: (Fractional u, FromPtSize u) => LocGraphic u-markDisk = lift0R1 markHalfHeight >>= filledDisk +markDisk :: (Fractional u, InterpretUnit u) => LocGraphic u+markDisk = markHalfHeight >>= filledDisk -markSquare :: (Fractional u, FromPtSize u) => LocGraphic u+markSquare :: (Fractional u, InterpretUnit u) => LocGraphic u markSquare = - lift0R1 markHeight >>= \h -> + markHeight >>= \h -> let d = 0.5*(-h) in moveStart (displace d d) $ strokedRectangle h h -markCircle :: (Fractional u, FromPtSize u) => LocGraphic u-markCircle = lift0R1 markHalfHeight >>= strokedDisk +markCircle :: (Fractional u, InterpretUnit u) => LocGraphic u+markCircle = markHalfHeight >>= strokedDisk -markBCircle :: (Fractional u, FromPtSize u) => LocGraphic u-markBCircle = lift0R1 markHalfHeight >>= borderedDisk +markBCircle :: (Fractional u, InterpretUnit u) => LocGraphic u+markBCircle = markHalfHeight >>= borderedDisk -markPentagon :: (Floating u, FromPtSize u) => LocGraphic u-markPentagon = - promoteR1 $ \pt -> - markHeight >>= \h -> closedStroke $ pentagonPath pt (0.5*h)+markPentagon :: (Floating u, InterpretUnit u) => LocGraphic u+markPentagon = promoteR1 $ \pt -> + pentagonPath pt >>= closedStroke where- pentagonPath pt hh = coordinatePrimPath pt $ polygonCoordPath 5 hh+ pentagonPath pt = markHalfHeight >>= \hh -> + coordinatePrimPath (polygonCoordPath 5 hh) pt -markStar :: (Floating u, FromPtSize u) => LocGraphic u -markStar = lift0R1 markHeight >>= \h -> starLines (0.5*h)+markStar :: (Floating u, InterpretUnit u) => LocGraphic u +markStar = markHeight >>= \h -> starLines (0.5*h) -starLines :: Floating u => u -> LocGraphic u-starLines hh = - promoteR1 $ \ctr -> let cp = polygonCoordPath 5 hh- in step $ map (fn ctr) $ cp ctr+starLines :: (Floating u, InterpretUnit u) => u -> LocGraphic u+starLines hh = promoteR1 $ \ctr -> + let cp = polygonCoordPath 5 hh+ in step $ map (fn ctr) $ cp ctr where- fn p0 p1 = openStroke $ primPath p0 [lineTo p1]+ fn p0 p1 = straightLine p0 p1 step (x:xs) = oconcat x xs step _ = error "starLines - unreachable" -markAsterisk :: (Floating u, FromPtSize u) => LocGraphic u-markAsterisk = lift0R1 markHeight >>= asteriskLines+markAsterisk :: (Floating u, InterpretUnit u) => LocGraphic u+markAsterisk = markHeight >>= asteriskLines -asteriskLines :: Floating u => u -> LocGraphic u+asteriskLines :: (Floating u, InterpretUnit u) => u -> LocGraphic u asteriskLines h = lineF1 `oplus` lineF2 `oplus` lineF3 where ang = (pi*2) / 6@@ -217,27 +215,28 @@ lineF3 = axialLine (avec ((pi*0.5) + ang + ang) h) -markOPlus :: (Fractional u, FromPtSize u) => LocGraphic u+markOPlus :: (Fractional u, InterpretUnit u) => LocGraphic u markOPlus = markCircle `oplus` markPlus -markOCross :: (Floating u, FromPtSize u) => LocGraphic u+markOCross :: (Floating u, InterpretUnit u) => LocGraphic u markOCross = markCircle `oplus` markCross -markFOCross :: (Floating u, FromPtSize u) => LocGraphic u+markFOCross :: (Floating u, InterpretUnit u) => LocGraphic u markFOCross = markCross `oplus` markBCircle --- bkCircle :: (Fractional u, FromPtSize u) => LocGraphic u+-- bkCircle :: (Fractional u, InterpretUnit u) => LocGraphic u -- bkCircle = disk (fillAttr attr) (0.5*markHeight attr) -markTriangle :: (Floating u, FromPtSize u) => LocGraphic u+markTriangle :: (Floating u, InterpretUnit u) => LocGraphic u markTriangle = tripath `renderPathWith` closedStroke where tripath = promoteR1 $ \pt -> - markHeight >>= \h -> let cp = equilateralTriangleCoordPath h - in pure $ coordinatePrimPath pt cp+ markHeight >>= \h -> + let cp = equilateralTriangleCoordPath h+ in coordinatePrimPath cp pt
+ src/Wumpus/Drawing/Extras/Axes.hs view
@@ -0,0 +1,49 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Extras.Axes+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Drawing grids+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Extras.Axes+ ( + + orthontAxes++ ) where++import Wumpus.Drawing.Connectors++import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Core -- package: wumpus-core+++-- Note - axes need labels working out...+++-- | Draw axes from (0,0).+--+orthontAxes :: (Real u, Floating u, InterpretUnit u)+ => (Double, Double) -> Graphic u+orthontAxes (w,h) = + snapmove (1,1) >>= \(V2 w1 h1) ->+ let conn1 = rightArrow barb45 connline+ uw = w1 * realToFrac w+ uh = h1 * realToFrac h+ ptX = displaceH uw zeroPt+ ptY = displaceV uh zeroPt+ in localize cap_square $ graphic_ (connect conn1 zeroPt ptX) + `oplus` graphic_ (connect conn1 zeroPt ptY)+++ +
+ src/Wumpus/Drawing/Extras/Grids.hs view
@@ -0,0 +1,229 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Extras.Grids+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Drawing grids+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Extras.Grids+ ( + + GridContextF+ , grid+ , standard_grid+ , grid_major_colour+ , grid_major_line_width+ , grid_major_dotnum+ , grid_minor_subdivisions+ , grid_minor_colour+ , grid_minor_line_width+ , grid_minor_dotnum+ , grid_point_size+ , grid_label_colour++ ) where+++import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Colour ( black )+++++type GridContextF = GridProps -> GridProps++-- | GridProps control the drawing of grids.+-- +data GridProps = GridProps+ { gp_major_colour :: RGBi+ , gp_major_lnwidth :: Double+ , gp_major_dotnum :: Int+ , gp_minor_subdivs :: Int+ , gp_minor_colour :: RGBi+ , gp_minor_lnwidth :: Double+ , gp_minor_dotnum :: Int+ , gp_point_size :: FontSize+ , gp_label_colour :: RGBi+ }++default_grid_props :: GridProps+default_grid_props = + GridProps { gp_major_colour = grey1+ , gp_major_lnwidth = 1+ , gp_major_dotnum = 0+ , gp_minor_subdivs = 5+ , gp_minor_colour = grey2+ , gp_minor_lnwidth = 0.5+ , gp_minor_dotnum = 0+ , gp_point_size = 10+ , gp_label_colour = black+ }+ where+ grey1 = RGBi 100 100 100+ grey2 = RGBi 150 150 150 ++++grid :: (Fractional u, InterpretUnit u) + => GridContextF -> (Int,Int) -> (Int,Int) -> Graphic u +grid upd bl tr = go (upd default_grid_props)+ where+ go props | gp_minor_subdivs props < 1 = gridMajor bl tr props+ | otherwise = gridMinor bl tr props `oplus` gridMajor bl tr props++++standard_grid :: GridContextF+standard_grid = id++grid_major_colour :: RGBi -> GridContextF+grid_major_colour rgb = (\s -> s { gp_major_colour = rgb })++grid_major_line_width :: Double -> GridContextF+grid_major_line_width lw = (\s -> s { gp_major_lnwidth = lw })++grid_major_dotnum :: Int -> GridContextF+grid_major_dotnum n = (\s -> s { gp_major_dotnum = n })++grid_minor_subdivisions :: Int -> GridContextF+grid_minor_subdivisions n = (\s -> s { gp_major_dotnum = n })++grid_minor_colour :: RGBi -> GridContextF+grid_minor_colour rgb = (\s -> s { gp_minor_colour = rgb })++grid_minor_line_width :: Double -> GridContextF+grid_minor_line_width lw = (\s -> s { gp_minor_lnwidth = lw })++grid_minor_dotnum :: Int -> GridContextF+grid_minor_dotnum n = (\s -> s { gp_minor_dotnum = n })+++grid_point_size :: FontSize -> GridContextF+grid_point_size i = (\s -> s { gp_point_size = i })+++grid_label_colour :: RGBi -> GridContextF+grid_label_colour rgb = (\s -> s { gp_label_colour = rgb })++++--------------------------------------------------------------------------------++++gridMinor :: (Fractional u, InterpretUnit u) + => (Int,Int) -> (Int,Int) -> GridProps -> Graphic u+gridMinor bl tr props = + let mi = minorInterior bl tr (gp_minor_subdivs props)+ minF = lineProps (gp_minor_colour props) (gp_minor_lnwidth props)+ (gp_minor_dotnum props)+ in localize minF mi++gridMajor :: (Fractional u, InterpretUnit u) + => (Int,Int) -> (Int,Int) -> GridProps -> Graphic u+gridMajor bl tr props = + let mj = majorInterior bl tr+ outer = outerRect bl tr+ majF = lineProps (gp_major_colour props) (gp_major_lnwidth props)+ (gp_major_dotnum props) + in localize majF (mj `oplus` outer)+++++lineProps :: RGBi -> Double -> Int -> DrawingContextF+lineProps rgb lw n + | n < 1 = stroke_colour rgb . set_line_width lw . solid_line + | otherwise = stroke_colour rgb . set_line_width lw . dashesF + where+ dashesF = set_dash_pattern $ Dash 0 [(1,n)]+++-- | Coordinates are expected to be normalized.+--+outerRect :: (Fractional u, InterpretUnit u) + => (Int,Int) -> (Int,Int) -> Graphic u +outerRect cbl@(xmin,ymin) (xmaj,ymaj) = + snapmove (xmaj-xmin, ymaj-ymin) >>= \(V2 uw uh) ->+ position cbl >>= \bl ->+ strokedRectangle uw uh `at` bl++++-- | The major interior is the snap grid. +--+majorInterior :: (Fractional u, InterpretUnit u)+ => (Int,Int) -> (Int,Int) -> Graphic u+majorInterior cbl@(xmin,ymin) (xmaj,ymaj) = + snapmove (xmaj-xmin, ymaj-ymin) >>= \(V2 uw uh) ->+ snapmove (1,1) >>= \(V2 w1 h1) ->+ position cbl >>= \bl ->+ let xcount = sub1 (xmaj - xmin)+ ycount = sub1 (ymaj - ymin)+ hlines = chainlike ycount (displaceV h1) (hline uw)+ vlines = chainlike xcount (displaceH w1) (vline uh)+ in (apply1R1 hlines $ displaceV h1 bl) + `oplus` (apply1R1 vlines $ displaceH w1 bl) +++++-- | The minor interior divides each element of the snap grid.+--+minorInterior :: (Fractional u, InterpretUnit u)+ => (Int,Int) -> (Int,Int) -> Int -> Graphic u+minorInterior cbl@(xmin,ymin) (xmaj,ymaj) scount = + snapmove (xmaj-xmin, ymaj-ymin) >>= \(V2 uw uh) ->+ snapmove (1,1) >>= \(V2 w1 h1) ->+ position cbl >>= \bl ->+ let xcount = xmaj - xmin+ ycount = ymaj - ymin+ subw1 = w1 / fromIntegral scount+ subh1 = h1 / fromIntegral scount+ hlines1 = moveStart (displaceV subh1) + $ chainlike (scount-1) (displaceV subh1) (hline uw)++ vlines1 = moveStart (displaceH subw1) + $ chainlike (scount-1) (displaceH subw1) (vline uh)+ hlines = chainlike ycount (displaceV h1) hlines1+ vlines = chainlike xcount (displaceH w1) vlines1++ in (apply1R1 hlines bl) + `oplus` (apply1R1 vlines bl) ++-- This doesn\'t work as an advGraphic+++-- | This is an operation chain should support, but chain needs a +-- rethink...+--+chainlike :: Int -> PointDisplace u -> LocGraphic u -> LocGraphic u+chainlike i mv g = promoteR1 $ \start -> go (i-1) (g `at` start) (mv start)+ where+ go n acc pt | n < 1 = acc+ | otherwise = go (n-1) (acc `oplus` (g `at` pt)) (mv pt)+ +++vline :: InterpretUnit u => u -> LocGraphic u +vline len = locStraightLine $ vvec len++hline :: InterpretUnit u => u -> LocGraphic u +hline len = locStraightLine $ hvec len++++sub1 :: Num u => u -> u+sub1 = subtract 1++
+ src/Wumpus/Drawing/Extras/Turtle/TurtleClass.hs view
@@ -0,0 +1,91 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Extras.Turtle.TurtleClass+-- Copyright : (c) Stephen Tetley 2010+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC +--+-- Turtle monad and monad transformer.+--+-- The Turtle monad embodies the LOGO style of imperative +-- drawing - sending commands to update the a cursor.+--+-- While Wumpus generally aims for a more compositional,+-- \"coordinate-free\" style of drawing, some types of diagram +-- are more easily expressed in the LOGO style.+--+-- Note - as turtle drawing with Wumpus is a /local effect/, +-- there is only one instance of TurtleM. Potentially TurtleM +-- will be removed and the functions implemented directly. +--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Extras.Turtle.TurtleClass+ (++ Coord++ , TurtleM(..)++ , setsLoc+ , setsLoc_++ -- * movement+ , resetLoc+ , moveLeft+ , moveRight+ , moveUp+ , moveDown+ , nextLine+ ++ ) where++++type Coord = (Int,Int)+++class Monad m => TurtleM m where+ getLoc :: m (Int,Int)+ setLoc :: (Int,Int) -> m ()+ getOrigin :: m (Int,Int)+ setOrigin :: (Int,Int) -> m ()++++setsLoc :: TurtleM m => (Coord -> (a,Coord)) -> m a+setsLoc f = getLoc >>= \coord -> + let (a,coord') = f coord in setLoc coord' >> return a++setsLoc_ :: TurtleM m => (Coord -> Coord) -> m ()+setsLoc_ f = getLoc >>= \coord -> setLoc (f coord)+++resetLoc :: TurtleM m => m ()+resetLoc = getOrigin >>= setLoc+++moveRight :: TurtleM m => m ()+moveRight = setsLoc_ $ \(x,y)-> (x+1, y)+++moveLeft :: TurtleM m => m ()+moveLeft = setsLoc_ $ \(x,y) -> (x-1,y)++moveUp :: TurtleM m => m ()+moveUp = setsLoc_ $ \(x,y) -> (x,y+1)++moveDown :: TurtleM m => m ()+moveDown = setsLoc_ $ \(x,y) -> (x ,y-1)+++nextLine :: TurtleM m => m ()+nextLine = getOrigin >>= \(ox,_) ->+ setsLoc_ $ \(_,y) -> (ox,y-1)+
+ src/Wumpus/Drawing/Extras/Turtle/TurtleMonad.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Extras.Turtle.TurtleMonad+-- Copyright : (c) Stephen Tetley 2010+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC +--+-- Turtle monad transformer.+--+-- The Turtle monad embodies the LOGO style of imperative +-- drawing - sending commands to update the a cursor.+--+-- While Wumpus generally aims for a more compositional,+-- \"coordinate-free\" style of drawing, some types of +-- diagram are more easily expressed in the LOGO style.+--+-- Turtle is only a transformer - it is intended to be run within+-- a 'Drawing'.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Extras.Turtle.TurtleMonad+ (+ -- * Re-exports+ module Wumpus.Drawing.Extras.Turtle.TurtleClass++ -- * Turtle transformer+ , TurtleT+ , runTurtleT++ + ) where++import Wumpus.Drawing.Extras.Turtle.TurtleClass++import Wumpus.Basic.Kernel -- package: wumpus-basic+++import Control.Applicative+import Control.Monad+++-- Note - if Turtle is now just a /local effect/ monad is the +-- Turtle class still needed? Afterall, there is (probably)+-- only ever going to be one instance.+--++-- Turtle is a Reader / State monad+-- +-- The env is the horizontal and vertical move distances.+-- +-- The state is the current coordinate and the origin.+--++data TurtleState = TurtleState + { _turtle_origin :: (Int,Int)+ , _current_coord :: (Int,Int)+ }++newtype TurtleT u m a = TurtleT { + getTurtleT :: TurtleState -> m (a, TurtleState) }++ +type instance MonUnit (TurtleT u m a) = u++-- Functor++++instance Monad m => Functor (TurtleT u m) where+ fmap f m = TurtleT $ \s -> getTurtleT m s >>= \(a,s') ->+ return (f a, s')+++-- Applicative ++instance Monad m => Applicative (TurtleT u m) where+ pure a = TurtleT $ \s -> return (a,s)+ mf <*> ma = TurtleT $ \s -> getTurtleT mf s >>= \(f,s') ->+ getTurtleT ma s' >>= \(a,s'') ->+ return (f a,s'') +++-- Monad ++instance Monad m => Monad (TurtleT u m) where+ return a = TurtleT $ \s -> return (a,s)+ m >>= k = TurtleT $ \s -> getTurtleT m s >>= \(a,s') ->+ (getTurtleT . k) a s'+++++instance Monad m => TurtleM (TurtleT u m) where+ getLoc = TurtleT $ \s@(TurtleState _ c) -> return (c,s)+ setLoc c = TurtleT $ \(TurtleState o _) -> return ((),TurtleState o c)+ getOrigin = TurtleT $ \s@(TurtleState o _) -> return (o,s)+ setOrigin o = TurtleT $ \(TurtleState _ c) -> return ((),TurtleState o c)+++runTurtleT :: (Monad m, Num u) + => (Int,Int) -> TurtleT u m a -> m a+runTurtleT ogin mf = getTurtleT mf st0 >>= \(a,_) -> return a+ where + st0 = TurtleState ogin ogin ++++----------------------------------------------------------------------------------+-- Cross instances++instance DrawingCtxM m => DrawingCtxM (TurtleT u m) where+ askDC = TurtleT $ \s -> askDC >>= \ ctx -> return (ctx,s)+ localize upd mf = TurtleT $ \s -> localize upd (getTurtleT mf s)+++-- This needs undecidable instances...++instance (Monad m, TraceM m, u ~ MonUnit (m ()) ) => TraceM (TurtleT u m) where+ trace a = TurtleT $ \s -> trace a >> return ((),s)+ fontDelta mf = TurtleT $ \s -> fontDelta $ getTurtleT mf s++
− src/Wumpus/Drawing/Grids.hs
@@ -1,67 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Grids--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Drawing grids--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Grids- ( - grid- , interiorGrid-- ) where--import Wumpus.Drawing.Chains--import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Core -- package: wumpus-core----grid :: Fractional u => (Int,Int) -> u -> LocGraphic u-grid (nx,ny) incr - | nx < 1 || ny < 1 = emptyLocGraphic- | otherwise = promoteR1 $ \sw -> - let rw = incr * fromIntegral nx- rh = incr * fromIntegral ny- xchn = horizontalPoints incr- ychn = verticalPoints incr- vline1 = straightLine (vvec rh)- hline1 = straightLine (hvec rw)- vlines = unchain nx emptyLocGraphic vline1 xchn- hlines = unchain ny emptyLocGraphic hline1 ychn- in (hlines `oplus` vlines `oplus` strokedRectangle rw rh) `at` sw------ | 'interiorGrid' : @ increment -> ConnectorGraphic @------ Draw the interior lines of a grid between the /connector/ --- points - start point is interpreted as bottom-left, end-point--- is interpreted as top right.------ The interior lines are calculated with repsect to the 0 and the --- increment, for instance with an increment of 10 but a start --- point @(15,0)@ lines are drawn from @(20,0), (30,0)@ etc.----interiorGrid :: RealFrac u => u -> ConnectorGraphic u-interiorGrid incr = promoteR2 $ \sw ne ->- let xcc = innerHorizontals incr- ycc = innerVerticals incr- (V2 vx vy) = pvec sw ne- hline1 = straightLine (hvec vx)- vline1 = straightLine (vvec vy)- vlines = unconnectorChain emptyConnectorGraphic vline1 xcc- hlines = unconnectorChain emptyConnectorGraphic hline1 ycc- in connect (hlines `oplus` vlines) sw ne-
− src/Wumpus/Drawing/Paths.hs
@@ -1,32 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths--- Copyright : (c) Stephen Tetley 2010-2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Shim import module for Paths.------ Note MonadicConstruction is not exported, this module is --- somewhat out-of-date and needs a re-think.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths - ( -- module Wumpus.Drawing.Paths.Base- , module Wumpus.Drawing.Paths.Connectors- , module Wumpus.Drawing.Paths.ControlPoints-- ) where--import Wumpus.Drawing.Paths.Base-import Wumpus.Drawing.Paths.Connectors-import Wumpus.Drawing.Paths.ControlPoints-
+ src/Wumpus/Drawing/Paths/Absolute.hs view
@@ -0,0 +1,28 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Abolute+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Shim import module for the Absolute Path modules.+--+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Absolute+ ( ++ module Wumpus.Drawing.Paths.Base.AbsBuilder+ , module Wumpus.Drawing.Paths.Base.AbsPath++ ) where++import Wumpus.Drawing.Paths.Base.AbsBuilder+import Wumpus.Drawing.Paths.Base.AbsPath+
− src/Wumpus/Drawing/Paths/Base.hs
@@ -1,585 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.Base--- Copyright : (c) Stephen Tetley 2010-2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Extended path type - more amenable for complex drawings than--- the type in Wumpus-Core.------ \*\* WARNING \*\* this module is an experiment, and may --- change significantly or even be dropped from future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.Base- ( -- Path- , DPath- , length- , append- , pconcat- , line- , curve- , pivot- , traceLinePoints- , traceCurvePoints- , curveByAngles-- , toPrimPath -- , tipL- , tipR-- , shortenPath- , shortenL- , shortenR- , directionL- , directionR-- , midway- , midway_- , atstart- , atstart_- , atend- , atend_-- , PathViewL(..)- , DPathViewL- , PathViewR(..)- , DPathViewR- , PathSegment(..)- , DPathSegment- , pathViewL- , pathViewR--- , roundTrail- , roundInterior-- ) where----import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Utils.JoinList ( JoinList, ViewL(..), viewl- , ViewR(..), viewr, cons, snoc, join )-import qualified Wumpus.Basic.Utils.JoinList as JL--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace--import Data.List ( foldl' ) --import Prelude hiding ( length )--data Path u = Path { _path_length :: u - , _path_start :: Point2 u- , _path_elements :: JoinList (PathSeg u)- , _path_end :: Point2 u- }- deriving (Eq,Show)--type DPath = Path Double---- Annotating each segment with length is \*\* good \*\*.--- Makes it much more efficient to find the midway point.------ But what do we do about the start point:------ a) put it in the segment - too much info in the type, allows --- consistency problems vis-a-vis gaps in the path.------ b) leave it out - too little info in the type, allows --- consistency problems with length.------ Option (a) is probably most convenient espcially as the --- constructors won\'t be exported.---- Annotation is length...--- -data PathSeg u = LineSeg { _line_length :: u - , _line_start :: Point2 u- , _line_end :: Point2 u- }- | CurveSeg { _curve_length :: u - , _curve_start :: Point2 u- , _ctrl_pt_one :: Point2 u- , _ctrl_pt_two :: Point2 u- , _curve_end :: Point2 u- }- deriving (Eq,Show)---type instance DUnit (Path u) = u-type instance DUnit (PathSeg u) = u---infixr 1 `append`--length :: Num u => Path u -> u-length (Path u _ _ _) = u--append :: Floating u => Path u -> Path u -> Path u-append (Path len1 start1 se1 end1) (Path len2 start2 se2 end2) - | end1 == start2 = Path (len1+len2) start1 (se1 `join` se2) end2 - | otherwise = let joint = lineSegment end1 start2- total_len = len1 + len2 + segmentLength joint- in Path total_len start1 (se1 `join` (cons joint se2)) end2 ---- CAUTION - @append@ is using Floating Point equality to see if--- points are equal...---pconcat :: Floating u => Path u -> [Path u] -> Path u-pconcat p0 ps = foldl' append p0 ps--segmentLength :: PathSeg u -> u-segmentLength (LineSeg u _ _) = u-segmentLength (CurveSeg u _ _ _ _) = u---segmentStart :: PathSeg u -> Point2 u-segmentStart (LineSeg _ p0 _) = p0-segmentStart (CurveSeg _ p0 _ _ _) = p0--segmentEnd :: PathSeg u -> Point2 u-segmentEnd (LineSeg _ _ p1) = p1-segmentEnd (CurveSeg _ _ _ _ p3) = p3-----lineSegment :: Floating u => Point2 u -> Point2 u -> PathSeg u -lineSegment p0 p1 = let v = vlength $ pvec p0 p1 in LineSeg v p0 p1---pathZero :: Floating u => Point2 u -> Path u -pathZero p0 = Path 0 p0 JL.empty p0- --line :: Floating u => Point2 u -> Point2 u -> Path u -line p0 p1 = let v = vlength $ pvec p0 p1 - in Path v p0 (JL.one $ LineSeg v p0 p1) p1- --curve :: (Floating u, Ord u, FromPtSize u)- => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Path u -curve p0 p1 p2 p3 = let v = bezierLength (BezierCurve p0 p1 p2 p3)- in Path v p0 (JL.one $ CurveSeg v p0 p1 p2 p3) p3---- | A draw a /straight line/ of length 0 at the supplied point. ------ This is /might/ be useful in concatenating curved paths--- as it introduces and extra control point.--- -pivot :: Floating u => Point2 u -> Path u -pivot p0 = Path 0 p0 (JL.one $ LineSeg 0 p0 p0) p0----- | 'traceLinePoints' throws a runtime error if the supplied list--- is empty. ----traceLinePoints :: Floating u => [Point2 u] -> Path u-traceLinePoints [] = error "traceLinePoints - empty point list."-traceLinePoints [a] = line a a-traceLinePoints (a:b:xs) = step (line a b) b xs- where- step acc _ [] = acc- step acc e (y:ys) = step (acc `append` line e y) y ys----- | 'traceCurvePoints' consumes 4 points from the list on the --- intial step (start, control1, control2, end) then steps --- through the list taking 3 points at a time thereafter--- (control1,control2, end). Leftover points are discarded. --- --- 'traceCurvePoints' throws a runtime error if the supplied list--- is has less than 4 elements (start, control1, control2, end). ----traceCurvePoints :: (Floating u, Ord u, FromPtSize u) - => [Point2 u] -> Path u-traceCurvePoints (a:b:c:d:xs) = step (curve a b c d) d xs- where- step acc p0 (x:y:z:zs) = step (acc `append` curve p0 x y z) z zs- step acc _ _ = acc--traceCurvePoints _ = error "tracePointsCurve - less than 4 elems."---curveByAngles :: (Floating u, Ord u, FromPtSize u) - => Point2 u -> Radian -> Radian -> Point2 u -> Path u-curveByAngles start cin cout end = curve start (start .+^ v1) (end .+^ v2) end- where- sz = 0.375 * (vlength $ pvec start end)- v1 = avec cin sz- v2 = avec cout sz------ | Turn a Path into an ordinary PrimPath.------ Assumes path is properly formed - i.e. end point of one --- segment is the same point as the start point of the next--- segment.----toPrimPath :: Num u => Path u -> PrimPath u-toPrimPath (Path _ start segs _) = step1 $ viewl segs- where- step1 EmptyL = emptyPath start- step1 (e :< se) = let (p0,a) = seg1 e in - primPath p0 $ a : step2 (viewl se)-- step2 EmptyL = []- step2 (e :< se) = seg2 e : step2 (viewl se)- - seg1 (LineSeg _ p0 p1) = (p0, lineTo p1)- seg1 (CurveSeg _ p0 p1 p2 p3) = (p0, curveTo p1 p2 p3)- - seg2 (LineSeg _ _ p1) = lineTo p1- seg2 (CurveSeg _ _ p1 p2 p3) = curveTo p1 p2 p3---------------------------------------------------------------------------------------- tips --tipL :: Path u -> Point2 u-tipL (Path _ sp _ _) = sp---tipR :: Path u -> Point2 u-tipR (Path _ _ _ ep) = ep------- | 'sortenPath' : @ left_dist * right_dist * path -> Path @----shortenPath :: (Real u , Floating u) => u -> u -> Path u -> Path u-shortenPath l r = shortenL l . shortenR r -------------------------------------------------------------------------------------- shorten from the left...---- | Note - shortening a line from the left by --- greater-than-or-equal its length is operationally equivalent --- to making a zero-length line at the end point.----shortenL :: (Real u, Floating u) => u -> Path u -> Path u-shortenL n (Path u _ segs ep) - | n >= u = line ep ep- | otherwise = step n (viewl segs)- where- step _ EmptyL = line ep ep -- should be unreachable- step d (e :< se) = let z = segmentLength e in- case compare d z of- GT -> step (d-z) (viewl se)- EQ -> makeLeftPath (u-n) se ep- LT -> let e1 = shortenSegL d e- in Path (u-n) (segmentStart e1) (e1 `cons` se) ep---makeLeftPath :: Floating u => u -> JoinList (PathSeg u) -> Point2 u -> Path u-makeLeftPath u se ep = - case viewl se of- EmptyL -> line ep ep- (e :< _) -> Path u (segmentStart e) se ep---shortenSegL :: (Real u, Floating u) => u -> PathSeg u -> PathSeg u-shortenSegL n (LineSeg u p0 p1) = - LineSeg (u-n) (shortenLineL n p0 p1) p1--shortenSegL n (CurveSeg u p0 p1 p2 p3) = CurveSeg (u-n) q0 q1 q2 q3- where- (BezierCurve q0 q1 q2 q3) = snd $ subdividet (n/u) - (BezierCurve p0 p1 p2 p3)- ---shortenLineL :: (Real u, Floating u) - => u -> Point2 u -> Point2 u -> Point2 u-shortenLineL n p0 p1 = p0 .+^ v- where- v0 = p1 .-. p0- v = avec (vdirection v0) n--------------------------------------------------------------------------------------- shorten from the right ...- --- | Note - shortening a line from the right by --- greater-than-or-equal its length is operationally equivalent --- to making a zero-length line at the start point.----shortenR :: (Real u, Floating u) => u -> Path u -> Path u-shortenR n (Path u sp segs _) - | n >= u = line sp sp- | otherwise = step n (viewr segs)- where- step _ EmptyR = line sp sp -- should be unreachable- step d (se :> e) = let z = segmentLength e in- case compare d z of- GT -> step (d-z) (viewr se)- EQ -> makeRightPath n sp se- LT -> let e1 = shortenSegR d e- in Path (u-n) sp (se `snoc` e1) (segmentEnd e1)- --makeRightPath :: Floating u => u -> Point2 u -> JoinList (PathSeg u) -> Path u-makeRightPath u sp se = - case viewr se of- EmptyR -> line sp sp- (_ :> e) -> Path u sp se (segmentEnd e)----shortenSegR :: (Real u, Floating u) => u -> PathSeg u -> PathSeg u-shortenSegR n (LineSeg u p0 p1) = - LineSeg (u-n) p0 (shortenLineR n p0 p1) --shortenSegR n (CurveSeg u p0 p1 p2 p3) = CurveSeg (u-n) q0 q1 q2 q3- where- (BezierCurve q0 q1 q2 q3) = fst $ subdividet ((u-n)/u) - (BezierCurve p0 p1 p2 p3)- ---shortenLineR :: (Real u, Floating u) - => u -> Point2 u -> Point2 u -> Point2 u-shortenLineR n p0 p1 = p1 .+^ v- where- v0 = p0 .-. p1- v = avec (vdirection v0) n---------------------------------------------------------------------------------------- line direction---- | Direction of empty path is considered to be 0.----directionL :: (Real u, Floating u) => Path u -> Radian-directionL (Path _ _ se _) = step $ viewl se- where- step (LineSeg _ p0 p1 :< _) = lineDirection p1 p0 -- 1-to-0- step (CurveSeg _ p0 p1 _ _ :< _) = lineDirection p1 p0- step _ = 0 -- should be unreachable----- | Direction of empty path is considered to be 0.----directionR :: (Real u, Floating u) => Path u -> Radian-directionR (Path _ _ se _) = step $ viewr se- where- step (_ :> LineSeg _ p0 p1) = lineDirection p0 p1- step (_ :> CurveSeg _ _ _ p2 p3) = lineDirection p2 p3- step _ = 0 -- should be unreachable ------------------------------------------------------------------------------------------ Return direction as well because the calculation is expensive...----midway :: (Real u, Floating u) => Path u -> (Point2 u, Radian)-midway pa@(Path u sp _ _) - | u == 0 = (sp,0)- | otherwise = let pa1 = shortenR (u/2) pa in (tipR pa1, directionR pa1)---- Just the midway point.----midway_ :: (Real u, Floating u) => Path u -> Point2 u-midway_ = fst . midway---atstart :: (Real u, Floating u) => Path u -> (Point2 u, Radian)-atstart pa@(Path _ sp _ _) = (sp, directionL pa)--atstart_ :: Path u -> Point2 u-atstart_ (Path _ sp _ _) = sp---atend :: (Real u, Floating u) => Path u -> (Point2 u, Radian)-atend pa@(Path _ _ _ ep) = (ep, directionR pa)- --atend_ :: Path u -> Point2 u-atend_ (Path _ _ _ ep) = ep----- nearstart, nearend, verynear ...-------------------------------------------------------------------------------------data PathViewL u = PathOneL (PathSegment u)- | PathSegment u :<< Path u- deriving (Eq,Show) --type DPathViewL = PathViewL Double--data PathViewR u = PathOneR (PathSegment u)- | Path u :>> PathSegment u- deriving (Eq,Show) --type DPathViewR = PathViewR Double---data PathSegment u = Line1 (Point2 u) (Point2 u)- | Curve1 (Point2 u) (Point2 u) (Point2 u) (Point2 u)- deriving (Eq,Show) --type DPathSegment = PathSegment Double--type instance DUnit (PathViewL u) = u-type instance DUnit (PathViewR u) = u-type instance DUnit (PathSegment u) = u--pathViewL :: Num u => Path u -> PathViewL u-pathViewL (Path u _ segs ep) = go (viewl segs)- where- go EmptyL = error "pathViewL - (not) unreachable."- - go (LineSeg v p0 p1 :< se)- | JL.null se = PathOneL (Line1 p0 p1)- | otherwise = Line1 p0 p1 :<< Path (u-v) p1 se ep-- go (CurveSeg v p0 p1 p2 p3 :< se) - | JL.null se = PathOneL (Curve1 p0 p1 p2 p3)- | otherwise = Curve1 p0 p1 p2 p3 :<< Path (u-v) p3 se ep---pathViewR :: Num u => Path u -> PathViewR u-pathViewR (Path u _ segs ep) = go (viewr segs)- where- go EmptyR = error "pathViewR - (not) unreachable."-- go (se :> LineSeg v p0 p1) - | JL.null se = PathOneR (Line1 p0 p1)- | otherwise = Path (u-v) p1 se ep :>> Line1 p0 p1-- go (se :> CurveSeg v p0 p1 p2 p3) - | JL.null se = PathOneR (Curve1 p0 p1 p2 p3)- | otherwise = Path (u-v) p3 se ep :>> Curve1 p0 p1 p2 p3---------------------------------------------------------------------------------------- Round corners---- | The length of the control-point vector wants to be slighly --- longer than half of /d/ (d - being the distance between the --- /truncated/ points and the corner).----cornerCurve :: (Real u, Floating u, FromPtSize u) - => Point2 u -> Point2 u -> Point2 u -> Path u-cornerCurve p1 p2 p3 = curve p1 cp1 cp2 p3- where- len1 = 0.6 * (vlength $ pvec p1 p2)- len2 = 0.6 * (vlength $ pvec p3 p2)- cp1 = p1 .+^ (avec (lineAngle p1 p2) len1)- cp2 = p3 .+^ (avec (lineAngle p3 p2) len2)----- | 'roundTrail' : @ rounding_distance * [point] -> Path @------ Build a path from the list of vertices, all the interior --- corners are rounded by the rounding distance \*and\* final --- round corner is created \"incorporating\" the start point (as --- the start point becomes a rounded corner the actual path will --- not intersect it). --- --- It is expected that this function will be used to create round --- cornered shapes.--- --- 'roundTrail' throws a runtime error if the input list is empty. --- If the list has one element /the null path/ is built, if the --- list has two elements a straight line is built.----roundTrail :: (Real u, Floating u, FromPtSize u) - => u -> [Point2 u] -> Path u -roundTrail _ [] = error "roundTrail - empty list."-roundTrail _ [a] = pathZero a-roundTrail _ [a,b] = line a b-roundTrail u (start:b:c:xs) = step (lineCurveTrail u start b c) (b:c:xs)- where- step acc (m:n:o:ps) = step (acc `append` lineCurveTrail u m n o) (n:o:ps)- step acc [n,o] = acc `append` lineCurveTrail u n o start- `append` lineCurveTrail u o start b - step acc _ = acc------ | Two parts - line and corner curve...------ Note - the starting point is moved, this function is for --- closed, rounded paths.----lineCurveTrail :: (Real u, Floating u, FromPtSize u) - => u -> Point2 u -> Point2 u -> Point2 u -> Path u-lineCurveTrail u a b c = line p1 p2 `append` cornerCurve p2 b p3- where- p1 = a .+^ (avec (vdirection $ pvec a b) u)- p2 = b .+^ (avec (vdirection $ pvec b a) u)- p3 = b .+^ (avec (vdirection $ pvec b c) u)----- | 'roundInterior' : @ rounding_distance * [point] -> Path @------ Build a path from the list of vertices, all the interior --- corners are rounded by the rounding distance. Unlike --- 'roundTrail' there is no /loop around/ to the start point,--- and start path will begin exactly on the start point and end --- exactly on the end point. --- --- 'roundInterior' throws a runtime error if the input list is --- empty. If the list has one element /the null path/ is built, --- if the list has two elements a straight line is built.----roundInterior :: (Real u, Floating u, FromPtSize u) - => u -> [Point2 u] -> Path u -roundInterior _ [] = error "roundEveryInterior - empty list."-roundInterior _ [a] = pathZero a-roundInterior _ [a,b] = line a b-roundInterior u (start:b:c:xs) = let (path1,p1) = lineCurveInter1 u start b c- in step path1 (p1:c:xs)- where- step acc (m:n:o:ps) = let (seg2,p1) = lineCurveInter1 u m n o- in step (acc `append` seg2) (p1:o:ps)- step acc [n,o] = acc `append` line n o- step acc _ = acc------ | Two parts - line and corner curve...------ Note - draws a straight line from the starting point - this is --- the first step of an interior (non-closed) rounded path----lineCurveInter1 :: (Real u, Floating u, FromPtSize u) - => u -> Point2 u -> Point2 u -> Point2 u -> (Path u, Point2 u)-lineCurveInter1 u a b c = - (line a p2 `append` cornerCurve p2 b p3, p3)- where- p2 = b .+^ (avec (vdirection $ pvec b a) u)- p3 = b .+^ (avec (vdirection $ pvec b c) u)-
+ src/Wumpus/Drawing/Paths/Base/AbsBuilder.hs view
@@ -0,0 +1,561 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Base.AbsBuilder+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Build absolute paths monadically.+--+-- \*\* WARNING \*\* this module is an experiment, and may +-- change significantly or even be dropped from future revisions.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Base.AbsBuilder+ ( ++ AbsBuild+ , runAbsBuild+ , execAbsBuild+ , evalAbsBuild++ , tip++ , absline+ , abscurve+ , absmove++ , relline+ , relcurve+ , relmove++ , rellineParallel+ , rellinePerpendicular++ , relmoveParallel+ , relmovePerpendicular++++ , ctrlcurve++ , insert+ , vamp+ , cycle+ , setIncline++ -- * Derived operators+ , pen_colour+ , pen_width++ , hline+ , vline+ , aline++ , hmove+ , vmove+ , amove++ , line_up+ , line_down+ , line_left+ , line_right++ , line_up_left+ , line_up_right+ , line_down_left+ , line_down_right++ , line_north+ , line_south+ , line_east+ , line_west+ , line_northeast+ , line_northwest+ , line_southeast+ , line_southwest++ , move_up+ , move_down+ , move_left+ , move_right++ , move_up_left+ , move_up_right+ , move_down_left+ , move_down_right++ , move_north+ , move_south+ , move_east+ , move_west+ , move_northeast+ , move_northwest+ , move_southeast+ , move_southwest+++ ) where++import Wumpus.Drawing.Paths.Base.AbsPath+import qualified Wumpus.Drawing.Paths.Base.AbsPath as A+import Wumpus.Drawing.Paths.Base.BuildCommon+import qualified Wumpus.Drawing.Paths.Base.RelPath as R+++import Wumpus.Basic.Geometry ( half_pi ) -- package: wumpus-basic+import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++import Control.Applicative hiding ( empty )+import Data.Monoid++import Prelude hiding ( log, cycle )++++-- State monad building is quite good - it ameliorates the problem+-- of joining to the end point of an empty path...++data St u = St+ { current_point :: Point2 u + , current_incline :: Radian+ , cumulative_path :: AbsPath u+ , active_path :: (Point2 u, AbsPath u)+ , pen_dc_modifier :: DrawingContextF+ }++type instance DUnit (St u) = u++type Log u = BuildLog (Graphic u)+++-- | Absolute Path builder monad.+--+newtype AbsBuild u a = AbsBuild { + getAbsBuild :: St u -> (a, St u, Log u) }++type instance DUnit (AbsBuild u a) = u+++--------------------------------------------------------------------------------+-- instances++++instance Functor (AbsBuild u) where+ fmap f mf = AbsBuild $ \s0 -> let (a,s1,w1) = getAbsBuild mf s0+ in (f a, s1, w1)+++instance Applicative (AbsBuild u) where+ pure a = AbsBuild $ \s0 -> (a,s0,mempty)+ mf <*> ma = AbsBuild $ \s0 -> let (f,s1,w1) = getAbsBuild mf s0+ (a,s2,w2) = getAbsBuild ma s1+ in (f a,s2,w1 `mappend` w2)++instance Monad (AbsBuild u) where+ return a = AbsBuild $ \s0 -> (a,s0,mempty)+ m >>= k = AbsBuild $ \s0 -> let (a,s1,w1) = getAbsBuild m s0+ (b,s2,w2) = (getAbsBuild . k) a s1+ in (b, s2, w1 `mappend` w2)++++++-- | The initial state is needs the start point.+--+initSt :: Floating u => Point2 u -> St u+initSt pt = St { current_point = pt+ , current_incline = 0+ , cumulative_path = empty pt+ , active_path = (pt, empty pt)+ , pen_dc_modifier = id+ }++-- run - (path,graphic)+-- exec - graphic+-- eval - path++-- | Note - runAbsBuild drops the monadic answer and returns the+-- constructed path and a trace of the inserts and sub-paths.+--+runAbsBuild :: (Floating u, InterpretUnit u)+ => Point2 u -> AbsBuild u a -> (AbsPath u, Graphic u)+runAbsBuild pt mf = post $ getAbsBuild mf (initSt pt)+ where+ post (_,st,log) = let sub_last = snd $ active_path st+ cf = pen_dc_modifier st+ log_last = logSubPath PATH_OPEN cf sub_last+ log2 = log `mappend` log_last+ empty_gfx = emptyLocGraphic `at` pt+ (pen,ins) = extractTrace empty_gfx log2+ in (cumulative_path st, pen `oplus` ins)+++-- | Run an 'AbsBuild' - return the Graphic formed by the pen +-- trace and the insert trace, /forget/ the outline of the path.+-- +execAbsBuild :: (Floating u, InterpretUnit u)+ => Point2 u -> AbsBuild u a -> Graphic u+execAbsBuild pt mf = snd $ runAbsBuild pt mf++++-- | Run an 'AbsBuild' - return the outline of the path, /forget/+-- the Graphic formed by the pen trace and the insert trace.+-- +evalAbsBuild :: (Floating u, InterpretUnit u)+ => Point2 u -> AbsBuild u a -> AbsPath u+evalAbsBuild pt mf = fst $ runAbsBuild pt mf++++logSubPath :: InterpretUnit u + => PathEnd -> DrawingContextF -> AbsPath u -> Log u +logSubPath spe upd subp + | A.null subp = mempty+ | otherwise = pen1 (toPrimPath subp >>= localize upd . drawF)+ where+ drawF = if spe == PATH_OPEN then openStroke else closedStroke++++tellSubClosed :: InterpretUnit u + => DrawingContextF -> AbsPath u -> AbsBuild u ()+tellSubClosed upd subp = + AbsBuild $ \s0 -> ((), s0, logSubPath PATH_CLOSED upd subp)++tellSubOpen :: InterpretUnit u + => DrawingContextF -> AbsPath u -> AbsBuild u ()+tellSubOpen upd subp = + AbsBuild $ \s0 -> ((), s0, logSubPath PATH_OPEN upd subp)+++tellInsert :: Graphic u -> AbsBuild u ()+tellInsert g1 = + AbsBuild $ \s0 -> ((),s0, insert1 g1)+++sets_ :: (St u -> St u) -> AbsBuild u ()+sets_ f = AbsBuild $ \s0 -> ((), f s0, mempty)+++gets :: (St u -> a) -> AbsBuild u a+gets f = AbsBuild $ \s0 -> (f s0, s0, mempty)++++--------------------------------------------------------------------------------+-- operations++tip :: AbsBuild u (Point2 u)+tip = gets current_point++-- | Helper - extend the path.+--+extendPath :: (Point2 u -> AbsPath u -> AbsPath u) -> Point2 u -> AbsBuild u ()+extendPath fn end_pt = sets_ upd+ where+ upd = (\s pt i j -> s { current_point = end_pt+ , cumulative_path = fn pt i+ , active_path = bimapR (fn pt) j })+ <*> current_point <*> cumulative_path <*> active_path++absline :: Floating u => Point2 u -> AbsBuild u ()+absline p1 = extendPath (\_ acc -> acc `snocLineTo` p1) p1++++abscurve :: (Floating u, Ord u, Tolerance u)+ => Point2 u -> Point2 u -> Point2 u -> AbsBuild u ()+abscurve p1 p2 p3 = extendPath (\_ acc -> snocCurveTo acc p1 p2 p3) p3++++ +-- | 'absmove' is a pen up.+--+absmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => Point2 u -> AbsBuild u ()+absmove p1 = + gets active_path >>= \(_,ans) -> + gets pen_dc_modifier >>= \cf -> + tellSubOpen cf ans >> sets_ upd + where+ upd = (\s i -> s { current_point = p1+ , cumulative_path = i `snocLineTo` p1+ , active_path = (p1, empty p1) }) + <*> cumulative_path+++relline :: Floating u => Vec2 u -> AbsBuild u ()+relline v1 = gets current_point >>= \pt -> absline (pt .+^ v1)+++relcurve :: (Floating u, Ord u, Tolerance u)+ => Vec2 u -> Vec2 u -> Vec2 u -> AbsBuild u ()+relcurve v1 v2 v3 = + gets current_point >>= \pt -> + abscurve (pt .+^ v1) (pt .+^ v1 ^+^ v2) (pt .+^ v1 ^+^ v2 ^+^ v3)+++relmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => Vec2 u -> AbsBuild u ()+relmove v1 = gets current_point >>= \pt -> absmove (pt .+^ v1)++++rellineParallel :: Floating u => u -> AbsBuild u ()+rellineParallel u = gets current_incline >>= \ang -> relline (avec ang u)++rellinePerpendicular :: Floating u => u -> AbsBuild u ()+rellinePerpendicular u = + gets current_incline >>= \ang -> relline (avec (fn ang) u)+ where+ fn = circularModulo . (+ half_pi)++relmoveParallel :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+relmoveParallel u = gets current_incline >>= \ang -> relmove (avec ang u)+++relmovePerpendicular :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+relmovePerpendicular u = + gets current_incline >>= \ang -> relmove (avec (fn ang) u)+ where+ fn = circularModulo . (+ half_pi)++++ctrlcurve :: (Floating u, Ord u, Tolerance u) + => Radian -> Radian -> Point2 u -> AbsBuild u ()+ctrlcurve cin cout p1 = + extendPath (\p0 acc -> acc `append` controlCurve p0 cin cout p1) p1++++insert :: Num u => LocGraphic u -> AbsBuild u ()+insert gf = gets current_point >>= \pt -> tellInsert (gf `at` pt)+++penCtxUpdate :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => DrawingContextF -> AbsBuild u ()+penCtxUpdate cf = relmove (V2 0 0) >> sets_ upd+ where+ upd = (\s f -> s { pen_dc_modifier = cf . f })+ <*> pen_dc_modifier++++-- Note - vamps should be a data type then we can have libraries +-- of them.++vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => Vamp u -> AbsBuild u ()+vamp (Vamp vnext vstart upd relp path_end) = + gets current_point >>= \p0 -> + relmove vnext >> drawF upd (R.toAbsPath (p0 .+^ vstart) relp)+ where+ drawF = if path_end == PATH_OPEN then tellSubOpen else tellSubClosed++cycle :: (Floating u, InterpretUnit u) => AbsBuild u ()+cycle = + gets current_point >>= \pt -> + gets pen_dc_modifier >>= \cf ->+ gets active_path >>= \(start,acc) -> + tellSubClosed cf (acc `snocLineTo` start) >> + sets_ (\s -> s { active_path = (pt, empty pt)})+++setIncline :: Radian -> AbsBuild u ()+setIncline ang = sets_ upd+ where+ upd = (\s -> s { current_incline = ang })+++--------------------------------------------------------------------------------+-- Derived operators+++pen_colour :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => RGBi -> AbsBuild u ()+pen_colour rgb = penCtxUpdate (stroke_colour rgb)++pen_width :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => Double -> AbsBuild u ()+pen_width d = penCtxUpdate (set_line_width d)+++++hline :: Floating u => u -> AbsBuild u ()+hline dx = relline (hvec dx)++vline :: Floating u => u -> AbsBuild u ()+vline dy = relline (vvec dy)++aline :: Floating u => u -> AbsBuild u ()+aline u = gets current_incline >>= \ang -> relline (avec ang u)++hmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+hmove dx = relmove (hvec dx)++vmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+vmove dy = relmove (vvec dy)+++amove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+amove u = gets current_incline >>= \ang -> relmove (avec ang u)++++line_up :: Floating u => u -> AbsBuild u ()+line_up u = relline (vvec u)++line_down :: Floating u => u -> AbsBuild u ()+line_down u = relline (vvec $ negate u)++line_left :: Floating u => u -> AbsBuild u ()+line_left u = relline (hvec $ negate u)+ +line_right :: Floating u => u -> AbsBuild u ()+line_right u = relline (hvec u)++-- | Diagonal lines ++line_up_left :: Floating u => u -> AbsBuild u ()+line_up_left u = relline (vec (-u) u)++line_up_right :: Floating u => u -> AbsBuild u ()+line_up_right u = relline (vec u u)++line_down_left :: Floating u => u -> AbsBuild u ()+line_down_left u = relline (vec (-u) (-u))++line_down_right :: Floating u => u -> AbsBuild u ()+line_down_right u = relline (vec u (-u))+++-- Cardinal lines++line_north :: Floating u => u -> AbsBuild u ()+line_north = vline+++line_south :: Floating u => u -> AbsBuild u ()+line_south = vline . negate++line_east :: Floating u => u -> AbsBuild u ()+line_east = hline++line_west :: Floating u => u -> AbsBuild u ()+line_west = hline . negate+++line_northeast :: Floating u => u -> AbsBuild u ()+line_northeast = relline . avec (0.25 * pi)++line_northwest :: Floating u => u -> AbsBuild u ()+line_northwest = relline . avec (0.75 * pi)++line_southeast :: Floating u => u -> AbsBuild u ()+line_southeast = relline . avec (1.75 * pi)++line_southwest :: Floating u => u -> AbsBuild u ()+line_southwest = relline . avec (1.25 * pi)+++++move_up :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_up u = relmove (vvec u)++move_down :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_down u = relmove (vvec $ negate u)++move_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_left u = relmove (hvec $ negate u)+ +move_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_right u = relmove (hvec u)++++-- | Diagonal moves ++move_up_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_up_left u = relmove (vec (-u) u)++move_up_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_up_right u = relmove (vec u u)++move_down_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_down_left u = relmove (vec (-u) (-u))++move_down_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_down_right u = relmove (vec u (-u))+++-- Cardinal moves++move_north :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_north = vmove+++move_south :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_south = vmove . negate++move_east :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_east = hmove++move_west :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_west = hmove . negate+++move_northeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_northeast = relmove . avec (0.25 * pi)++move_northwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_northwest = relmove . avec (0.75 * pi)++move_southeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_southeast = relmove . avec (1.75 * pi)++move_southwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => u -> AbsBuild u ()+move_southwest = relmove . avec (1.25 * pi)+++
+ src/Wumpus/Drawing/Paths/Base/AbsPath.hs view
@@ -0,0 +1,801 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Base.AbsPath+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Absolute path type - this should be more amenable for building +-- complex drawings than the PrimPath type in Wumpus-Core.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Base.AbsPath+ ( ++ -- * Absolute path type+ AbsPath+ , DAbsPath+++ -- * Construction+ , empty+ , line1+ , curve1+ , vertexPath+ , curvePath+ , controlCurve++ -- * Queries+ , null+ , length++ -- * Concat and extension+ , append+ , consLineTo+ , snocLineTo+ , consCurveTo+ , snocCurveTo++ , pathconcat++ -- * Conversion+ , toPrimPath+++ -- * Shortening+ , shortenPath+ , shortenL+ , shortenR++ -- * Tips and direction+ , tipL+ , tipR+ , directionL+ , directionR++ -- * Path anchors+ , midway+ , midway_+ , atstart+ , atstart_+ , atend+ , atend_++ -- * Views+ , PathViewL(..)+ , DPathViewL+ , PathViewR(..)+ , DPathViewR+ , PathSegment(..)+ , DPathSegment+ , pathViewL+ , pathViewR+++ , roundTrail+ , roundInterior++ ) where++++import Wumpus.Basic.Geometry.Base -- package: wumpus-basic+import Wumpus.Basic.Kernel+import Wumpus.Basic.Utils.JoinList ( JoinList, ViewL(..), viewl+ , ViewR(..), viewr, cons, snoc, join )+import qualified Wumpus.Basic.Utils.JoinList as JL++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace++import Data.List ( foldl' ) +import qualified Data.Traversable as T++import Prelude hiding ( null, length )+++++-- | Absolute path data type.++data AbsPath u = AbsPath + { _abs_path_length :: u + , _abs_path_start :: Point2 u+ , _abs_path_elements :: JoinList (AbsPathSeg u)+ , _abs_path_end :: Point2 u+ }+ deriving (Eq,Show)++type instance DUnit (AbsPath u) = u+++type DAbsPath = AbsPath Double++-- Annotating each segment with length is \*\* good \*\*.+-- Makes it much more efficient to find the midway point.+--+-- But what do we do about the start point:+--+-- a) put it in the segment - too much info in the type, allows +-- consistency problems vis-a-vis gaps in the path.+--+-- b) leave it out - too little info in the type, allows +-- consistency problems with length.+--+-- Option (a) is probably most convenient espcially as the +-- constructors won\'t be exported.++-- Annotation is length...+-- +data AbsPathSeg u = AbsLineSeg + { _abs_line_length :: u + , _abs_line_start :: Point2 u+ , _abs_line_end :: Point2 u+ }+ | AbsCurveSeg + { _abs_curve_length :: u + , _abs_curve_start :: Point2 u+ , _abs_ctrl_pt_one :: Point2 u+ , _abs_ctrl_pt_two :: Point2 u+ , _abs_curve_end :: Point2 u+ }+ deriving (Eq,Show)+++type instance DUnit (AbsPathSeg u) = u+++--------------------------------------------------------------------------------++instance Functor AbsPath where+ fmap f (AbsPath u sp ls ep) = + AbsPath (f u) (fmap f sp) (fmap (fmap f) ls) (fmap f ep)++instance Functor AbsPathSeg where+ fmap f (AbsLineSeg u p0 p1) = + AbsLineSeg (f u) (fmap f p0) (fmap f p1) ++ fmap f (AbsCurveSeg u p0 p1 p2 p3) = + AbsCurveSeg (f u) (fmap f p0) (fmap f p1) (fmap f p2) (fmap f p3)+++--------------------------------------------------------------------------------++-- TODO - must organize the Path datatype modules so they provide+-- Containers-like API functions when appropriate.++++--------------------------------------------------------------------------------+-- Construction++-- | Create the empty path.+-- +-- Note - an absolute path needs /locating/ and cannot be built +-- without a start point. Figuratively, the empty path is a path+-- from the start point to the start point.+--+-- Thus AbsPath operates as a semigroup but not a monoid.+--+empty :: Floating u => Point2 u -> AbsPath u+empty = zeroPath+++-- | Create an absolute path as a straight line between the +-- supplied points.+--+line1 :: Floating u => Point2 u -> Point2 u -> AbsPath u +line1 p0 p1 = AbsPath v p0 (JL.one $ AbsLineSeg v p0 p1) p1+ where+ v = vlength $ pvec p0 p1 ++-- | Create an absolute path from a single cubic Bezier curve.+--+curve1 :: (Floating u, Ord u, Tolerance u)+ => Point2 u -> Point2 u -> Point2 u -> Point2 u -> AbsPath u +curve1 p0 p1 p2 p3 = AbsPath v p0 (JL.one $ AbsCurveSeg v p0 p1 p2 p3) p3+ where+ v = bezierLength (BezierCurve p0 p1 p2 p3)+++-- | 'vertexPath' throws a runtime error if the supplied list+-- is empty. +--+vertexPath :: (Floating u, Ord u, Tolerance u) + => [Point2 u] -> AbsPath u+vertexPath [] = error "traceLinePoints - empty point list."+vertexPath [a] = line1 a a+vertexPath (a:b:xs) = step (line1 a b) b xs+ where+ step acc _ [] = acc+ step acc e (y:ys) = step (acc `append` line1 e y) y ys++++-- | 'curvePath' consumes 4 points from the list on the +-- intial step (start, control1, control2, end) then steps +-- through the list taking 3 points at a time thereafter+-- (control1,control2, end). Leftover points are discarded. +-- +-- 'curvePath' throws a runtime error if the supplied list+-- is has less than 4 elements (start, control1, control2, end). +--+curvePath :: (Floating u, Ord u, Tolerance u) + => [Point2 u] -> AbsPath u+curvePath (a:b:c:d:xs) = step (curve1 a b c d) d xs+ where+ step acc p0 (x:y:z:zs) = step (acc `append` curve1 p0 x y z) z zs+ step acc _ _ = acc++curvePath _ = error "curvePath - less than 4 elems."++++-- NOTE - need a proper arc path builder.++++-- | This is not an arc...+-- +controlCurve :: (Floating u, Ord u, Tolerance u) + => Point2 u -> Radian -> Radian -> Point2 u -> AbsPath u+controlCurve start cin cout end = + curve1 start (start .+^ v1) (end .+^ v2) end+ where+ sz = 0.375 * (vlength $ pvec start end)+ v1 = avec cin sz+ v2 = avec cout sz+++--------------------------------------------------------------------------------+-- Queries++-- | Is the path empty?+--+null :: AbsPath u -> Bool+null = JL.null . _abs_path_elements++-- | Length of the Path.+--+-- Length is the length of the path as it is drawn, it is not a +-- count of the number or path segments.+--+-- Length is cached so this operation is cheap - though this put +-- a tax on the build operations. +-- +length :: Num u => AbsPath u -> u+length (AbsPath u _ _ _) = u+++--------------------------------------------------------------------------------+-- Concat++infixr 1 `append`++-- | Append two AbsPaths. +-- +-- If the end of the first path and the start of the second path+-- coalesce then the paths are joined directly, otherwise, a+-- straight line segment is added to join the paths.+-- +-- Neither path is /moved/. Consider 'RelPath' if you need +-- different concatenation.+--+append :: (Floating u, Ord u, Tolerance u) + => AbsPath u -> AbsPath u -> AbsPath u+append (AbsPath len1 start1 se1 end1) (AbsPath len2 start2 se2 end2) + | end1 == start2 = AbsPath (len1+len2) start1 (se1 `join` se2) end2 + | otherwise = AbsPath total_len start1 segs end2 + where+ joint = lineSegment end1 start2+ total_len = len1 + len2 + segmentLength joint+ segs = se1 `join` (cons joint se2)+++-- | Prefix the path with a straight line segment from the +-- supplied point.+--+consLineTo :: Floating u => Point2 u -> AbsPath u -> AbsPath u+consLineTo p0 (AbsPath len1 sp se1 ep) = AbsPath (v+len1) p0 (cons s1 se1) ep+ where+ s1@(AbsLineSeg v _ _) = lineSegment p0 sp +++-- | Suffix the path with a straight line segment to the +-- supplied point.+--+snocLineTo :: Floating u => AbsPath u -> Point2 u -> AbsPath u+snocLineTo (AbsPath len1 sp se1 ep) p1 = AbsPath (len1+v) sp (snoc se1 s1) p1+ where+ s1@(AbsLineSeg v _ _) = lineSegment ep p1+++-- | Prefix the path with a Bezier curve segment formed by the +-- supplied points.+--+consCurveTo :: (Floating u, Ord u, Tolerance u)+ => Point2 u -> Point2 u -> Point2 u -> AbsPath u -> AbsPath u+consCurveTo p0 p1 p2 (AbsPath len1 sp se1 ep) = + AbsPath (v+len1) p0 (cons s1 se1) ep+ where+ s1@(AbsCurveSeg v _ _ _ _) = curveSegment p0 p1 p2 sp+++-- | Suffix the path with a Bezier curve segment formed by the +-- supplied points.+--+snocCurveTo :: (Floating u, Ord u, Tolerance u)+ => AbsPath u -> Point2 u -> Point2 u -> Point2 u -> AbsPath u+snocCurveTo (AbsPath len1 sp se1 ep) p1 p2 p3 = + AbsPath (v+len1) sp (snoc se1 s1) p3+ where+ s1@(AbsCurveSeg v _ _ _ _) = curveSegment ep p1 p2 p3+ ++ ++-- | Concat the list of paths onto the intial path.+-- +-- Because a true empty path cannot be constructed (i.e. the+-- /empty/ path needs a start point even if it has no segments) - +-- the list is in /destructor form/. Client code has to decide +-- how to handle the empty list case, e.g.:+--+-- > case paths of+-- > (x:xs) -> Just $ pathconcat x xs+-- > [] -> Nothing+--+-- +pathconcat :: (Floating u, Ord u, Tolerance u) + => AbsPath u -> [AbsPath u] -> AbsPath u+pathconcat p0 ps = foldl' append p0 ps++segmentLength :: AbsPathSeg u -> u+segmentLength (AbsLineSeg u _ _) = u+segmentLength (AbsCurveSeg u _ _ _ _) = u+++segmentStart :: AbsPathSeg u -> Point2 u+segmentStart (AbsLineSeg _ p0 _) = p0+segmentStart (AbsCurveSeg _ p0 _ _ _) = p0++segmentEnd :: AbsPathSeg u -> Point2 u+segmentEnd (AbsLineSeg _ _ p1) = p1+segmentEnd (AbsCurveSeg _ _ _ _ p3) = p3+++++-- | Helper - construct a curve segment.+-- +lineSegment :: Floating u => Point2 u -> Point2 u -> AbsPathSeg u +lineSegment p0 p1 = AbsLineSeg v p0 p1+ where+ v = vlength $ pvec p0 p1+++-- | Helper - construct a curve segment.+-- +curveSegment :: (Floating u, Ord u, Tolerance u) + => Point2 u -> Point2 u -> Point2 u -> Point2 u -> AbsPathSeg u +curveSegment p0 p1 p2 p3 = AbsCurveSeg v p0 p1 p2 p3+ where+ v = bezierLength (BezierCurve p0 p1 p2 p3)+++-- | Helper - construct the /empty/ but located path.+-- +zeroPath :: Floating u => Point2 u -> AbsPath u +zeroPath p0 = AbsPath 0 p0 JL.empty p0+ ++++++++-- | Turn a Path into an ordinary PrimPath.+--+-- Assumes path is properly formed - i.e. end point of one +-- segment is the same point as the start point of the next+-- segment.+--+toPrimPath :: InterpretUnit u => AbsPath u -> Query PrimPath+toPrimPath (AbsPath _ start segs _) = + uconvertCtxF start >>= \dstart -> + T.mapM uconvertCtxF segs >>= \dsegs ->+ return $ step1 dstart (viewl dsegs)+ where+ step1 p0 EmptyL = emptyPrimPath p0+ step1 _ (e :< se) = let (p0,a) = seg1 e+ rest = step2 (viewl se)+ in absPrimPath p0 (a:rest)++ step2 EmptyL = []+ step2 (e :< se) = seg2 e : step2 (viewl se)+ + seg1 (AbsLineSeg _ p0 p1) = (p0, absLineTo p1)+ seg1 (AbsCurveSeg _ p0 p1 p2 p3) = (p0, absCurveTo p1 p2 p3)+ + seg2 (AbsLineSeg _ _ p1) = absLineTo p1+ seg2 (AbsCurveSeg _ _ p1 p2 p3) = absCurveTo p1 p2 p3+++++++-- | 'sortenPath' : @ left_dist * right_dist * path -> Path @+--+shortenPath :: (Real u , Floating u) + => u -> u -> AbsPath u -> AbsPath u+shortenPath l r = shortenL l . shortenR r +++--------------------------------------------------------------------------------+-- shorten from the left...++-- | Note - shortening a line from the left by +-- greater-than-or-equal its length is operationally equivalent +-- to making a zero-length line at the end point.+--+shortenL :: (Real u, Floating u) => u -> AbsPath u -> AbsPath u+shortenL n (AbsPath u _ segs ep) + | n >= u = line1 ep ep+ | otherwise = step n (viewl segs)+ where+ step _ EmptyL = line1 ep ep -- should be unreachable+ step d (e :< se) = let z = segmentLength e in+ case compare d z of+ GT -> step (d-z) (viewl se)+ EQ -> makeLeftPath (u-n) se ep+ LT -> let e1 = shortenSegL d e+ sp = segmentStart e1+ in AbsPath (u-n) sp (e1 `cons` se) ep+++makeLeftPath :: Floating u + => u -> JoinList (AbsPathSeg u) -> Point2 u -> AbsPath u+makeLeftPath u se ep = + case viewl se of+ EmptyL -> line1 ep ep+ (e :< _) -> AbsPath u (segmentStart e) se ep+++shortenSegL :: (Real u, Floating u) + => u -> AbsPathSeg u -> AbsPathSeg u+shortenSegL n (AbsLineSeg u p0 p1) = + AbsLineSeg (u-n) (shortenLineL n p0 p1) p1++shortenSegL n (AbsCurveSeg u p0 p1 p2 p3) = + AbsCurveSeg (u-n) q0 q1 q2 q3+ where+ (BezierCurve q0 q1 q2 q3) = snd $ subdividet (n/u) + (BezierCurve p0 p1 p2 p3)+ +++shortenLineL :: (Real u, Floating u) + => u -> Point2 u -> Point2 u -> Point2 u+shortenLineL n p0 p1 = p0 .+^ v+ where+ v0 = p1 .-. p0+ v = avec (vdirection v0) n++++--------------------------------------------------------------------------------+-- shorten from the right ...+ +-- | Note - shortening a line from the right by +-- greater-than-or-equal its length is operationally equivalent +-- to making a zero-length line at the start point.+--+shortenR :: (Real u, Floating u) => u -> AbsPath u -> AbsPath u+shortenR n (AbsPath u sp segs _) + | n >= u = line1 sp sp+ | otherwise = step n (viewr segs)+ where+ step _ EmptyR = line1 sp sp -- should be unreachable+ step d (se :> e) = let z = segmentLength e in+ case compare d z of+ GT -> step (d-z) (viewr se)+ EQ -> makeRightPath n sp se+ LT -> let e1 = shortenSegR d e+ ep = segmentEnd e1+ in AbsPath (u-n) sp (se `snoc` e1) ep+ ++makeRightPath :: Floating u + => u -> Point2 u -> JoinList (AbsPathSeg u) -> AbsPath u+makeRightPath u sp se = + case viewr se of+ EmptyR -> line1 sp sp+ (_ :> e) -> AbsPath u sp se (segmentEnd e)++++shortenSegR :: (Real u, Floating u) + => u -> AbsPathSeg u -> AbsPathSeg u+shortenSegR n (AbsLineSeg u p0 p1) = + AbsLineSeg (u-n) p0 (shortenLineR n p0 p1) ++shortenSegR n (AbsCurveSeg u p0 p1 p2 p3) = AbsCurveSeg (u-n) q0 q1 q2 q3+ where+ (BezierCurve q0 q1 q2 q3) = fst $ subdividet ((u-n)/u) + (BezierCurve p0 p1 p2 p3)+ +++shortenLineR :: (Real u, Floating u) + => u -> Point2 u -> Point2 u -> Point2 u+shortenLineR n p0 p1 = p1 .+^ v+ where+ v0 = p0 .-. p1+ v = avec (vdirection v0) n++++--------------------------------------------------------------------------------+-- tips ++tipL :: AbsPath u -> Point2 u+tipL (AbsPath _ sp _ _) = sp+++tipR :: AbsPath u -> Point2 u+tipR (AbsPath _ _ _ ep) = ep+++--------------------------------------------------------------------------------+-- line direction++-- | Direction of empty path is considered to be 0.+--+directionL :: (Real u, Floating u) => AbsPath u -> Radian+directionL (AbsPath _ _ se _) = step $ viewl se+ where+ step (AbsLineSeg _ p0 p1 :< _) = lineDirection p1 p0 -- 1-to-0+ step (AbsCurveSeg _ p0 p1 _ _ :< _) = lineDirection p1 p0+ step _ = 0 -- should be unreachable+++-- | Direction of empty path is considered to be 0.+--+directionR :: (Real u, Floating u) => AbsPath u -> Radian+directionR (AbsPath _ _ se _) = step $ viewr se+ where+ step (_ :> AbsLineSeg _ p0 p1) = lineDirection p0 p1+ step (_ :> AbsCurveSeg _ _ _ p2 p3) = lineDirection p2 p3+ step _ = 0 -- should be unreachable + ++++--------------------------------------------------------------------------------+++-- Return direction as well because the calculation is expensive...+--+midway :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)+midway pa@(AbsPath u sp _ _) + | u == 0 = (sp,0)+ | otherwise = let pa1 = shortenR (u/2) pa in (tipR pa1, directionR pa1)++-- Just the midway point.+--+midway_ :: (Real u, Floating u) => AbsPath u -> Point2 u+midway_ = fst . midway+++atstart :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)+atstart pa@(AbsPath _ sp _ _) = (sp, directionL pa)++atstart_ :: AbsPath u -> Point2 u+atstart_ (AbsPath _ sp _ _) = sp+++atend :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)+atend pa@(AbsPath _ _ _ ep) = (ep, directionR pa)+ ++atend_ :: AbsPath u -> Point2 u+atend_ (AbsPath _ _ _ ep) = ep+++-- nearstart, nearend, verynear ...+++--------------------------------------------------------------------------------++infixr 5 :<<+infixl 5 :>>++data PathViewL u = PathOneL (PathSegment u)+ | PathSegment u :<< AbsPath u+ deriving (Eq,Show) ++type DPathViewL = PathViewL Double++data PathViewR u = PathOneR (PathSegment u)+ | AbsPath u :>> PathSegment u+ deriving (Eq,Show) ++type DPathViewR = PathViewR Double+++data PathSegment u = LineSeg (Point2 u) (Point2 u)+ | CurveSeg (Point2 u) (Point2 u) (Point2 u) (Point2 u)+ deriving (Eq,Show) ++type DPathSegment = PathSegment Double+++--------------------------------------------------------------------------------++instance Functor PathSegment where+ fmap f (LineSeg p0 p1) = LineSeg (fmap f p0) (fmap f p1)+ fmap f (CurveSeg p0 p1 p2 p3) = + CurveSeg (fmap f p0) (fmap f p1) (fmap f p2) (fmap f p3)++instance Functor PathViewL where+ fmap f (PathOneL a) = PathOneL (fmap f a)+ fmap f (a :<< as) = fmap f a :<< fmap f as++instance Functor PathViewR where+ fmap f (PathOneR a) = PathOneR (fmap f a)+ fmap f (as :>> a) = fmap f as :>> fmap f a++--------------------------------------------------------------------------------++++pathViewL :: Num u => AbsPath u -> PathViewL u+pathViewL (AbsPath u _ segs ep) = go (viewl segs)+ where+ go EmptyL = error "pathViewL - (not) unreachable."+ + go (AbsLineSeg v p0 p1 :< se)+ | JL.null se = PathOneL (LineSeg p0 p1)+ | otherwise = LineSeg p0 p1 :<< AbsPath (u-v) p1 se ep++ go (AbsCurveSeg v p0 p1 p2 p3 :< se) + | JL.null se = PathOneL (CurveSeg p0 p1 p2 p3)+ | otherwise = CurveSeg p0 p1 p2 p3 :<< AbsPath (u-v) p3 se ep+++pathViewR :: Num u => AbsPath u -> PathViewR u+pathViewR (AbsPath u _ segs ep) = go (viewr segs)+ where+ go EmptyR = error "pathViewR - (not) unreachable."++ go (se :> AbsLineSeg v p0 p1) + | JL.null se = PathOneR (LineSeg p0 p1)+ | otherwise = AbsPath (u-v) p1 se ep :>> LineSeg p0 p1++ go (se :> AbsCurveSeg v p0 p1 p2 p3) + | JL.null se = PathOneR (CurveSeg p0 p1 p2 p3)+ | otherwise = AbsPath (u-v) p3 se ep :>> CurveSeg p0 p1 p2 p3+++++--------------------------------------------------------------------------------+-- Round corners++-- NOTE - round corners are probably better suited to construction +-- rather than transformation.+-- +-- The code below is pencilled in to change.+--++++-- | The length of the control-point vector wants to be slighly +-- longer than half of /d/ (d - being the distance between the +-- /truncated/ points and the corner).+--+cornerCurve :: (Real u, Floating u, Tolerance u) + => Point2 u -> Point2 u -> Point2 u -> AbsPath u+cornerCurve p1 p2 p3 = curve1 p1 cp1 cp2 p3+ where+ len1 = 0.6 * (vlength $ pvec p1 p2)+ len2 = 0.6 * (vlength $ pvec p3 p2)+ cp1 = p1 .+^ (avec (lineAngle p1 p2) len1)+ cp2 = p3 .+^ (avec (lineAngle p3 p2) len2)+++-- | 'roundTrail' : @ rounding_distance * [point] -> Path @+--+-- Build a path from the list of vertices, all the interior +-- corners are rounded by the rounding distance \*and\* final +-- round corner is created \"incorporating\" the start point (as +-- the start point becomes a rounded corner the actual path will +-- not intersect it). +-- +-- It is expected that this function will be used to create round +-- cornered shapes.+-- +-- 'roundTrail' throws a runtime error if the input list is empty. +-- If the list has one element /the null path/ is built, if the +-- list has two elements a straight line is built.+--+roundTrail :: (Real u, Floating u, Tolerance u) + => u -> [Point2 u] -> AbsPath u +roundTrail _ [] = error "roundTrail - empty list."+roundTrail _ [a] = zeroPath a+roundTrail _ [a,b] = line1 a b+roundTrail u (start:b:c:xs) = step (lineCurveTrail u start b c) (b:c:xs)+ where+ step acc (m:n:o:ps) = step (acc `append` lineCurveTrail u m n o) (n:o:ps)+ step acc [n,o] = acc `append` lineCurveTrail u n o start+ `append` lineCurveTrail u o start b + step acc _ = acc++++-- | Two parts - line and corner curve...+--+-- Note - the starting point is moved, this function is for +-- closed, rounded paths.+--+lineCurveTrail :: (Real u, Floating u, Tolerance u) + => u -> Point2 u -> Point2 u -> Point2 u -> AbsPath u+lineCurveTrail u a b c = line1 p1 p2 `append` cornerCurve p2 b p3+ where+ p1 = a .+^ (avec (vdirection $ pvec a b) u)+ p2 = b .+^ (avec (vdirection $ pvec b a) u)+ p3 = b .+^ (avec (vdirection $ pvec b c) u)+++-- | 'roundInterior' : @ rounding_distance * [point] -> Path @+--+-- Build a path from the list of vertices, all the interior +-- corners are rounded by the rounding distance. Unlike +-- 'roundTrail' there is no /loop around/ to the start point,+-- and start path will begin exactly on the start point and end +-- exactly on the end point. +-- +-- 'roundInterior' throws a runtime error if the input list is +-- empty. If the list has one element /the null path/ is built, +-- if the list has two elements a straight line is built.+--+roundInterior :: (Real u, Floating u, Tolerance u) + => u -> [Point2 u] -> AbsPath u +roundInterior _ [] = error "roundEveryInterior - empty list."+roundInterior _ [a] = zeroPath a+roundInterior _ [a,b] = line1 a b+roundInterior u (start:b:c:xs) = let (path1,p1) = lineCurveInter1 u start b c+ in step path1 (p1:c:xs)+ where+ step acc (m:n:o:ps) = let (seg2,p1) = lineCurveInter1 u m n o+ in step (acc `append` seg2) (p1:o:ps)+ step acc [n,o] = acc `append` line1 n o+ step acc _ = acc++++-- | Two parts - line and corner curve...+--+-- Note - draws a straight line from the starting point - this is +-- the first step of an interior (non-closed) rounded path+--+lineCurveInter1 :: (Real u, Floating u, Tolerance u) + => u -> Point2 u -> Point2 u -> Point2 u + -> (AbsPath u, Point2 u)+lineCurveInter1 u a b c = + (line1 a p2 `append` cornerCurve p2 b p3, p3)+ where+ p2 = b .+^ (avec (vdirection $ pvec b a) u)+ p3 = b .+^ (avec (vdirection $ pvec b c) u)+
+ src/Wumpus/Drawing/Paths/Base/BuildCommon.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Base.BuildCommon+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Common data types for the monadic builders.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Base.BuildCommon+ ( ++ BuildLog+ , PathEnd(..)+ , Vamp(..)+ + , extractTrace+ , addInsert+ , addPen++ , insert1+ , pen1+ + ) where++import Wumpus.Drawing.Paths.Base.RelPath ( RelPath )++import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Basic.Utils.HList++import Wumpus.Core -- package: wumpus-core++import Data.Monoid++-- | Monadic builders allow both inserts (patterned after TikZ)+-- which are decorations along the path and sub paths that are +-- stroked and possibly closed.+--+data BuildLog a = Log { insert_trace :: H a+ , pen_trace :: H a+ }+ | NoLog++data PathEnd = PATH_CLOSED | PATH_OPEN+ deriving (Eq,Show)+++data Vamp u = Vamp + { vamp_move_span :: Vec2 u+ , vamp_move_start :: Vec2 u+ , vamp_dc_update :: DrawingContextF+ , vamp_deco_path :: RelPath u+ , vamp_path_end :: PathEnd+ }++type instance DUnit (Vamp u) = u++--------------------------------------------------------------------------------+-- instances++instance Monoid (BuildLog a) where+ mempty = NoLog+ NoLog `mappend` b = b+ a `mappend` NoLog = a+ Log li lp `mappend` Log ri rp = Log (li `appendH` ri) (lp `appendH` rp)+++++-- | Extract the pen and insert drawings from a 'BuildLog'.+--+-- Any sub-paths traced by the pen are drawn at the back in the +-- Z-order.+--+extractTrace :: OPlus a => a -> BuildLog a -> (a,a)+extractTrace zero NoLog = (zero,zero)+extractTrace zero (Log ins pen) = (pent,inst)+ where+ pent = altconcat zero $ toListH $ pen + inst = altconcat zero $ toListH $ ins+++-- | Add an /insert/.+--+-- This is a decoration drawn at the /current point/ during path+-- building.+-- +addInsert :: a -> BuildLog a -> BuildLog a+addInsert a NoLog = Log { insert_trace = wrapH a, pen_trace = emptyH }+addInsert a s@(Log { insert_trace=i }) = s { insert_trace = i `snocH` a }+++-- | Build a trace from an /insert/.+--+-- This is a decoration drawn at the /current point/ during path+-- building.+-- +insert1 :: a -> BuildLog a+insert1 a = Log { insert_trace = wrapH a, pen_trace = emptyH }++-- | Add a /pen/ drawing. +--+-- This is a stroked path sub-path formed prior to a @moveto@ +-- instruction. Moveto is synonymous with /pen up/ - at a pen up+-- and sub-path is drawn as a trace.+-- +addPen :: a -> BuildLog a -> BuildLog a+addPen a NoLog = Log { insert_trace = wrapH a, pen_trace = emptyH }+addPen a s@(Log { pen_trace=i }) = s { pen_trace = i `snocH` a }+++-- | Build a trace from an /insert/.+--+-- This is a decoration drawn at the /current point/ during path+-- building.+-- +pen1 :: a -> BuildLog a+pen1 a = Log { insert_trace = emptyH, pen_trace = wrapH a }+++
+ src/Wumpus/Drawing/Paths/Base/RelBuilder.hs view
@@ -0,0 +1,520 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Base.RelBuilder+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Build relative paths monadically.+--+-- \*\* WARNING \*\* this module is an experiment, and may +-- change significantly or even be dropped from future revisions.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Base.RelBuilder+ ( ++ RelBuild+ , runRelBuild+ , execRelBuild+ , evalRelBuild+ , execPivot+++ , tip + , line+ , curve+ , move++ , insert+ , vamp+ , cycle++ , setIncline+ , pivot++ -- * Derived operators+ , pen_colour+ , pen_width++ , hline+ , vline+ , aline++ , hmove+ , vmove+ , amove++ , line_up+ , line_down+ , line_left+ , line_right++ , line_up_left+ , line_up_right+ , line_down_left+ , line_down_right++ , line_north+ , line_south+ , line_east+ , line_west+ , line_northeast+ , line_northwest+ , line_southeast+ , line_southwest++ , move_up+ , move_down+ , move_left+ , move_right++ , move_up_left+ , move_up_right+ , move_down_left+ , move_down_right++ , move_north+ , move_south+ , move_east+ , move_west+ , move_northeast+ , move_northwest+ , move_southeast+ , move_southwest++ ) where++-- import qualified Wumpus.Drawing.Paths.Base.AbsPath as A+import Wumpus.Drawing.Paths.Base.BuildCommon+import Wumpus.Drawing.Paths.Base.RelPath+import qualified Wumpus.Drawing.Paths.Base.RelPath as R+++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core+++import Data.VectorSpace -- package: vector-space++import Control.Applicative+import Data.Monoid+import Prelude hiding ( null, log, cycle )+++data St u = St + { cumulative_disp :: Vec2 u+ , cumulative_path :: RelPath u+ , current_incline :: Radian+ , active_path :: (Vec2 u, RelPath u)+ , pen_dc_modifier :: DrawingContextF+ , pivot_position :: Vec2 u+ }++type instance DUnit (St u) = u++type Log u = BuildLog (LocGraphic u)++++ +-- Don\'t want to write pen trace along with the insert commands +-- as some renderings (fill) should ignore the the pen trace.+++-- | Evaluation is two States - a vector for cummulative +-- displacement and a cummulative path - plus one Writer - a trace +-- of TikZ-like @insert@ commands.+--+data RelBuild u a = RelBuild { getRelBuild :: St u -> (a, St u, Log u) }++type instance DUnit (RelBuild u a) = u+++--------------------------------------------------------------------------------+-- instances++++instance Functor (RelBuild u) where+ fmap f mf = RelBuild $ \s0 -> let (a, s1, w) = getRelBuild mf s0+ in (f a, s1, w)+++instance Applicative (RelBuild u) where+ pure a = RelBuild $ \s0 -> (a, s0, mempty)+ mf <*> ma = RelBuild $ \s0 -> + let (f,s1,w1) = getRelBuild mf s0+ (a,s2,w2) = getRelBuild ma s1+ in (f a, s2, w1 `mappend` w2)++instance Monad (RelBuild u) where+ return a = RelBuild $ \s0 -> (a, s0, mempty)+ ma >>= k = RelBuild $ \s0 -> + let (a,s1,w1) = getRelBuild ma s0+ (b,s2,w2) = (getRelBuild . k) a s1+ in (b, s2, w1 `mappend` w2)++++zeroSt :: Num u => St u+zeroSt = St { cumulative_disp = V2 0 0 + , cumulative_path = mempty+ , current_incline = 0+ , active_path = (V2 0 0, mempty)+ , pen_dc_modifier = id+ , pivot_position = V2 0 0+ }+++runBuildMonad :: (Floating u, InterpretUnit u)+ => RelBuild u a -> (a, St u, LocGraphic u)+runBuildMonad mf = post $ getRelBuild mf zeroSt+ where+ post (a,st,log) = (a, st, pen `oplus` ins)+ where+ (v1,sub_last) = active_path st+ cf = pen_dc_modifier st+ log_last = logSubPath PATH_OPEN cf v1 sub_last+ log2 = log `mappend` log_last+ (pen,ins) = extractTrace emptyLocGraphic log2+++-- | Note - runAbsBuild drops the monadic answer and returns the+-- constructed path and a trace of the inserts and sub-paths.+--+runRelBuild :: (Floating u, InterpretUnit u)+ => RelBuild u a -> (RelPath u, LocGraphic u)+runRelBuild mf = post $ runBuildMonad mf+ where+ post (_,st,gf) = (cumulative_path st,gf)+++-- | Run an 'RelBuild' - return the LocGraphic formed by the pen +-- trace and the insert trace, /forget/ the outline of the path.+-- +execRelBuild :: (Floating u, InterpretUnit u)+ => RelBuild u a -> LocGraphic u+execRelBuild mf = snd $ runRelBuild mf++++-- | Run an 'RelBuild' - return the outline of the path, /forget/+-- the LocGraphic formed by the pen trace and the insert trace.+-- +evalRelBuild :: (Floating u, InterpretUnit u)+ => RelBuild u a -> RelPath u+evalRelBuild mf = fst $ runRelBuild mf+++execPivot :: (Floating u, InterpretUnit u)+ => RelBuild u a -> LocGraphic u+execPivot mf = post $ runBuildMonad mf+ where+ post (_,st,gf) = let v1 = pivot_position st+ in moveStart (displaceVec $ vreverse v1) gf+++++logSubPath :: InterpretUnit u + => PathEnd -> DrawingContextF -> Vec2 u -> RelPath u -> Log u +logSubPath spe upd v1 subp + | R.null subp = mempty+ | otherwise = pen1 gf+ where+ drawF = if spe == PATH_OPEN then openStroke else closedStroke+ gf = promoteR1 $ \pt -> + toPrimPath (displaceVec v1 pt) subp >>= \pp -> + localize upd (drawF pp)+++tellSubClosed :: InterpretUnit u + => DrawingContextF -> Vec2 u -> RelPath u -> RelBuild u ()+tellSubClosed upd v1 subp = + RelBuild $ \s0 -> ((), s0, logSubPath PATH_CLOSED upd v1 subp)++tellSubOpen :: InterpretUnit u + => DrawingContextF -> Vec2 u -> RelPath u -> RelBuild u ()+tellSubOpen upd v1 subp = + RelBuild $ \s0 -> ((), s0, logSubPath PATH_OPEN upd v1 subp)+++tellInsert :: LocGraphic u -> RelBuild u ()+tellInsert g1 = + RelBuild $ \s0 -> ((),s0, insert1 g1)+++sets_ :: (St u -> St u) -> RelBuild u ()+sets_ f = RelBuild $ \s0 -> ((), f s0, mempty)+++gets :: (St u -> a) -> RelBuild u a+gets f = RelBuild $ \s0 -> (f s0, s0, mempty)++++--------------------------------------------------------------------------------+-- operations++tip :: RelBuild u (Vec2 u)+tip = gets cumulative_disp++++-- | Helper - extend the path.+--+extendPath :: Num u + => (Vec2 u -> RelPath u -> RelPath u) -> Vec2 u -> RelBuild u ()+extendPath fn v1 = sets_ upd+ where+ upd = (\s v0 i j -> s { cumulative_disp = v0 ^+^ v1+ , cumulative_path = fn v0 i+ , active_path = bimapR (fn v0) j })+ <*> cumulative_disp <*> cumulative_path <*> active_path++--+-- Note - is the @r@ prefix of @rlineto@ redundant considering+-- RelBuild can only support relative operations anyway.+--+-- @lineto@ or probably better just @line@ would be shorter and+-- the derivatives @hline@, @vline@ would inherit an obvious +-- naming scheme.+--+++line :: Floating u => Vec2 u -> RelBuild u ()+line v1 = extendPath (\_ acc -> snocLineTo acc v1) v1++++++curve :: Floating u => Vec2 u -> Vec2 u -> Vec2 u -> RelBuild u ()+curve v1 v2 v3 = extendPath (\_ acc -> snocCurveTo acc v1 v2 v3) v3+++++-- | 'rmoveto' is a pen up.+--+move :: (Floating u, InterpretUnit u) => Vec2 u -> RelBuild u ()+move v1 = + gets active_path >>= \(v0,ans) -> + gets pen_dc_modifier >>= \cf -> + tellSubOpen cf v0 ans >> sets_ upd + where+ upd = (\s v0 i -> s { cumulative_disp = v0 ^+^ v1+ , cumulative_path = snocLineTo i v1+ , active_path = (v0 ^+^ v1, mempty) })+ <*> cumulative_disp <*> cumulative_path++++++insert :: Num u => LocGraphic u -> RelBuild u ()+insert gf = gets cumulative_disp >>= \v -> + tellInsert (moveStart (displaceVec v) gf)+++penCtxUpdate :: (Floating u, InterpretUnit u) + => DrawingContextF -> RelBuild u ()+penCtxUpdate cf = move (V2 0 0) >> sets_ upd+ where+ upd = (\s f -> s { pen_dc_modifier = cf . f }) <*> pen_dc_modifier+++++-- Note - vamps should be a data type then we can have libraries +-- of them.++vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) + => Vamp u -> RelBuild u ()+vamp (Vamp vnext vstart upd relp path_end) = + gets cumulative_disp >>= \v0 -> + gets pen_dc_modifier >>= \cf ->+ move vnext >> drawF (upd . cf) (v0 ^+^ vstart) relp+ where+ drawF = if path_end == PATH_OPEN then tellSubOpen else tellSubClosed+ ++cycle :: (Floating u, InterpretUnit u) => RelBuild u ()+cycle = + gets cumulative_disp >>= \v1 -> + gets pen_dc_modifier >>= \cf ->+ gets active_path >>= \(start,acc) -> + tellSubClosed cf start (snocLineTo acc start) >> + sets_ (\s -> s { active_path = (v1, mempty)})+++setIncline :: Radian -> RelBuild u ()+setIncline ang = sets_ upd+ where+ upd = (\s -> s { current_incline = ang })+++pivot :: RelBuild u ()+pivot = sets_ upd+ where+ upd = (\s i -> s { pivot_position = i }) <*> cumulative_disp+++--------------------------------------------------------------------------------+-- Derived operators+++pen_colour :: (Floating u, InterpretUnit u) + => RGBi -> RelBuild u ()+pen_colour rgb = penCtxUpdate (stroke_colour rgb)++pen_width :: (Floating u, InterpretUnit u) + => Double -> RelBuild u ()+pen_width d = penCtxUpdate (set_line_width d)++++hline :: Floating u => u -> RelBuild u ()+hline dx = line (hvec dx)++vline :: Floating u => u -> RelBuild u ()+vline dy = line (vvec dy)++aline :: Floating u => Radian -> u -> RelBuild u ()+aline ang u = line (avec ang u)++hmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+hmove dx = move (hvec dx)++vmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+vmove dy = move (vvec dy)+++amove :: (Floating u, InterpretUnit u) => Radian -> u -> RelBuild u ()+amove ang u = move (avec ang u)+++line_up :: Floating u => u -> RelBuild u ()+line_up u = line (vvec u)++line_down :: Floating u => u -> RelBuild u ()+line_down u = line (vvec $ negate u)++line_left :: Floating u => u -> RelBuild u ()+line_left u = line (hvec $ negate u)+ +line_right :: Floating u => u -> RelBuild u ()+line_right u = line (hvec u)++-- | Diagonal lines ++line_up_left :: Floating u => u -> RelBuild u ()+line_up_left u = line (vec (-u) u)++line_up_right :: Floating u => u -> RelBuild u ()+line_up_right u = line (vec u u)++line_down_left :: Floating u => u -> RelBuild u ()+line_down_left u = line (vec (-u) (-u))++line_down_right :: Floating u => u -> RelBuild u ()+line_down_right u = line (vec u (-u))+++-- Cardinal lines++line_north :: Floating u => u -> RelBuild u ()+line_north = vline+++line_south :: Floating u => u -> RelBuild u ()+line_south = vline . negate++line_east :: Floating u => u -> RelBuild u ()+line_east = hline++line_west :: Floating u => u -> RelBuild u ()+line_west = hline . negate+++line_northeast :: Floating u => u -> RelBuild u ()+line_northeast = line . avec (0.25 * pi)++line_northwest :: Floating u => u -> RelBuild u ()+line_northwest = line . avec (0.75 * pi)++line_southeast :: Floating u => u -> RelBuild u ()+line_southeast = line . avec (1.75 * pi)++line_southwest :: Floating u => u -> RelBuild u ()+line_southwest = line . avec (1.25 * pi)+++++move_up :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_up u = move (vvec u)++move_down :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_down u = move (vvec $ negate u)++move_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_left u = move (hvec $ negate u)+ +move_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_right u = move (hvec u)++++-- | Diagonal moves ++move_up_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_up_left u = move (vec (-u) u)++move_up_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_up_right u = move (vec u u)++move_down_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_down_left u = move (vec (-u) (-u))++move_down_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_down_right u = move (vec u (-u))+++-- Cardinal moves++move_north :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_north = vmove+++move_south :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_south = vmove . negate++move_east :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_east = hmove++move_west :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_west = hmove . negate+++move_northeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_northeast = move . avec (0.25 * pi)++move_northwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_northwest = move . avec (0.75 * pi)++move_southeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_southeast = move . avec (1.75 * pi)++move_southwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()+move_southwest = move . avec (1.25 * pi)+
+ src/Wumpus/Drawing/Paths/Base/RelPath.hs view
@@ -0,0 +1,269 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Base.RelPath+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Relative path type - this should be more amenable for building +-- complex drawings than the PrimPath type in Wumpus-Core.+-- +-- Note - RelPath is not directly equivalent to AbsPath.+-- AbsPath is more powerful - as it is expected to have more +-- demanding use-cases (e.g. connector paths).+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Base.RelPath+ ( +++ -- * Relative path type++ RelPath+ , DRelPath++ -- * Construction+ , empty+ , line1+ , curve1+ , vertexPath+ , curvedPath+ + , circular++ -- * Queries+ , null+++ -- * Concat+ , append+ , consLineTo+ , snocLineTo+ , consCurveTo+ , snocCurveTo+++ -- * Conversion+ , fromPathAlgVertices+ , fromPathAlgCurves++ , toPrimPath+ , toAbsPath+ , strokeRelPath++ ) where+++import Wumpus.Drawing.Paths.Base.AbsPath ( AbsPath )+import qualified Wumpus.Drawing.Paths.Base.AbsPath as Abs++import Wumpus.Basic.Geometry+import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Basic.Utils.JoinList ( JoinList, ViewL(..), viewl, join )+import qualified Wumpus.Basic.Utils.JoinList as JL++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace++import qualified Data.Foldable as F+import Data.Monoid+import qualified Data.Traversable as T+import Prelude hiding ( null )++++++-- | Relative Path data type.+-- +-- Note this type is more limited than AbsPath, it does not+-- support /introspective/ operations like @length@ or anchors.+--+newtype RelPath u = RelPath { getRelPath :: JoinList (RelPathSeg u) }+ deriving (Eq,Show)++type instance DUnit (RelPath u) = u+++type DRelPath = RelPath Double++-- No annotations...+-- +data RelPathSeg u = RelLineSeg (Vec2 u)+ | RelCurveSeg (Vec2 u) (Vec2 u) (Vec2 u)+ deriving (Eq,Show)+++type instance DUnit (RelPathSeg u) = u++++--------------------------------------------------------------------------------++instance Functor RelPath where+ fmap f = RelPath . fmap (fmap f) . getRelPath++instance Functor RelPathSeg where+ fmap f (RelLineSeg v1) = + RelLineSeg (fmap f v1)++ fmap f (RelCurveSeg v1 v2 v3) = + RelCurveSeg (fmap f v1) (fmap f v2) (fmap f v3)+++instance Monoid (RelPath u) where+ mempty = empty+ mappend = append+++--------------------------------------------------------------------------------+-- Construction+++-- | An empty relative path is acceptible to Wumpus because +-- it is always drawn as a LocGraphic.+--+empty :: RelPath u +empty = RelPath mempty++-- | Create a relative path from a single straight line.+--+line1 :: Vec2 u -> RelPath u+line1 = RelPath . JL.one . RelLineSeg+++-- | Create a relative path from a single Bezier curve.+--+curve1 :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u+curve1 v1 v2 v3 = RelPath $ JL.one $ RelCurveSeg v1 v2 v3+++vertexPath :: [Vec2 u] -> RelPath u+vertexPath [] = empty+vertexPath (x:xs) = go (line1 x) xs+ where+ go acc [] = acc+ go acc (v:vs) = go (acc `snocLineTo` v) vs++++curvedPath :: [Vec2 u] -> RelPath u+curvedPath xs = case xs of + (v1:v2:v3:vs) -> go (curve1 v1 v2 v3) vs+ _ -> empty+ where+ go acc (v1:v2:v3:vs) = go (acc `append` curve1 v1 v2 v3) vs+ go acc _ = acc++++circular :: Floating u => u -> RelPath u+circular = snd . fromPathAlgCurves . circlePathAlg ++--------------------------------------------------------------------------------+-- Queries++null :: RelPath u -> Bool+null = JL.null . getRelPath++++--------------------------------------------------------------------------------+-- Concat ++infixr 1 `append`++++append :: RelPath u -> RelPath u -> RelPath u+append (RelPath se0) (RelPath se1) = RelPath $ se0 `join` se1+++consLineTo :: Vec2 u -> RelPath u -> RelPath u +consLineTo v1 (RelPath se) = RelPath $ JL.cons (RelLineSeg v1) se++snocLineTo :: RelPath u -> Vec2 u -> RelPath u+snocLineTo (RelPath se) v1 = RelPath $ JL.snoc se (RelLineSeg v1)++++consCurveTo :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u -> RelPath u +consCurveTo v1 v2 v3 (RelPath se) = RelPath $ JL.cons (RelCurveSeg v1 v2 v3) se++snocCurveTo :: RelPath u -> Vec2 u -> Vec2 u -> Vec2 u -> RelPath u+snocCurveTo (RelPath se) v1 v2 v3 = RelPath $ JL.snoc se (RelCurveSeg v1 v2 v3)++++++--------------------------------------------------------------------------------+-- Conversion++fromPathAlgVertices :: Num u => PathAlg u -> (Vec2 u, RelPath u)+fromPathAlgVertices = bimap fn vertexPath . runPathAlgVec+ where+ fn = maybe (V2 0 0) id++fromPathAlgCurves :: Num u => PathAlg u -> (Vec2 u, RelPath u)+fromPathAlgCurves = bimap fn curvedPath . runPathAlgVec+ where+ fn = maybe (V2 0 0) id+++toPrimPath :: InterpretUnit u => Point2 u -> RelPath u -> Query PrimPath+toPrimPath start (RelPath segs) = + uconvertCtxF start >>= \dstart -> + T.mapM uconvertCtxF segs >>= \dsegs ->+ return $ relPrimPath dstart $ F.foldr fn [] dsegs+ where+ fn (RelLineSeg v1) ac = relLineTo v1 : ac+ fn (RelCurveSeg v1 v2 v3) ac = relCurveTo v1 v2 v3 : ac+++toAbsPath :: (Floating u, Ord u, Tolerance u) + => Point2 u -> RelPath u -> AbsPath u+toAbsPath start (RelPath segs) = step1 start $ viewl segs+ where+ step1 p0 EmptyL = Abs.empty p0++ step1 p0 (RelLineSeg v1 :< se) = + let (pth,end) = aline p0 v1 in step2 end pth (viewl se)++ step1 p0 (RelCurveSeg v1 v2 v3 :< se) = + let (pth,end) = acurve p0 v1 v2 v3 in step2 end pth (viewl se)++ step2 _ acc EmptyL = acc+ step2 p0 acc (RelLineSeg v1 :< se) = + let (s1,end) = aline p0 v1 + in step2 end (acc `Abs.append` s1) (viewl se)++ step2 p0 acc (RelCurveSeg v1 v2 v3 :< se) = + let (s1,end) = acurve p0 v1 v2 v3 + in step2 end (acc `Abs.append` s1) (viewl se)++ aline p0 v1 = + let p1 = p0 .+^ v1 in (Abs.line1 p0 p1, p1)++ acurve p0 v1 v2 v3 = + let p1 = p0 .+^ v1+ p2 = p1 .+^ v2+ p3 = p2 .+^ v3+ in (Abs.curve1 p0 p1 p2 p3, p3)++++strokeRelPath :: InterpretUnit u => RelPath u -> LocGraphic u+strokeRelPath rp = + promoteR1 $ \start -> toPrimPath start rp >>= openStroke++
− src/Wumpus/Drawing/Paths/Connectors.hs
@@ -1,253 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.Connectors--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Library of connector paths...------ \*\* WARNING \*\* this module is experimental and may change --- significantly in future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.Connectors- ( -- ConnectorPath- , DConnectorPath- , sconnect-- , connLine-- , connRightVH- , connRightHV- , connRightVHV- , connRightHVH-- , connIsosceles- , connIsosceles2- , connLightningBolt-- , connIsoscelesCurve- , connSquareCurve- , connUSquareCurve-- , connTrapezoidCurve- , connZSquareCurve- , connUZSquareCurve-- ) where--import Wumpus.Drawing.Paths.Base-import Wumpus.Drawing.Paths.ControlPoints--import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space--import Control.Applicative-import Prelude hiding ( length )----- | Note - a ConnectorPath is not drawn automatically, it is a--- @ConnectorCF@ not a @ConnectorGraphic@ or @ConnectorImage@.----type ConnectorPath u = ConnectorCF u (Path u)--type DConnectorPath = ConnectorPath Double------ Maybe this should be ConnectorPath u -> ConnectorImage u (Path u) instead?--- This would be closer to the new shapes...----sconnect :: Num u - => ConnectorPath u -> Point2 u -> Point2 u -> Image u (Path u)-sconnect mf p0 p1 = - connect mf p0 p1 >>= \cpath -> - intoImage (pure cpath) (openStroke $ toPrimPath cpath) - ---- | Build the path with interior round corners.--- -roundCornerPath :: (Real u, Floating u, FromPtSize u) - => [Point2 u] -> CF (Path u)-roundCornerPath xs = getRoundCornerSize >>= \sz -> - if sz == 0 then return (traceLinePoints xs) - else return (roundInterior sz xs)---------------------------------------------------------------------------------------- | Connect with a straight line.----connLine :: Floating u => ConnectorPath u-connLine = promoteR2 $ \p0 p1 -> pure $ line p0 p1------ | Right-angled connector - go vertical, then go horizontal.----connRightVH :: (Real u, Floating u, FromPtSize u) => ConnectorPath u-connRightVH = promoteR2 $ \ p0@(P2 x0 _) p1@(P2 _ y1) ->- let mid = P2 x0 y1 in roundCornerPath [p0, mid, p1]------ | Right-angled connector - go horizontal, then go vertical.----connRightHV :: (Real u, Floating u, FromPtSize u) - => ConnectorPath u-connRightHV = promoteR2 $ \ p0@(P2 _ y0) p1@(P2 x1 _) -> - let mid = P2 x1 y0 in roundCornerPath [p0, mid, p1]---- | Right-angled connector - go vertical for the supplied --- distance, go horizontal, go vertical again for the --- remaining distance.--- -connRightVHV :: (Real u, Floating u, FromPtSize u) - => u -> ConnectorPath u-connRightVHV v = promoteR2 $ \ p0@(P2 x0 _) p1@(P2 x1 _) ->- let a0 = p0 .+^ vvec v- a1 = a0 .+^ hvec (x1 - x0)- in roundCornerPath [p0, a0, a1, p1]----- | Right-angled connector - go horizontal for the supplied --- distance, go verical, go horizontal again for the --- remaining distance.--- -connRightHVH :: (Real u, Floating u, FromPtSize u) - => u -> ConnectorPath u-connRightHVH h = promoteR2 $ \ p0@(P2 _ y0) p1@(P2 _ y1) -> - let a0 = p0 .+^ hvec h- a1 = a0 .+^ vvec (y1 - y0)- in roundCornerPath [p0,a0,a1,p1]----- | /Triangular/ joint.--- --- @u@ is the altitude of the triangle.----connIsosceles :: (Real u, Floating u, FromPtSize u) - => u -> ConnectorPath u -connIsosceles dy = promoteR2 $ \ p0 p1 -> - let mid_pt = midpointIsosceles dy p0 p1- in roundCornerPath [p0, mid_pt, p1]- - ------ | Double /triangular/ joint.--- --- @u@ is the altitude of the triangle.----connIsosceles2 :: (Real u, Floating u, FromPtSize u)- => u -> ConnectorPath u -connIsosceles2 u = promoteR2 $ \ p0 p1 -> - let (cp0,cp1) = dblpointIsosceles u p0 p1- in roundCornerPath [ p0, cp0, cp1, p1 ]------ | /Lightning bolt/ joint - a two joint connector with an /axis/--- perpendicular to the connector direction.--- --- @u@ is the half length of the of the axis.----connLightningBolt :: (Real u, Floating u, FromPtSize u) - => u -> ConnectorPath u -connLightningBolt u = promoteR2 $ \ p0 p1 -> - let cp0 = midpointIsosceles u p0 p1- cp1 = midpointIsosceles (-u) p0 p1- in roundCornerPath [ p0, cp0, cp1, p1 ]---------------------------------------------------------------------------------------- | Form a curve inside an isosceles triangle. ------ The two Bezier control points take the same point - the--- altitude of the triangle. The curve tends to be quite shallow--- relative to the altitude.------ @u@ is the altitude of the triangle.----connIsoscelesCurve :: (Real u, Floating u, FromPtSize u) - => u -> ConnectorPath u -connIsoscelesCurve u = promoteR2 $ \ p0 p1 ->- let control_pt = midpointIsosceles u p0 p1- in pure $ traceCurvePoints [p0, control_pt, control_pt, p1]- - ---- | Form a curve inside a square. ------ The two Bezier control points take the /top/ corners. The--- curve tends to be very deep.--- -connSquareCurve :: (Real u, Floating u, FromPtSize u) - => ConnectorPath u -connSquareCurve = promoteR2 $ \ p0 p1 ->- let (cp0,cp1) = squareFromBasePoints p0 p1- in pure $ traceCurvePoints [p0, cp0, cp1, p1]------ | Form a curve inside a square. ------ As per 'connSquareCurve' but the curve is drawn /underneath/--- the line formed between the start and end points.--- --- (Underneath is modulo the direction, of course).--- -connUSquareCurve :: (Real u, Floating u, FromPtSize u) - => ConnectorPath u -connUSquareCurve = promoteR2 $ \ p0 p1 -> - let (cp0,cp1) = usquareFromBasePoints p0 p1- in pure $ traceCurvePoints [p0, cp0, cp1, p1]----- | altitude * ratio_to_base ------ Form a curve inside a trapeziod.--- -connTrapezoidCurve :: (Real u, Floating u, FromPtSize u) - => u -> u -> ConnectorPath u -connTrapezoidCurve u ratio_to_base = promoteR2 $ \p0 p1 -> - let (cp0,cp1) = trapezoidFromBasePoints u ratio_to_base p0 p1- in pure $ traceCurvePoints [p0, cp0, cp1, p1]----- | Make a curve within a square, following the corner points as--- a Z.----connZSquareCurve :: (Real u, Floating u, FromPtSize u) - => ConnectorPath u -connZSquareCurve = promoteR2 $ \p0 p1 -> - let (cp0,cp1) = squareFromCornerPoints p0 p1- in pure $ traceCurvePoints [p0,cp0,cp1,p1]---- | Make a curve within a square, following the corner points as--- a Z.------ The order of tracing flips the control points, so this is an--- /underneath/ version of 'connZSquareCurve'.--- -connUZSquareCurve :: (Real u, Floating u, FromPtSize u) - => ConnectorPath u -connUZSquareCurve = promoteR2 $ \ p0 p1 -> - let (cp0,cp1) = squareFromCornerPoints p0 p1 - in pure $ traceCurvePoints [p0,cp1,cp0,p1]-
− src/Wumpus/Drawing/Paths/ControlPoints.hs
@@ -1,189 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.ControlPoints--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Collection of point manufacturing functions.------ \*\* WARNING \*\* this module is experimental and may change --- significantly in future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.ControlPoints- ( -- midpointIsosceles- , dblpointIsosceles-- , rectangleFromBasePoints- , squareFromBasePoints- , usquareFromBasePoints-- , trapezoidFromBasePoints-- , squareFromCornerPoints-- ) where--import Wumpus.Basic.Kernel--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space------- | 'midpointIsosceles' : --- @ altitude * start_pt * end_pt -> mid_pt @------ Triangular midpoint.--- --- @u@ is the altitude of the triangle - negative values of u --- form the triangle below the line.----midpointIsosceles :: (Real u, Floating u) - => u -> Point2 u -> Point2 u -> Point2 u-midpointIsosceles u p1@(P2 x1 y1) p2@(P2 x2 y2) = - mid_pt .+^ avec perp_ang u- where- mid_pt = P2 (x1 + 0.5*(x2-x1)) (y1 + 0.5*(y2-y1))- perp_ang = (pi*0.5) + vdirection (pvec p1 p2) ------ | 'dblpointIsosceles' : --- @ altitude * start_pt * end_pt * (third_pt, two_thirds_pt) @--- --- Double triangular joint - one joint at a third of the line--- length, the other at two thirds.--- -dblpointIsosceles :: (Real u, Floating u) - => u -> Point2 u -> Point2 u -> (Point2 u, Point2 u) -dblpointIsosceles u p1@(P2 x1 y1) p2@(P2 x2 y2) = - (mid1 .+^ avec perp_ang u, mid2 .-^ avec perp_ang u)- where- mid1 = P2 (x1 + 0.33*(x2-x1)) (y1 + 0.33*(y2-y1))- mid2 = P2 (x1 + 0.66*(x2-x1)) (y1 + 0.66*(y2-y1))- perp_ang = (pi*0.5) + vdirection (pvec p1 p2) ----------------------------------------------------------------------------------------- | 'rectangleFromBasePoints' : --- @ altitude * start_pt * end_pt * (top_left, top_right) @--- --- Control points forming a rectangle. ------ The two manufactured control points form the top corners, --- so the supplied points map as @start_point == bottom_left@ and --- @end_point == bottom_right@.----rectangleFromBasePoints :: (Real u, Floating u) - => u -> Point2 u -> Point2 u -> (Point2 u, Point2 u)-rectangleFromBasePoints u p1 p2 = (cp1, cp2)- where- base_vec = pvec p1 p2- theta = vdirection base_vec- cp1 = displacePerpendicular u theta p1- cp2 = displacePerpendicular u theta p2----- | 'squareFromBasePoints' : --- @ start_pt -> end_pt -> (top_left, top_right) @--- --- Control points forming a square - side_len derived from the --- distance between start and end points.------ The two manufactured control points form the top corners, --- so the supplied points map as @start_point == bottom_left@ and --- @end_point == bottom_right@.----squareFromBasePoints :: (Real u, Floating u) - => Point2 u -> Point2 u -> (Point2 u, Point2 u)-squareFromBasePoints p1 p2 = rectangleFromBasePoints side_len p1 p2- where- side_len = vlength $ pvec p1 p2----- | 'usquareFromBasePoints' : --- @ start_pt -> end_pt -> (bottom_left, bottom_right) @--- --- Control points forming a square - side_len derived from the --- distance between start and end points.------ As per 'squareFromBasePoints' but the square is drawn --- /underneath/ the line formed between the start and end points.--- (Underneath is modulo the direction, of course).------ The two manufactured control points form the /bottom/ corners, --- so the supplied points map as @start_point == top_left@ and --- @end_point == top_right@.--- -usquareFromBasePoints :: (Real u, Floating u) - => Point2 u -> Point2 u -> (Point2 u, Point2 u)-usquareFromBasePoints p1 p2 = rectangleFromBasePoints side_len p1 p2- where- side_len = negate $ vlength $ pvec p1 p2-------- | 'trapezoidFromBasePoints' : --- @ altitude * ratio_to_base * start_pt * end_pt -> (top_left, top_right) @------ Control points form an isosceles trapezoid.------ The two manufactured control points form the top corners, --- so the supplied points map as @start_point == bottom_left@ and --- @end_point == bottom_right@.--- -trapezoidFromBasePoints :: (Real u, Floating u) - => u -> u -> Point2 u -> Point2 u - -> (Point2 u, Point2 u) -trapezoidFromBasePoints u ratio_to_base p1 p2 = (cp1, cp2)- where- base_vec = pvec p1 p2- base_len = vlength base_vec- theta = vdirection base_vec- half_ulen = 0.5 * ratio_to_base * base_len- base_mid = displaceParallel (0.5 * base_len) theta p1- ubase_mid = displacePerpendicular u theta base_mid- cp1 = displaceParallel (-half_ulen) theta ubase_mid- cp2 = displaceParallel half_ulen theta ubase_mid------- | 'squareFromCornerPoints' : --- @ altitude * start_pt * end_pt * (top_left, bottom_right) @--- --- Control points forming a square bisected by the line from --- start_pt to end_pt. ------ The two manufactured control points form the top_left and--- bottom_right corners, so the supplied points map as --- @start_point == bottom_left@ and @end_point == top_right@.----squareFromCornerPoints :: (Real u, Floating u) - => Point2 u -> Point2 u -> (Point2 u, Point2 u) -squareFromCornerPoints p1 p2 = (cp1, cp2)- where- base_vec = pvec p1 p2- half_len = 0.5 * (vlength base_vec)- theta = vdirection base_vec- base_mid = displaceParallel half_len theta p1- cp1 = displacePerpendicular half_len theta base_mid- cp2 = displacePerpendicular (-half_len) theta base_mid-
− src/Wumpus/Drawing/Paths/MonadicConstruction.hs
@@ -1,160 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.MonadicConstruction--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Build paths monadically.------ \*\* WARNING \*\* this module is an experiment, and may --- change significantly or even be dropped from future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.MonadicConstruction- ( -- PathM- , runPath- , execPath-- , tip-- , lineto- , rlineto- , hline- , vline-- , bezierto- , curveto-- , verticalHorizontal- , horizontalVertical-- ) where--import Wumpus.Basic.Utils.HList-import Wumpus.Drawing.Paths.Base--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space--import Control.Applicative-import Data.List----- Are connectors and paths quite different things?------ It looks like they are - connectors always know start and end --- points.-------- State monad version is quite good - it ameliorates the problem--- of joining to the end point of an empty path...--data St u = St- { current_point :: Point2 u - , path_acc :: H (Path u)- }---newtype PathM u a = PathM { getPathM :: St u -> (a,St u) }---instance Functor (PathM u) where- fmap f mf = PathM $ \s -> let (a,s1) = getPathM mf s in (f a,s1)---instance Applicative (PathM u) where- pure a = PathM $ \s -> (a,s)- mf <*> ma = PathM $ \s -> let (f,s1) = getPathM mf s- (a,s2) = getPathM ma s1- in (f a,s2)--instance Monad (PathM u) where- return a = PathM $ \s -> (a,s)- m >>= k = PathM $ \s -> let (a,s1) = getPathM m s in- (getPathM . k) a s1------ Running the path is (probably) agnostic to the DrawingCtx.----runPath :: Floating u => Point2 u -> PathM u a -> (a, Path u)-runPath start mf = - let (a,s') = getPathM mf s in (a, post $ toListH $ path_acc s')- where- s = St { current_point = start- , path_acc = emptyH- }- post [] = line start start- post (x:xs) = foldl' append x xs --execPath :: Floating u => Point2 u -> PathM u a -> Path u-execPath start mf = snd $ runPath start mf--snocline :: Floating u => Vec2 u -> PathM u ()-snocline v = PathM $ \(St pt ac) -> let ep = pt .+^ v - in ((), St ep (ac `snocH` line pt ep))---tip :: PathM u (Point2 u)-tip = PathM $ \s -> (current_point s,s)---lineto :: Floating u => Point2 u -> PathM u ()-lineto pt = PathM $ \(St p0 ac) -> ((), St pt (ac `snocH` line p0 pt))--rlineto :: Floating u => Vec2 u -> PathM u ()-rlineto (V2 dx dy) = tip >>= \(P2 x y) -> lineto (P2 (x+dx) (y+dy))---hline :: Floating u => u -> PathM u ()-hline len = snocline (hvec len) --vline :: Floating u => u -> PathM u ()-vline len = snocline (vvec len) ----bezierto :: (Floating u, Ord u, FromPtSize u) - => Point2 u -> Point2 u -> Point2 u -> PathM u ()-bezierto c1 c2 ep = PathM $ \(St p0 ac) -> - ((), St ep (ac `snocH` curve p0 c1 c2 ep))-----------curveto :: (Floating u, Ord u, FromPtSize u) - => Radian -> Radian -> Point2 u -> PathM u ()-curveto cin cout end = PathM $ \(St p0 ac) -> - let seg = curveByAngles p0 cin cout end - ac1 = ac `snocH` seg- end1 = tipR seg- in ((), St end1 ac1) -----verticalHorizontal :: Floating u => Point2 u -> PathM u ()-verticalHorizontal (P2 x y) = - tip >>= \(P2 x0 _) -> lineto (P2 x0 y) >> lineto (P2 x y)--horizontalVertical :: Floating u => Point2 u -> PathM u ()-horizontalVertical (P2 x y) = - tip >>= \(P2 _ y0) -> lineto (P2 x y0) >> lineto (P2 x y)-
+ src/Wumpus/Drawing/Paths/Relative.hs view
@@ -0,0 +1,27 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Relative+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Shim import module for the Relative Path modules.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Relative+ ( ++ module Wumpus.Drawing.Paths.Base.RelBuilder+ , module Wumpus.Drawing.Paths.Base.RelPath++ ) where++import Wumpus.Drawing.Paths.Base.RelBuilder+import Wumpus.Drawing.Paths.Base.RelPath+
+ src/Wumpus/Drawing/Paths/Vamps.hs view
@@ -0,0 +1,56 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Vamps+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Shim import module for the Absolute Path modules.+--+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Vamps+ ( ++ -- * Re-exported types+ Vamp(..)+ , PathEnd(..)++ , circleVamp++ ) where++import Wumpus.Drawing.Paths.Base.BuildCommon+import Wumpus.Drawing.Paths.Base.RelPath++import Wumpus.Basic.Geometry -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++import Data.VectorSpace -- package: vector-space+++-- TODO - library of useful / illustrative vamps (circle, square etc.)+++++circleVamp :: (Fractional u, Floating u) => Vec2 u -> Vamp u+circleVamp v0 = Vamp { vamp_move_span = v0+ , vamp_move_start = half_v0 ^+^ v1+ , vamp_dc_update = id+ , vamp_deco_path = path+ , vamp_path_end = PATH_CLOSED+ }+ where+ radius = 0.5 * vlength v0+ half_v0 = 0.5 *^ v0+ (v1,path) = fromPathAlgCurves $ circlePathAlg radius++ -- Note - circlePathAlg starts from east
src/Wumpus/Drawing/Shapes/Base.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -24,8 +23,10 @@ Shape , DShape + , shapeMap , makeShape , strokedShape+ , dblStrokedShape , filledShape , borderedShape , rstrokedShape@@ -41,21 +42,23 @@ , makeShapeCTM , ctmCenter , ctmAngle- , displaceCenter- + , projectFromCtr ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Core -- package: wumpus-core +import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Colour ( white ) import Data.AffineSpace -- package: vector-space import Control.Applicative +-- import Data.Traversable ( Traversable )+-- import qualified Data.Traversable as T -- | Shape is a record of three /LocTheta/ functions - -- functions /from Point and Angle to answer/. @@ -73,23 +76,28 @@ -- to address specific locations on the Shape border so -- \"node and link\" diagrams can be made easily. ---data Shape u a = Shape - { shape_ans_fun :: LocThetaCF u a- , shape_path_fun :: LocThetaCF u (Path u) +data Shape t u = Shape + { shape_ans_fun :: LocThetaQuery u (t u)+ , shape_path_fun :: LocThetaQuery u (AbsPath u) , shape_decoration :: LocThetaGraphic u } -type DShape a = Shape Double a+type DShape t = Shape t Double -type instance DUnit (Shape u a) = u +-- Design note - shapes look like they should be constrained to +-- InterpretUnit rather than CtxSize, this allows direct affine +-- transformations.+--+ -------------------------------------------------------------------------------- -instance Functor (Shape u) where- fmap f = (\s i -> s { shape_ans_fun = fmap f i }) - <*> shape_ans_fun+shapeMap :: (t u -> t' u) -> Shape t u -> Shape t' u+shapeMap f = (\s sf -> s { shape_ans_fun = promoteR2 $ \pt ang -> + fmap f $ apply2R2 sf pt ang }) + <*> shape_ans_fun -- Note - there are no instances of Applicative, Monad, @@ -104,7 +112,8 @@ -------------------------------------------------------------------------------- -makeShape :: Num u => LocThetaCF u a -> LocThetaCF u (Path u) -> Shape u a+makeShape :: InterpretUnit u+ => LocThetaQuery u (t u) -> LocThetaQuery u (AbsPath u) -> Shape t u makeShape f g = Shape { shape_ans_fun = f , shape_path_fun = g , shape_decoration = emptyLocThetaGraphic@@ -113,59 +122,75 @@ -strokedShape :: Num u => Shape u a -> LocImage u a+strokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u) strokedShape = shapeToLoc closedStroke -filledShape :: Num u => Shape u a -> LocImage u a+-- | Note - this is simplistic double stroking - draw a background +-- line with triple thickness and draw a white line on top.+--+-- I think this is what TikZ does, but it works better for TikZ +-- where the extra thickness seems to be accounted for by the +-- anchors. For Wumpus, arrows cut into the outside black line.+--+-- Probably Wumpus should calculate two paths instead.+--+dblStrokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)+dblStrokedShape sh = decorateR1 back fore + where+ img = shapeToLoc closedStroke sh+ back = getLineWidth >>= \lw ->+ localize (set_line_width $ lw * 3.0) img+ fore = pushR1 ignoreAns $ localize (stroke_colour white) img++++filledShape :: InterpretUnit u => Shape t u -> LocImage u (t u) filledShape = shapeToLoc filledPath -borderedShape :: Num u => Shape u a -> LocImage u a+borderedShape :: InterpretUnit u => Shape t u -> LocImage u (t u) borderedShape = shapeToLoc borderedPath -shapeToLoc :: Num u - => (PrimPath u -> Graphic u) -> Shape u a -> LocImage u a-shapeToLoc pathF sh = promoteR1 $ \pt -> - atRot (shape_ans_fun sh) pt 0 >>= \a -> - atRot (shape_path_fun sh) pt 0 >>= \spath -> - let g1 = pathF $ toPrimPath spath - g2 = atRot (shape_decoration sh) pt 0 - in intoImage (pure a) (g1 `oplus` g2)+shapeToLoc :: InterpretUnit u+ => (PrimPath -> Graphic u) -> Shape t u -> LocImage u (t u)+shapeToLoc drawF sh = promoteR1 $ \pt -> + apply2R2 (shape_ans_fun sh) pt 0 >>= \a -> + apply2R2 (shape_path_fun sh) pt 0 >>= \spath -> + let g2 = atIncline (shape_decoration sh) pt 0 + in intoImage (pure a) (decorateR0 g2 $ toPrimPath spath >>= drawF) -rstrokedShape :: Num u => Shape u a -> LocThetaImage u a+rstrokedShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u) rstrokedShape = shapeToLocTheta closedStroke -rfilledShape :: Num u => Shape u a -> LocThetaImage u a+rfilledShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u) rfilledShape = shapeToLocTheta filledPath -rborderedShape :: Num u => Shape u a -> LocThetaImage u a+rborderedShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u) rborderedShape = shapeToLocTheta borderedPath -shapeToLocTheta :: Num u - => (PrimPath u -> Graphic u) -> Shape u a -> LocThetaImage u a-shapeToLocTheta pathF sh = promoteR2 $ \pt theta -> - atRot (shape_ans_fun sh) pt theta >>= \a -> - atRot (shape_path_fun sh) pt theta >>= \spath -> - let g1 = pathF $ toPrimPath spath - g2 = atRot (shape_decoration sh) pt theta- in intoImage (pure a) (g1 `oplus` g2)+shapeToLocTheta :: InterpretUnit u+ => (PrimPath -> Graphic u) -> Shape t u -> LocThetaImage u (t u)+shapeToLocTheta drawF sh = promoteR2 $ \pt theta -> + apply2R2 (shape_ans_fun sh) pt theta >>= \a -> + apply2R2 (shape_path_fun sh) pt theta >>= \spath -> + let g2 = atIncline (shape_decoration sh) pt theta+ in intoImage (pure a) (decorateR0 g2 $ toPrimPath spath >>= drawF) -- | Draw the shape path with round corners. -- -roundCornerShapePath :: (Real u, Floating u, FromPtSize u) - => [Point2 u] -> CF (Path u)-roundCornerShapePath xs = getRoundCornerSize >>= \sz -> - if sz == 0 then return (traceLinePoints xs) - else return (roundTrail sz xs)+roundCornerShapePath :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => u -> [Point2 u] -> Query (AbsPath u)+roundCornerShapePath sz xs = + if sz `tEQ` 0 then return (vertexPath xs) else return (roundTrail sz xs) -- | The path angle can be modified. This allows /inverse/ -- versions of shapes (e.g. InvTriangle) to be made by@@ -176,26 +201,19 @@ -- angle. The anchors are typically implemented by rotating the -- correspoding anchor of the wrapped Shape about its center. -- -updatePathAngle :: (Radian -> Radian) -> Shape u a -> Shape u a+updatePathAngle :: (Radian -> Radian) -> Shape t u -> Shape t u updatePathAngle f = - (\s i -> s { shape_path_fun = moveTheta (circularModulo . f) i})+ (\s i -> s { shape_path_fun = promoteR2 $ \pt ang -> + apply2R2 i pt (mvTheta ang) }) <*> shape_path_fun+ where+ mvTheta = circularModulo . f -setDecoration :: LocThetaGraphic u -> Shape u a -> Shape u a+setDecoration :: LocThetaGraphic u -> Shape t u -> Shape t u setDecoration gf = (\s -> s { shape_decoration = gf }) ---- For Wumpus-Basic...--- | Move the /rotation/ of a LocThetaImage with the supplied --- displacement function.----moveTheta :: (Radian -> Radian) -> LocThetaCF u a -> LocThetaCF u a-moveTheta f ma = promoteR2 $ \pt theta -> apply2R2 ma pt (f theta)--- -------------------------------------------------------------------------------- -- CTM @@ -205,31 +223,47 @@ data ShapeCTM u = ShapeCTM { ctm_center :: Point2 u- , ctm_scale_x :: !u- , ctm_scale_y :: !u+ , ctm_scale_x :: !Double+ , ctm_scale_y :: !Double , ctm_rotation :: Radian } deriving (Eq,Ord,Show) - type instance DUnit (ShapeCTM u) = u -makeShapeCTM :: Num u => Point2 u -> Radian -> ShapeCTM u++instance Functor ShapeCTM where+ fmap f = (\s i -> s { ctm_center = fmap f i }) <*> ctm_center+++makeShapeCTM :: Point2 u -> Radian -> ShapeCTM u makeShapeCTM pt ang = ShapeCTM { ctm_center = pt , ctm_scale_x = 1 , ctm_scale_y = 1 , ctm_rotation = ang } -instance Num u => Scale (ShapeCTM u) where- scale sx sy = (\s x y -> s { ctm_scale_x = x*sx, ctm_scale_y = y*sy })- <*> ctm_scale_x <*> ctm_scale_y+ctmCenter :: ShapeCTM u -> Point2 u+ctmCenter = ctm_center +ctmAngle :: ShapeCTM u -> Radian+ctmAngle = ctm_rotation -instance Rotate (ShapeCTM u) where- rotate ang = (\s i -> s { ctm_rotation = circularModulo $ i+ang })- <*> ctm_rotation +instance (Fractional u) => Scale (ShapeCTM u) where+ scale sx sy = (\s x y pt -> s { ctm_scale_x = x*sx+ , ctm_scale_y = y*sy + , ctm_center = scale sx sy pt })+ <*> ctm_scale_x <*> ctm_scale_y <*> ctm_center+++instance (Real u, Floating u) => Rotate (ShapeCTM u) where+ rotate ang = (\s i pt -> let ctr = rotate ang pt+ in s { ctm_rotation = circularModulo $ i+ang+ , ctm_center = ctr })+ <*> ctm_rotation <*> ctm_center++ instance (Real u, Floating u) => RotateAbout (ShapeCTM u) where rotateAbout ang pt = (\s ctr i -> s { ctm_rotation = circularModulo $ i+ang@@ -237,27 +271,18 @@ <*> ctm_center <*> ctm_rotation -instance Num u => Translate (ShapeCTM u) where- translate dx dy = (\s (P2 x y) -> s { ctm_center = P2 (x+dx) (y+dy) })- <*> ctm_center-+instance (Num u) => Translate (ShapeCTM u) where+ translate dx dy = + (\s i -> s { ctm_center = translate dx dy i })+ <*> ctm_center -ctmCenter :: ShapeCTM u -> Point2 u-ctmCenter = ctm_center--ctmAngle :: ShapeCTM u -> Radian-ctmAngle = ctm_rotation+projectFromCtr :: (Real u, Floating u) => Vec2 u -> ShapeCTM u -> Anchor u+projectFromCtr v (ShapeCTM { ctm_center = ctr+ , ctm_scale_x = sx+ , ctm_scale_y = sy+ , ctm_rotation = theta }) = + let v1 = rotate theta $ scale sx sy $ v in ctr .+^ v1 -displaceCenter :: (Real u, Floating u) => Vec2 u -> ShapeCTM u -> Point2 u-displaceCenter v0 (ShapeCTM { ctm_center = ctr0- , ctm_scale_x = sx- , ctm_scale_y = sy- , ctm_rotation = theta }) = ctr .+^ v- where- ctr = rotate theta $ scale sx sy ctr0- v = rotateAbout theta ctr $ scale sx sy v0- -
src/Wumpus/Drawing/Shapes/Circle.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -25,7 +24,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Kernel -- package: wumpus-basic@@ -44,10 +43,13 @@ { circ_ctm :: ShapeCTM u , circ_radius :: !u }- ++type instance DUnit (Circle u) = u + type DCircle = Circle Double -type instance DUnit (Circle u) = u+instance Functor Circle where+ fmap f (Circle ctm r) = Circle (fmap f ctm) (f r) --------------------------------------------------------------------------------@@ -56,32 +58,31 @@ mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Circle u -> Circle u mapCTM f = (\s i -> s { circ_ctm = f i }) <*> circ_ctm -instance Num u => Scale (Circle u) where- scale sx sy = mapCTM (scale sx sy) -instance Rotate (Circle u) where- rotate ang = mapCTM (rotate ang)+instance (Real u, Floating u) => Rotate (Circle u) where+ rotate ang = mapCTM (rotate ang) - instance (Real u, Floating u) => RotateAbout (Circle u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Circle u) where+ scale sx sy = mapCTM (scale sx sy) instance Num u => Translate (Circle u) where- translate dx dy = mapCTM (translate dx dy)+ translate dx dy = mapCTM (translate dx dy) -------------------------------------------------------------------------------- -- Anchors -runDisplaceCenter :: (Real u, Floating u) - => (u -> Vec2 u) -> Circle u -> Point2 u+runDisplaceCenter :: (Real u, Floating u)+ => (u -> Vec2 u) -> Circle u -> Anchor u runDisplaceCenter fn (Circle { circ_ctm = ctm , circ_radius = radius }) = - displaceCenter (fn radius) ctm-+ projectFromCtr (fn radius) ctm +-- Anchors look like they need ctx... instance (Real u, Floating u) => CenterAnchor (Circle u) where center = runDisplaceCenter $ \_ -> V2 0 0 @@ -112,13 +113,13 @@ -- | 'circle' : @ radius -> Shape @ ---circle :: (Real u, Floating u, FromPtSize u) - => u -> Shape u (Circle u)+circle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Shape Circle u circle radius = makeShape (mkCircle radius) (mkCirclePath radius) -mkCircle :: Num u => u -> LocThetaCF u (Circle u)+mkCircle :: InterpretUnit u => u -> LocThetaQuery u (Circle u) mkCircle radius = promoteR2 $ \ctr theta -> pure $ Circle { circ_ctm = makeShapeCTM ctr theta , circ_radius = radius @@ -127,10 +128,10 @@ -- Rotation (theta) can be ignored. ---mkCirclePath :: (Floating u, Ord u, FromPtSize u) - => u -> LocThetaCF u (Path u)+mkCirclePath :: (Floating u, Ord u, InterpretUnit u, Tolerance u)+ => u -> LocThetaQuery u (AbsPath u) mkCirclePath radius = promoteR2 $ \ctr _ -> - pure $ traceCurvePoints $ bezierCircle radius ctr + pure $ curvePath $ bezierCircle radius ctr
src/Wumpus/Drawing/Shapes/Diamond.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -26,7 +25,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Geometry.Base -- package: wumpus-basic@@ -52,10 +51,13 @@ , dia_hh :: !u } +type instance DUnit (Diamond u) = u+ type DDiamond = Diamond Double -type instance DUnit (Diamond u) = u +instance Functor Diamond where+ fmap f (Diamond ctm hw hh) = Diamond (fmap f ctm) (f hw) (f hh) -------------------------------------------------------------------------------- -- Affine trans@@ -63,21 +65,19 @@ mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Diamond u -> Diamond u mapCTM f = (\s i -> s { dia_ctm = f i }) <*> dia_ctm -instance Num u => Scale (Diamond u) where- scale sx sy = mapCTM (scale sx sy) -instance Rotate (Diamond u) where- rotate ang = mapCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Diamond u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Diamond u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Diamond u) where+ scale sx sy = mapCTM (scale sx sy) instance Num u => Translate (Diamond u) where- translate dx dy = mapCTM (translate dx dy)-+ translate dx dy = mapCTM (translate dx dy) --------------------------------------------------------------------------------@@ -86,12 +86,12 @@ -- | 'runDisplaceCenter' : @ ( half_width -- * half_height -> Vec ) * diamond -> Point @ ---runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> Vec2 u) -> Diamond u -> Point2 u+runDisplaceCenter :: (Real u, Floating u)+ => (u -> u -> Vec2 u) -> Diamond u -> Anchor u runDisplaceCenter fn (Diamond { dia_ctm = ctm , dia_hw = hw , dia_hh = hh }) = - displaceCenter (fn hw hh) ctm+ projectFromCtr (fn hw hh) ctm instance (Real u, Floating u) => CenterAnchor (Diamond u) where@@ -100,7 +100,8 @@ instance (Real u, Floating u) => ApexAnchor (Diamond u) where apex = runDisplaceCenter $ \_ hh -> V2 0 hh -instance (Real u, Floating u) => SideMidpointAnchor (Diamond u) where+instance (Real u, Floating u) => + SideMidpointAnchor (Diamond u) where sideMidpoint n a = step (n `mod` 4) where step 1 = midpoint (north a) (west a)@@ -115,7 +116,7 @@ east = runDisplaceCenter $ \hw _ -> V2 hw 0 west = runDisplaceCenter $ \hw _ -> V2 (-hw) 0 -instance (Real u, Floating u, Fractional u) => CardinalAnchor2 (Diamond u) where+instance (Real u, Floating u) => CardinalAnchor2 (Diamond u) where northeast x = midpoint (north x) (east x) southeast x = midpoint (south x) (east x) southwest x = midpoint (south x) (west x)@@ -123,9 +124,10 @@ -instance (Real u, Floating u) => RadialAnchor (Diamond u) where- radialAnchor ang = runDisplaceCenter $ \hw hh -> - diamondRadialVector hw hh ang+instance (Real u, Floating u) => + RadialAnchor (Diamond u) where+ radialAnchor ang = runDisplaceCenter $ \hw hh -> + diamondRadialVector hw hh ang @@ -137,21 +139,25 @@ -- -- Note - args might change to tull_width and full_height... ---diamond :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (Diamond u)-diamond hw hh = makeShape (mkDiamond hw hh) (mkDiamondPath hw hh)+diamond :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => u -> u -> Shape Diamond u+diamond hw hh = makeShape (mkDiamond hw hh) (mkDiamondPath 0 hw hh) -mkDiamond :: Num u => u -> u -> LocThetaCF u (Diamond u)+mkDiamond :: InterpretUnit u => u -> u -> LocThetaQuery u (Diamond u) mkDiamond hw hh = promoteR2 $ \ctr theta -> pure $ Diamond { dia_ctm = makeShapeCTM ctr theta , dia_hw = hw- , dia_hh = hh + , dia_hh = hh } -mkDiamondPath :: (Real u, Floating u, FromPtSize u) - => u -> u -> LocThetaCF u (Path u)-mkDiamondPath hw hh = promoteR2 $ \ctr theta -> - roundCornerShapePath $ map (rotateAbout theta ctr) - $ diamondCoordPath hw hh ctr+mkDiamondPath :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => u -> u -> u -> LocThetaQuery u (AbsPath u)+mkDiamondPath rnd hw hh = promoteR2 $ \ctr theta ->+ let ps = map (rotateAbout theta ctr) $ diamondCoordPath hw hh ctr+ in roundCornerShapePath rnd ps++++
src/Wumpus/Drawing/Shapes/Ellipse.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -28,7 +27,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Kernel -- package: wumpus-basic@@ -46,53 +45,64 @@ -- Ellipse + data Ellipse u = Ellipse- { ell_ctm :: ShapeCTM u + { ell_ctm :: ShapeCTM u , ell_rx :: !u , ell_ry :: !u } +type instance DUnit (Ellipse u) = u+ type DEllipse = Ellipse Double -type instance DUnit (Ellipse u) = u +instance Functor Ellipse where+ fmap f (Ellipse ctm rx ry) = Ellipse (fmap f ctm) (f rx) (f ry)++ -------------------------------------------------------------------------------- -- Affine trans -mapEllipseCTM :: (ShapeCTM u -> ShapeCTM u) -> Ellipse u -> Ellipse u-mapEllipseCTM f = (\s i -> s { ell_ctm = f i }) <*> ell_ctm--instance Num u => Scale (Ellipse u) where- scale sx sy = mapEllipseCTM (scale sx sy)+mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Ellipse u -> Ellipse u+mapCTM f = (\s i -> s { ell_ctm = f i }) <*> ell_ctm -instance Rotate (Ellipse u) where- rotate ang = mapEllipseCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Ellipse u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Ellipse u) where- rotateAbout ang pt = mapEllipseCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Ellipse u) where+ scale sx sy = mapCTM (scale sx sy) -instance Num u => Translate (Ellipse u) where- translate dx dy = mapEllipseCTM (translate dx dy)+instance InterpretUnit u => Translate (Ellipse u) where+ translate dx dy = mapCTM (translate dx dy) -------------------------------------------------------------------------------- -- Anchors -runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> Vec2 u) -> Ellipse u -> Point2 u+-- Note - this is monadic for Ellipse...++runDisplaceCenter :: (Real u, Floating u)+ => (u -> u -> Vec2 u) -> Ellipse u -> Anchor u runDisplaceCenter fn (Ellipse { ell_ctm = ctm- , ell_rx = rx- , ell_ry = ry }) = - displaceCenter (fn rx ry) ctm+ , ell_rx = rx+ , ell_ry = ry }) = + projectFromCtr (fn rx ry) ctm +-- NOTE - the Affine instances provided by Wumpus-Core for Point +-- and Vector may be contradictory for Wumpus-Basic.++ -- | x_radius is the unit length. ---scaleEll :: (Scale t, Fractional u, u ~ DUnit t) => u -> u -> t -> t-scaleEll rx ry = scale 1 (ry/rx) +scaleEll :: (Real u, Fractional u)+ => u -> u -> Vec2 u -> Vec2 u+scaleEll rx ry v = let rat = realToFrac (ry/rx) in scale 1 rat v instance (Real u, Floating u) => CenterAnchor (Ellipse u) where@@ -123,12 +133,12 @@ -- | 'ellipse' : @ x_radii * y_radii -> shape @ ---ellipse :: (Real u, Floating u, FromPtSize u, Ord u) - => u -> u -> Shape u (Ellipse u)+ellipse :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) + => u -> u -> Shape Ellipse u ellipse rx ry = makeShape (mkEllipse rx ry) (mkEllipsePath rx ry) -mkEllipse :: Num u => u -> u -> LocThetaCF u (Ellipse u)+mkEllipse :: InterpretUnit u => u -> u -> LocThetaQuery u (Ellipse u) mkEllipse rx ry = promoteR2 $ \ctr theta -> pure $ Ellipse { ell_ctm = makeShapeCTM ctr theta , ell_rx = rx@@ -136,9 +146,10 @@ } -mkEllipsePath :: (Real u, Floating u, FromPtSize u, Ord u) - => u -> u -> LocThetaCF u (Path u)+mkEllipsePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> LocThetaQuery u (AbsPath u) mkEllipsePath rx ry = promoteR2 $ \pt theta -> - pure $ traceCurvePoints $ map (rotateAbout theta pt) - $ bezierEllipse rx ry pt+ let xs = map (rotateAbout theta pt) $ bezierEllipse rx ry pt+ in return $ curvePath xs+
src/Wumpus/Drawing/Shapes/InvSemicircle.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -40,62 +39,68 @@ newtype InvSemicircle u = InvSemicircle { getInvSemicircle :: Semicircle u } +type instance DUnit (InvSemicircle u) = u type DInvSemicircle = InvSemicircle Double -type instance DUnit (InvSemicircle u) = u +instance Functor InvSemicircle where+ fmap f = InvSemicircle . fmap f . getInvSemicircle -------------------------------------------------------------------------------- -- Affine trans -mapSemicircle :: (Semicircle u -> Semicircle u) - -> InvSemicircle u - -> InvSemicircle u-mapSemicircle f = InvSemicircle . f . getInvSemicircle--instance Num u => Scale (InvSemicircle u) where- scale sx sy = mapSemicircle (scale sx sy)+mapInner :: (Semicircle u -> Semicircle u) + -> InvSemicircle u + -> InvSemicircle u+mapInner f = InvSemicircle . f . getInvSemicircle -instance Rotate (InvSemicircle u) where- rotate ang = mapSemicircle (rotate ang)- -+instance (Real u, Floating u) => Rotate (InvSemicircle u) where+ rotate ang = mapInner (rotate ang)+ instance (Real u, Floating u) => RotateAbout (InvSemicircle u) where- rotateAbout ang pt = mapSemicircle (rotateAbout ang pt)+ rotateAbout ang pt = mapInner (rotateAbout ang pt) +instance Fractional u => Scale (InvSemicircle u) where+ scale sx sy = mapInner (scale sx sy) -instance Num u => Translate (InvSemicircle u) where- translate dx dy = mapSemicircle (translate dx dy)+instance InterpretUnit u => Translate (InvSemicircle u) where+ translate dx dy = mapInner (translate dx dy) + -------------------------------------------------------------------------------- -- Anchors runRotateAnchor :: (Real u, Floating u) - => (Semicircle u -> Point2 u) -> InvSemicircle u -> Point2 u-runRotateAnchor f (InvSemicircle a) = rotateAbout pi (center a) (f a)+ => (Semicircle u -> Anchor u) -> InvSemicircle u -> Anchor u+runRotateAnchor f (InvSemicircle a) = + let ctr = center a in rotateAbout pi ctr (f a) -instance (Real u, Floating u) => CenterAnchor (InvSemicircle u) where+instance (Real u, Floating u) => + CenterAnchor (InvSemicircle u) where center = center . getInvSemicircle -instance (Real u, Floating u) => ApexAnchor (InvSemicircle u) where+instance (Real u, Floating u) => + ApexAnchor (InvSemicircle u) where apex = runRotateAnchor apex -instance (Real u, Floating u) => TopCornerAnchor (InvSemicircle u) where+instance (Real u, Floating u) => + TopCornerAnchor (InvSemicircle u) where topLeftCorner = runRotateAnchor bottomRightCorner topRightCorner = runRotateAnchor bottomLeftCorner -instance (Real u, Floating u) => CardinalAnchor (InvSemicircle u) where+instance (Real u, Floating u) => + CardinalAnchor (InvSemicircle u) where north = runRotateAnchor south south = runRotateAnchor north east = runRotateAnchor west west = runRotateAnchor east -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (InvSemicircle u) where northeast = runRotateAnchor southwest southeast = runRotateAnchor northwest@@ -104,7 +109,7 @@ -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => RadialAnchor (InvSemicircle u) where radialAnchor theta = runRotateAnchor (radialAnchor $ circularModulo $ pi+theta)@@ -115,7 +120,7 @@ -- | 'invsemicircle' : @ radius -> Shape @ ---invsemicircle :: (Real u, Floating u, FromPtSize u) - => u -> Shape u (InvSemicircle u)+invsemicircle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Shape InvSemicircle u invsemicircle radius = - fmap InvSemicircle $ updatePathAngle (+ pi) $ semicircle radius+ shapeMap InvSemicircle $ updatePathAngle (+ pi) $ semicircle radius
src/Wumpus/Drawing/Shapes/InvSemiellipse.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -40,56 +39,61 @@ newtype InvSemiellipse u = InvSemiellipse { getInvSemiellipse :: Semiellipse u } +type instance DUnit (InvSemiellipse u) = u type DInvSemiellipse = InvSemiellipse Double -type instance DUnit (InvSemiellipse u) = u +instance Functor InvSemiellipse where+ fmap f = InvSemiellipse . fmap f . getInvSemiellipse+ -------------------------------------------------------------------------------- -- Affine trans -mapSemiellipse :: (Semiellipse u -> Semiellipse u) - -> InvSemiellipse u - -> InvSemiellipse u-mapSemiellipse f = InvSemiellipse . f . getInvSemiellipse--instance Num u => Scale (InvSemiellipse u) where- scale sx sy = mapSemiellipse (scale sx sy)---instance Rotate (InvSemiellipse u) where- rotate ang = mapSemiellipse (rotate ang)- +mapInner :: (Semiellipse u -> Semiellipse u) + -> InvSemiellipse u + -> InvSemiellipse u+mapInner f = InvSemiellipse . f . getInvSemiellipse +instance (Real u, Floating u) => Rotate (InvSemiellipse u) where+ rotate ang = mapInner (rotate ang)+ instance (Real u, Floating u) => RotateAbout (InvSemiellipse u) where- rotateAbout ang pt = mapSemiellipse (rotateAbout ang pt)+ rotateAbout ang pt = mapInner (rotateAbout ang pt) +instance Fractional u => Scale (InvSemiellipse u) where+ scale sx sy = mapInner (scale sx sy) -instance Num u => Translate (InvSemiellipse u) where- translate dx dy = mapSemiellipse (translate dx dy)+instance InterpretUnit u => Translate (InvSemiellipse u) where+ translate dx dy = mapInner (translate dx dy) + -------------------------------------------------------------------------------- -- Anchors runRotateAnchor :: (Real u, Floating u) - => (Semiellipse u -> Point2 u) -> InvSemiellipse u -> Point2 u-runRotateAnchor f (InvSemiellipse a) = rotateAbout pi (center a) (f a)+ => (Semiellipse u -> Anchor u) -> InvSemiellipse u -> Anchor u+runRotateAnchor f (InvSemiellipse a) =+ let ctr = center a in rotateAbout pi ctr (f a) -instance (Real u, Floating u) => CenterAnchor (InvSemiellipse u) where++instance (Real u, Floating u, Tolerance u) => + CenterAnchor (InvSemiellipse u) where center = center . getInvSemiellipse -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => ApexAnchor (InvSemiellipse u) where apex = runRotateAnchor apex -instance (Real u, Floating u) => TopCornerAnchor (InvSemiellipse u) where+instance (Real u, Floating u, Tolerance u) => + TopCornerAnchor (InvSemiellipse u) where topLeftCorner = runRotateAnchor bottomRightCorner topRightCorner = runRotateAnchor bottomLeftCorner -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor (InvSemiellipse u) where north = runRotateAnchor south south = runRotateAnchor north@@ -97,7 +101,7 @@ west = runRotateAnchor east -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (InvSemiellipse u) where northeast = runRotateAnchor southwest southeast = runRotateAnchor northwest@@ -106,7 +110,7 @@ -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => RadialAnchor (InvSemiellipse u) where radialAnchor theta = runRotateAnchor (radialAnchor $ circularModulo $ pi+theta)@@ -117,7 +121,7 @@ -- | 'invsemiellipse' : @ rx * ry -> Shape @ ---invsemiellipse :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (InvSemiellipse u)+invsemiellipse :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Shape InvSemiellipse u invsemiellipse rx ry = - fmap InvSemiellipse $ updatePathAngle (+ pi) $ semiellipse rx ry+ shapeMap InvSemiellipse $ updatePathAngle (+ pi) $ semiellipse rx ry
src/Wumpus/Drawing/Shapes/InvTriangle.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -36,65 +35,65 @@ --- -- Datatype newtype InvTriangle u = InvTriangle { getInvTriangle :: Triangle u } +type instance DUnit (InvTriangle u) = u type DInvTriangle = InvTriangle Double -type instance DUnit (InvTriangle u) = u +instance Functor InvTriangle where+ fmap f = InvTriangle . fmap f . getInvTriangle + -------------------------------------------------------------------------------- -- Affine trans -mapTriangle :: (Triangle u -> Triangle u) -> InvTriangle u -> InvTriangle u-mapTriangle f = InvTriangle . f . getInvTriangle ---instance Num u => Scale (InvTriangle u) where- scale sx sy = mapTriangle (scale sx sy)---instance Rotate (InvTriangle u) where- rotate ang = mapTriangle (rotate ang)- +mapInner :: (Triangle u -> Triangle u) -> InvTriangle u -> InvTriangle u+mapInner f = InvTriangle . f . getInvTriangle +instance (Real u, Floating u) => Rotate (InvTriangle u) where+ rotate ang = mapInner (rotate ang)+ instance (Real u, Floating u) => RotateAbout (InvTriangle u) where- rotateAbout ang pt = mapTriangle (rotateAbout ang pt)+ rotateAbout ang pt = mapInner (rotateAbout ang pt) +instance Fractional u => Scale (InvTriangle u) where+ scale sx sy = mapInner (scale sx sy) -instance Num u => Translate (InvTriangle u) where- translate dx dy = mapTriangle (translate dx dy)+instance InterpretUnit u => Translate (InvTriangle u) where+ translate dx dy = mapInner (translate dx dy) -------------------------------------------------------------------------------- -- Anchors --- I think anchors should be rotated about the center by pi...+-- Anchors should be rotated about the center by pi... runRotateAnchor :: (Real u, Floating u) - => (Triangle u -> Point2 u) -> InvTriangle u -> Point2 u-runRotateAnchor f (InvTriangle a) = rotateAbout pi (center a) (f a)+ => (Triangle u -> Anchor u) -> InvTriangle u -> Anchor u+runRotateAnchor f (InvTriangle a) =+ let ctr = center a in rotateAbout pi ctr (f a) -instance (Real u, Floating u) => CenterAnchor (InvTriangle u) where+instance (Real u, Floating u) => + CenterAnchor (InvTriangle u) where center = center . getInvTriangle -- apex is same on InvTriangle as regular triangle -instance (Real u, Floating u) => ApexAnchor (InvTriangle u) where+instance (Real u, Floating u) => + ApexAnchor (InvTriangle u) where apex = runRotateAnchor apex -- Top corners are bottom corners of the wrapped triangle. ---instance (Real u, Floating u) => TopCornerAnchor (InvTriangle u) where+instance (Real u, Floating u) => + TopCornerAnchor (InvTriangle u) where topLeftCorner = runRotateAnchor bottomRightCorner topRightCorner = runRotateAnchor bottomLeftCorner @@ -102,26 +101,29 @@ -- Use established points on the InvTrangle - don\'t delegate to -- the base Triangle. ---instance (Real u, Floating u) => SideMidpointAnchor (InvTriangle u) where+instance (Real u, Floating u) => + SideMidpointAnchor (InvTriangle u) where sideMidpoint n a = step (n `mod` 3) where- step 1 = midpoint (topRightCorner a) (topLeftCorner a)- step 2 = midpoint (topLeftCorner a) (apex a)- step _ = midpoint (apex a) (topRightCorner a)+ step 1 = midpoint (topRightCorner a) (topLeftCorner a)+ step 2 = midpoint (topLeftCorner a) (apex a)+ step _ = midpoint (apex a) (topRightCorner a) -- east and west should be parallel to the centroid. -- -instance (Real u, Floating u) => CardinalAnchor (InvTriangle u) where+instance (Real u, Floating u) => + CardinalAnchor (InvTriangle u) where north = runRotateAnchor south south = runRotateAnchor north east = runRotateAnchor west west = runRotateAnchor east -instance (Real u, Floating u) => CardinalAnchor2 (InvTriangle u) where+instance (Real u, Floating u) => + CardinalAnchor2 (InvTriangle u) where northeast = runRotateAnchor southwest southeast = runRotateAnchor northwest southwest = runRotateAnchor northeast@@ -129,7 +131,8 @@ -instance (Real u, Floating u) => RadialAnchor (InvTriangle u) where+instance (Real u, Floating u) => + RadialAnchor (InvTriangle u) where radialAnchor theta = runRotateAnchor (radialAnchor $ circularModulo $ pi+theta) --------------------------------------------------------------------------------@@ -138,9 +141,10 @@ -- | 'invtriangle' : @ top_base_width * height -> Triangle @ -- ---invtriangle :: (Real u, Floating u, FromPtSize u)- => u -> u -> Shape u (InvTriangle u)-invtriangle bw h = fmap InvTriangle $ updatePathAngle (+ pi) $ triangle bw h+invtriangle :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => u -> u -> Shape InvTriangle u+invtriangle bw h = + shapeMap InvTriangle $ updatePathAngle (+ pi) $ triangle bw h
src/Wumpus/Drawing/Shapes/Parallelogram.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -28,7 +27,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Geometry.Base -- package: wumpus-basic@@ -57,6 +56,7 @@ , pll_syn_props :: SyntheticProps u } +type instance DUnit (Parallelogram u) = u -- | Note (center) is a line dropped from the center of the -- paralleogram.@@ -69,34 +69,39 @@ , pll_base_major :: u } +type instance DUnit (SyntheticProps u) = u + type DParallelogram = Parallelogram Double -type instance DUnit (Parallelogram u) = u +instance Functor Parallelogram where+ fmap f (Parallelogram ctm bw h lang props) = + Parallelogram (fmap f ctm) (f bw) (f h) lang (fmap f props) +instance Functor SyntheticProps where+ fmap f (SyntheticProps bmin bmaj) = SyntheticProps (f bmin) (f bmaj) + -------------------------------------------------------------------------------- -- Affine trans mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Parallelogram u -> Parallelogram u mapCTM f = (\s i -> s { pll_ctm = f i }) <*> pll_ctm -instance Num u => Scale (Parallelogram u) where- scale sx sy = mapCTM (scale sx sy) --instance Rotate (Parallelogram u) where- rotate ang = mapCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Parallelogram u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Parallelogram u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Parallelogram u) where+ scale sx sy = mapCTM (scale sx sy) -instance Num u => Translate (Parallelogram u) where- translate dx dy = mapCTM (translate dx dy)+instance InterpretUnit u => Translate (Parallelogram u) where+ translate dx dy = mapCTM (translate dx dy) -------------------------------------------------------------------------------- -- Anchors@@ -107,30 +112,34 @@ -- * base_major -> Vec ) * parallelogram -> Point @ -- runDisplaceCenter :: (Real u, Floating u)- => (u -> u -> u -> u -> Vec2 u) -> Parallelogram u -> Point2 u+ => (u -> u -> u -> u -> Vec2 u) -> Parallelogram u -> Anchor u runDisplaceCenter fn (Parallelogram { pll_ctm = ctm , pll_base_width = bw , pll_height = h , pll_syn_props = syn }) = - displaceCenter (fn (0.5 * bw) (0.5 * h) + projectFromCtr (fn (0.5 * bw) (0.5 * h) (pll_base_minor syn) (pll_base_major syn)) ctm -instance (Real u, Floating u) => CenterAnchor (Parallelogram u) where+instance (Real u, Floating u) => + CenterAnchor (Parallelogram u) where center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0 -- top anchors swap the base minor and major... ---instance (Real u, Floating u) => TopCornerAnchor (Parallelogram u) where+instance (Real u, Floating u) => + TopCornerAnchor (Parallelogram u) where topLeftCorner = runDisplaceCenter $ \_ hh _ bmaj -> V2 (-bmaj) hh topRightCorner = runDisplaceCenter $ \_ hh bmin _ -> V2 bmin hh -instance (Real u, Floating u) => BottomCornerAnchor (Parallelogram u) where+instance (Real u, Floating u) => + BottomCornerAnchor (Parallelogram u) where bottomLeftCorner = runDisplaceCenter $ \_ hh bmin _ -> V2 (-bmin) (-hh) bottomRightCorner = runDisplaceCenter $ \_ hh _ bmaj -> V2 bmaj (-hh) -instance (Real u, Floating u) => SideMidpointAnchor (Parallelogram u) where+instance (Real u, Floating u) => + SideMidpointAnchor (Parallelogram u) where sideMidpoint n a = step (n `mod` 4) where step 1 = midpoint (topRightCorner a) (topLeftCorner a)@@ -140,14 +149,15 @@ -instance (Real u, Floating u) => CardinalAnchor (Parallelogram u) where+instance (Real u, Floating u) => + CardinalAnchor (Parallelogram u) where north = runDisplaceCenter $ \_ hh _ _ -> V2 0 hh south = runDisplaceCenter $ \_ hh _ _ -> V2 0 (-hh) east = runDisplaceCenter $ \hw _ _ _ -> V2 hw 0 west = runDisplaceCenter $ \hw _ _ _ -> V2 (-hw) 0 -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Parallelogram u) where northeast = pllRadialAnchor (0.25*pi) southeast = pllRadialAnchor (1.75*pi)@@ -156,15 +166,15 @@ -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Parallelogram u) where radialAnchor = pllRadialAnchor -- TODO - update this to a quadrant function... ---pllRadialAnchor :: (Real u, Floating u, FromPtSize u) - => Radian -> Parallelogram u -> Point2 u+pllRadialAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => Radian -> Parallelogram u -> Anchor u pllRadialAnchor theta (Parallelogram { pll_ctm = ctm , pll_height = h , pll_syn_props = syn }) =@@ -172,8 +182,8 @@ where ps = pllPoints (pll_base_minor syn) (pll_base_major syn) h post = \ans -> case ans of - Nothing -> displaceCenter (V2 0 0) ctm- Just (P2 x y) -> displaceCenter (V2 x y) ctm+ Nothing -> projectFromCtr (V2 0 0) ctm+ Just (P2 x y) -> projectFromCtr (V2 x y) ctm --------------------------------------------------------------------------------@@ -183,20 +193,20 @@ -- | 'parallelogram' : @ width * height * bottom_left_ang -> Parallelogram @ -- ---parallelogram :: (Real u, Floating u, FromPtSize u) - => u -> u -> Radian -> Shape u (Parallelogram u)+parallelogram :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Radian -> Shape Parallelogram u parallelogram bw h lang = let props = synthesizeProps bw h lang in makeShape (mkParallelogram bw h lang props) - (mkParallelogramPath (pll_base_minor props) - (pll_base_major props) h)+ (mkParallelogramPath 0 (pll_base_minor props) + (pll_base_major props) h) -- | 'zparallelogram' : @ base_width * height -> Parallelogram @ -- ---zparallelogram :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (Parallelogram u)+zparallelogram :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Shape Parallelogram u zparallelogram bw h = parallelogram bw h ang where ang = d2r (60::Double)@@ -205,9 +215,9 @@ -------------------------------------------------------------------------------- -mkParallelogram :: (Real u, Fractional u) +mkParallelogram :: (Real u, Fractional u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> SyntheticProps u - -> LocThetaCF u (Parallelogram u)+ -> LocThetaQuery u (Parallelogram u) mkParallelogram bw h lang props = promoteR2 $ \ctr theta -> pure $ Parallelogram { pll_ctm = makeShapeCTM ctr theta , pll_base_width = bw@@ -236,11 +246,12 @@ -mkParallelogramPath :: (Real u, Floating u, FromPtSize u) - => u -> u -> u -> LocThetaCF u (Path u)-mkParallelogramPath bw_minor bw_major h = promoteR2 $ \ctr theta -> - roundCornerShapePath $ map (rotateAbout theta ctr) - $ pllPath bw_minor bw_major h ctr+mkParallelogramPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> u -> u -> LocThetaQuery u (AbsPath u)+mkParallelogramPath rnd bw_minor bw_major h = promoteR2 $ \ctr theta -> + let xs = pllPath bw_minor bw_major h ctr+ in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs + pllPath :: (Real u, Floating u)
src/Wumpus/Drawing/Shapes/Rectangle.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -28,7 +27,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Geometry.Paths -- package: wumpus-basic@@ -51,11 +50,13 @@ } deriving (Eq,Ord,Show) +type instance DUnit (Rectangle u) = u+ type DRectangle = Rectangle Double -type instance DUnit (Rectangle u) = u-+instance Functor Rectangle where+ fmap f (Rectangle ctm hw hh) = Rectangle (fmap f ctm) (f hw) (f hh) -------------------------------------------------------------------------------- -- Affine trans@@ -63,20 +64,19 @@ mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Rectangle u -> Rectangle u mapCTM f = (\s i -> s { rect_ctm = f i }) <*> rect_ctm -instance Num u => Scale (Rectangle u) where- scale sx sy = mapCTM (scale sx sy) -instance Rotate (Rectangle u) where- rotate ang = mapCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Rectangle u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Rectangle u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Rectangle u) where+ scale sx sy = mapCTM (scale sx sy) -instance Num u => Translate (Rectangle u) where- translate dx dy = mapCTM (translate dx dy)+instance InterpretUnit u => Translate (Rectangle u) where+ translate dx dy = mapCTM (translate dx dy) -------------------------------------------------------------------------------- -- Anchors@@ -87,25 +87,29 @@ -- * half_height -> Vec ) * rectangle -> Point @ -- runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> Vec2 u) -> Rectangle u -> Point2 u+ => (u -> u -> Vec2 u) -> Rectangle u -> Anchor u runDisplaceCenter fn (Rectangle { rect_ctm = ctm , rect_hw = hw , rect_hh = hh }) = - displaceCenter (fn hw hh) ctm+ projectFromCtr (fn hw hh) ctm -instance (Real u, Floating u) => CenterAnchor (Rectangle u) where+instance (Real u, Floating u) => + CenterAnchor (Rectangle u) where center = runDisplaceCenter $ \_ _ -> V2 0 0 -instance (Real u, Floating u) => TopCornerAnchor (Rectangle u) where+instance (Real u, Floating u) => + TopCornerAnchor (Rectangle u) where topLeftCorner = runDisplaceCenter $ \hw hh -> V2 (-hw) hh topRightCorner = runDisplaceCenter $ \hw hh -> V2 hw hh -instance (Real u, Floating u) => BottomCornerAnchor (Rectangle u) where+instance (Real u, Floating u) => + BottomCornerAnchor (Rectangle u) where bottomLeftCorner = runDisplaceCenter $ \hw hh -> V2 (-hw) (-hh) bottomRightCorner = runDisplaceCenter $ \hw hh -> V2 hw (-hh) -instance (Real u, Floating u) => SideMidpointAnchor (Rectangle u) where+instance (Real u, Floating u) => + SideMidpointAnchor (Rectangle u) where sideMidpoint n a = step (n `mod` 4) where step 1 = north a@@ -114,20 +118,23 @@ step _ = east a -instance (Real u, Floating u) => CardinalAnchor (Rectangle u) where+instance (Real u, Floating u) => + CardinalAnchor (Rectangle u) where north = runDisplaceCenter $ \_ hh -> V2 0 hh south = runDisplaceCenter $ \_ hh -> V2 0 (-hh) east = runDisplaceCenter $ \hw _ -> V2 hw 0 west = runDisplaceCenter $ \hw _ -> V2 (-hw) 0 -instance (Real u, Floating u) => CardinalAnchor2 (Rectangle u) where+instance (Real u, Floating u) => + CardinalAnchor2 (Rectangle u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi) southwest = radialAnchor (1.25*pi) northwest = radialAnchor (0.75*pi) -instance (Real u, Floating u) => RadialAnchor (Rectangle u) where+instance (Real u, Floating u) => + RadialAnchor (Rectangle u) where radialAnchor theta = runDisplaceCenter $ \hw hh -> rectRadialVector hw hh theta @@ -139,14 +146,13 @@ -- | 'rectangle' : @ width * height -> shape @ ---rectangle :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (Rectangle u)+rectangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Shape Rectangle u rectangle w h = - makeShape (mkRectangle (0.5*w) (0.5*h))- (mkRectPath (0.5*w) (0.5*h))+ makeShape (mkRectangle (0.5*w) (0.5*h)) (mkRectPath 0 (0.5*w) (0.5*h)) -mkRectangle :: Num u => u -> u -> LocThetaCF u (Rectangle u)+mkRectangle :: InterpretUnit u => u -> u -> LocThetaQuery u (Rectangle u) mkRectangle hw hh = promoteR2 $ \ctr theta -> pure $ Rectangle { rect_ctm = makeShapeCTM ctr theta , rect_hw = hw@@ -154,12 +160,12 @@ } -mkRectPath :: (Real u, Floating u, FromPtSize u) - => u -> u -> LocThetaCF u (Path u)-mkRectPath hw hh = promoteR2 $ \ctr theta -> +mkRectPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> u -> LocThetaQuery u (AbsPath u)+mkRectPath rnd hw hh = promoteR2 $ \ctr theta -> let btm_left = displace (-hw) (-hh) ctr- in roundCornerShapePath $ map (rotateAbout theta ctr)- $ rectangleCoordPath (2*hw) (2*hh) btm_left+ xs = rectangleCoordPath (2*hw) (2*hh) btm_left+ in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs
src/Wumpus/Drawing/Shapes/Semicircle.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -25,7 +24,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Geometry.Base -- package: wumpus-basic@@ -50,39 +49,45 @@ , sc_syn_props :: SyntheticProps u } -+type instance DUnit (Semicircle u) = u -- | rect_width is the width of the (greater) enclosing rectangle. data SyntheticProps u = SyntheticProps { sc_ctr_minor :: u , sc_ctr_major :: u }++type instance DUnit (SyntheticProps u) = u+ type DSemicircle = Semicircle Double -type instance DUnit (Semicircle u) = u +instance Functor Semicircle where+ fmap f (Semicircle ctm r props) = Semicircle (fmap f ctm) (f r) (fmap f props) +instance Functor SyntheticProps where+ fmap f (SyntheticProps cmin cmaj) = SyntheticProps (f cmin) (f cmaj)++ -------------------------------------------------------------------------------- -- Affine trans mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Semicircle u -> Semicircle u mapCTM f = (\s i -> s { sc_ctm = f i }) <*> sc_ctm -instance Num u => Scale (Semicircle u) where- scale sx sy = mapCTM (scale sx sy) --instance Rotate (Semicircle u) where- rotate ang = mapCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Semicircle u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Semicircle u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Semicircle u) where+ scale sx sy = mapCTM (scale sx sy) -instance Num u => Translate (Semicircle u) where- translate dx dy = mapCTM (translate dx dy)+instance InterpretUnit u => Translate (Semicircle u) where+ translate dx dy = mapCTM (translate dx dy) --------------------------------------------------------------------------------@@ -93,24 +98,28 @@ -- * height_major -> Vec ) * semicircle -> Point @ -- runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> u -> Vec2 u) -> Semicircle u -> Point2 u+ => (u -> u -> u -> Vec2 u) -> Semicircle u -> Anchor u runDisplaceCenter fn (Semicircle { sc_ctm = ctm , sc_radius = radius , sc_syn_props = syn }) = - displaceCenter (fn radius (sc_ctr_minor syn) (sc_ctr_major syn)) ctm+ projectFromCtr (fn radius (sc_ctr_minor syn) (sc_ctr_major syn)) ctm -instance (Real u, Floating u) => CenterAnchor (Semicircle u) where+instance (Real u, Floating u) => + CenterAnchor (Semicircle u) where center = runDisplaceCenter $ \_ _ _ -> V2 0 0 -instance (Real u, Floating u) => ApexAnchor (Semicircle u) where+instance (Real u, Floating u) => + ApexAnchor (Semicircle u) where apex = runDisplaceCenter $ \_ _ cmaj -> V2 0 cmaj -instance (Real u, Floating u) => BottomCornerAnchor (Semicircle u) where+instance (Real u, Floating u) => + BottomCornerAnchor (Semicircle u) where bottomLeftCorner = runDisplaceCenter $ \r hminor _ -> V2 (-r) (-hminor) bottomRightCorner = runDisplaceCenter $ \r hminor _ -> V2 r (-hminor) -instance (Real u, Floating u) => CardinalAnchor (Semicircle u) where+instance (Real u, Floating u) => + CardinalAnchor (Semicircle u) where north = apex south = runDisplaceCenter $ \_ cmin _ -> V2 0 (-cmin) east = runDisplaceCenter $ \r cmin _ -> let x = pyth r cmin in V2 x 0@@ -126,7 +135,7 @@ pow2 = (^ (2::Int)) -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Semicircle u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi)@@ -136,11 +145,13 @@ -instance (Real u, Floating u, FromPtSize u) => RadialAnchor (Semicircle u) where+instance (Real u, Floating u, Tolerance u) => + RadialAnchor (Semicircle u) where radialAnchor theta = runDisplaceCenter (scRadialVec theta) +-- helpers -scRadialVec :: (Real u, Floating u, Ord u, FromPtSize u)+scRadialVec :: (Real u, Floating u, Ord u, Tolerance u) => Radian -> u -> u -> u -> Vec2 u scRadialVec theta radius hminor _ = go theta where@@ -197,8 +208,8 @@ -- | 'semicircle' : @ radius -> Shape @ ---semicircle :: (Real u, Floating u, FromPtSize u) - => u -> Shape u (Semicircle u)+semicircle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Shape Semicircle u semicircle radius = let props = synthesizeProps radius in makeShape (mkSemicircle radius props) @@ -215,7 +226,8 @@ cmajor = radius - cminor -mkSemicircle :: Num u => u -> SyntheticProps u -> LocThetaCF u (Semicircle u)+mkSemicircle :: InterpretUnit u+ => u -> SyntheticProps u -> LocThetaQuery u (Semicircle u) mkSemicircle radius props = promoteR2 $ \ctr theta -> pure $ Semicircle { sc_ctm = makeShapeCTM ctr theta , sc_radius = radius@@ -227,9 +239,9 @@ -- TODO - need to check other shapes to see if the are deriving -- the center properly... ---mkSemicirclePath :: (Real u, Floating u, FromPtSize u) - => u -> u -> LocThetaCF u (Path u)+mkSemicirclePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> LocThetaQuery u (AbsPath u) mkSemicirclePath radius cminor = promoteR2 $ \pt theta -> let ctr = displacePerpendicular (-cminor) theta pt- in pure $ traceCurvePoints $ bezierArcPoints pi radius theta ctr + in pure $ curvePath $ bezierArcPoints pi radius theta ctr
src/Wumpus/Drawing/Shapes/Semiellipse.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -25,7 +24,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Geometry.Base -- package: wumpus-basic@@ -50,18 +49,24 @@ , se_syn_props :: SyntheticProps u } -+type instance DUnit (Semiellipse u) = u -- | rect_width is the width of the (greater) enclosing rectangle. data SyntheticProps u = SyntheticProps { se_ry_minor :: u , se_ry_major :: u }++type instance DUnit (SyntheticProps u) = u type DSemiellipse = Semiellipse Double -type instance DUnit (Semiellipse u) = u+instance Functor Semiellipse where+ fmap f (Semiellipse ctm rx ry props) = + Semiellipse (fmap f ctm) (f rx) (f ry) (fmap f props) +instance Functor SyntheticProps where+ fmap f (SyntheticProps rymin rymaj) = SyntheticProps (f rymin) (f rymaj) -------------------------------------------------------------------------------- -- Affine trans@@ -69,20 +74,18 @@ mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Semiellipse u -> Semiellipse u mapCTM f = (\s i -> s { se_ctm = f i }) <*> se_ctm -instance Num u => Scale (Semiellipse u) where- scale sx sy = mapCTM (scale sx sy) --instance Rotate (Semiellipse u) where- rotate ang = mapCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Semiellipse u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Semiellipse u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Semiellipse u) where+ scale sx sy = mapCTM (scale sx sy) -instance Num u => Translate (Semiellipse u) where- translate dx dy = mapCTM (translate dx dy)+instance InterpretUnit u => Translate (Semiellipse u) where+ translate dx dy = mapCTM (translate dx dy) --------------------------------------------------------------------------------@@ -95,36 +98,38 @@ -- * ry_major -> Vec ) * semiellipse -> Point @ -- runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> u -> u -> Vec2 u) -> Semiellipse u -> Point2 u+ => (u -> u -> u -> u -> Vec2 u) -> Semiellipse u -> Anchor u runDisplaceCenter fn (Semiellipse { se_ctm = ctm , se_rx = rx , se_ry = ry , se_syn_props = syn }) = - displaceCenter (fn rx ry (se_ry_minor syn) (se_ry_major syn)) ctm+ projectFromCtr (fn rx ry (se_ry_minor syn) (se_ry_major syn)) ctm -instance (Real u, Floating u) => CenterAnchor (Semiellipse u) where+instance (Real u, Floating u) => + CenterAnchor (Semiellipse u) where center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0 -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => ApexAnchor (Semiellipse u) where apex = runDisplaceCenter $ \_ _ _ ry_major -> V2 0 ry_major -instance (Real u, Floating u) => BottomCornerAnchor (Semiellipse u) where+instance (Real u, Floating u) => + BottomCornerAnchor (Semiellipse u) where bottomLeftCorner = runDisplaceCenter $ \rx _ ry_minor _ -> V2 (-rx) (-ry_minor) bottomRightCorner = runDisplaceCenter $ \rx _ ry_minor _ -> V2 rx (-ry_minor) -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Semiellipse u) where north = apex south = runDisplaceCenter $ \_ _ ry_minor _ -> V2 0 (-ry_minor) east = radialAnchor 0 west = radialAnchor pi -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Semiellipse u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi)@@ -133,11 +138,12 @@ -instance (Real u, Floating u, FromPtSize u) => RadialAnchor (Semiellipse u) where+instance (Real u, Floating u, Tolerance u) => + RadialAnchor (Semiellipse u) where radialAnchor theta = runDisplaceCenter (seRadialVec theta) -seRadialVec :: (Real u, Floating u, Ord u, FromPtSize u)+seRadialVec :: (Real u, Floating u, Ord u, Tolerance u) => Radian -> u -> u -> u -> u -> Vec2 u seRadialVec theta rx ry hminor _ = go theta where@@ -190,8 +196,8 @@ -- | 'semiellipse' : @ x_radius * y_radius -> Shape @ ---semiellipse :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (Semiellipse u)+semiellipse :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Shape Semiellipse u semiellipse rx ry = let props = synthesizeProps ry in makeShape (mkSemiellipse rx ry props) @@ -209,8 +215,7 @@ ry_major = ry - ry_minor -mkSemiellipse :: Num u - => u -> u -> SyntheticProps u -> LocThetaCF u (Semiellipse u)+mkSemiellipse :: u -> u -> SyntheticProps u -> LocThetaQuery u (Semiellipse u) mkSemiellipse rx ry props = promoteR2 $ \ctr theta -> pure $ Semiellipse { se_ctm = makeShapeCTM ctr theta , se_rx = rx@@ -219,12 +224,12 @@ } -mkSemiellipsePath :: (Real u, Floating u, FromPtSize u) - => u -> u -> u -> LocThetaCF u (Path u)+mkSemiellipsePath :: (Real u, Floating u, Tolerance u) + => u -> u -> u -> LocThetaQuery u (AbsPath u) mkSemiellipsePath rx ry cminor = promoteR2 $ \pt theta -> let ctr = displacePerpendicular (-cminor) theta pt- in pure $ traceCurvePoints $ map (rotateAbout theta ctr)- $ bezierSemiellipsePoints rx ry ctr+ xs = bezierSemiellipsePoints rx ry ctr+ in return $ curvePath $ map (rotateAbout theta ctr) xs bezierSemiellipsePoints :: Floating u
src/Wumpus/Drawing/Shapes/Trapezium.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -30,11 +29,10 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Intersection -- package: wumpus-basic-import Wumpus.Basic.Geometry.Paths+import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core@@ -60,11 +58,13 @@ , tz_base_r_ang :: Radian } +type instance DUnit (Trapezium u) = u type DTrapezium = Trapezium Double -type instance DUnit (Trapezium u) = u-+instance Functor Trapezium where+ fmap f (Trapezium ctm bw h lang rang) = + Trapezium (fmap f ctm) (f bw) (f h) lang rang -------------------------------------------------------------------------------- -- Affine trans@@ -72,20 +72,18 @@ mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Trapezium u -> Trapezium u mapCTM f = (\s i -> s { tz_ctm = f i }) <*> tz_ctm -instance Num u => Scale (Trapezium u) where- scale sx sy = mapCTM (scale sx sy) --instance Rotate (Trapezium u) where- rotate ang = mapCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Trapezium u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Trapezium u) where- rotateAbout ang pt = mapCTM (rotateAbout ang pt)+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) +instance Fractional u => Scale (Trapezium u) where+ scale sx sy = mapCTM (scale sx sy) -instance Num u => Translate (Trapezium u) where- translate dx dy = mapCTM (translate dx dy)+instance InterpretUnit u => Translate (Trapezium u) where+ translate dx dy = mapCTM (translate dx dy) --------------------------------------------------------------------------------@@ -98,25 +96,28 @@ -- runDisplaceCenter :: (Real u, Floating u) => (u -> u -> Radian -> Radian -> Vec2 u) - -> Trapezium u -> Point2 u+ -> Trapezium u -> Anchor u runDisplaceCenter fn (Trapezium { tz_ctm = ctm , tz_base_width = bw , tz_height = h , tz_base_l_ang = lang , tz_base_r_ang = rang }) =- displaceCenter (fn (0.5 * bw) (0.5 * h) lang rang) ctm+ projectFromCtr (fn (0.5 * bw) (0.5 * h) lang rang) ctm -instance (Real u, Floating u) => CenterAnchor (Trapezium u) where+instance (Real u, Floating u) => + CenterAnchor (Trapezium u) where center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0 -instance (Real u, Floating u) => BottomCornerAnchor (Trapezium u) where+instance (Real u, Floating u) => + BottomCornerAnchor (Trapezium u) where bottomLeftCorner = runDisplaceCenter $ \hbw hh _ _ -> V2 (-hbw) (-hh) bottomRightCorner = runDisplaceCenter $ \hbw hh _ _ -> V2 hbw (-hh) -instance (Real u, Floating u) => TopCornerAnchor (Trapezium u) where+instance (Real u, Floating u) => + TopCornerAnchor (Trapezium u) where topLeftCorner = runDisplaceCenter $ \hbw hh lang _ -> let vbase = V2 (-hbw) (-hh) vup = leftSideVec (2*hh) lang @@ -127,7 +128,7 @@ in vbase ^+^ vup -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => SideMidpointAnchor (Trapezium u) where sideMidpoint n a = step (n `mod` 4) where@@ -138,7 +139,7 @@ -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Trapezium u) where north = runDisplaceCenter $ \_ hh _ _ -> V2 0 hh south = runDisplaceCenter $ \_ hh _ _ -> V2 0 (-hh)@@ -146,7 +147,7 @@ west = tzRadialAnchor pi -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Trapezium u) where northeast = tzRadialAnchor (0.25*pi) southeast = tzRadialAnchor (1.75*pi)@@ -155,14 +156,14 @@ -instance (Real u, Floating u, FromPtSize u) => +instance (Real u, Floating u, Tolerance u) => RadialAnchor (Trapezium u) where radialAnchor = tzRadialAnchor -- TODO - update this to a quadrant function... ---tzRadialAnchor :: (Real u, Floating u, FromPtSize u) - => Radian -> Trapezium u -> Point2 u+tzRadialAnchor :: (Real u, Floating u, Tolerance u) + => Radian -> Trapezium u -> Anchor u tzRadialAnchor theta (Trapezium { tz_ctm = ctm , tz_base_width = bw , tz_height = h@@ -172,8 +173,8 @@ where ps = tzPoints bw h lang rang post = \ans -> case ans of - Nothing -> displaceCenter (V2 0 0) ctm- Just (P2 x y) -> displaceCenter (V2 x y) ctm+ Nothing -> projectFromCtr (V2 0 0) ctm+ Just (P2 x y) -> projectFromCtr (V2 x y) ctm --------------------------------------------------------------------------------@@ -184,17 +185,17 @@ -- bottom_right_ang -> Shape @ -- ---trapezium :: (Real u, Floating u, FromPtSize u) - => u -> u -> Radian -> Radian -> Shape u (Trapezium u)+trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Radian -> Radian -> Shape Trapezium u trapezium bw h lang rang = - makeShape (mkTrapezium bw h lang rang) (mkTrapeziumPath bw h lang rang)+ makeShape (mkTrapezium bw h lang rang) (mkTrapeziumPath 0 bw h lang rang) -- | 'ztrapezium' : @ base_width * height -> Trapezium @ -- ---ztrapezium :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (Trapezium u)+ztrapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Shape Trapezium u ztrapezium bw h = trapezium bw h ang ang where ang = d2r (60::Double)@@ -203,8 +204,8 @@ -------------------------------------------------------------------------------- -mkTrapezium :: (Real u, Fractional u) - => u -> u -> Radian -> Radian -> LocThetaCF u (Trapezium u)+mkTrapezium :: (Real u, Fractional u, InterpretUnit u) + => u -> u -> Radian -> Radian -> LocThetaQuery u (Trapezium u) mkTrapezium bw h lang rang = promoteR2 $ \ctr theta -> pure $ Trapezium { tz_ctm = makeShapeCTM ctr theta , tz_base_width = bw@@ -214,11 +215,12 @@ } -mkTrapeziumPath :: (Real u, Floating u, FromPtSize u) - => u -> u -> Radian -> Radian -> LocThetaCF u (Path u)-mkTrapeziumPath bw h lang rang = promoteR2 $ \ctr theta -> - roundCornerShapePath $ map (rotateAbout theta ctr) - $ tzPath bw h lang rang ctr+mkTrapeziumPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> u -> Radian -> Radian + -> LocThetaQuery u (AbsPath u)+mkTrapeziumPath rnd bw h lang rang = promoteR2 $ \ctr theta -> + let xs = tzPath bw h lang rang ctr + in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs tzPath :: (Real u, Floating u)
src/Wumpus/Drawing/Shapes/Triangle.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -25,7 +24,7 @@ ) where -import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base import Wumpus.Basic.Geometry.Base -- package: wumpus-basic@@ -47,10 +46,12 @@ -- data Triangle u = Triangle { tri_ctm :: ShapeCTM u- , tri_height :: !u , tri_base_width :: !u+ , tri_height :: !u , tri_syn_props :: SyntheticProps u }++type instance DUnit (Triangle u) = u data SyntheticProps u = SyntheticProps { tri_hmajor :: u @@ -59,34 +60,37 @@ , tri_apex_ang :: Radian } +type instance DUnit (SyntheticProps u) = u + type DTriangle = Triangle Double -type instance DUnit (Triangle u) = u+instance Functor Triangle where+ fmap f (Triangle ctm bw h props) = + Triangle (fmap f ctm) (f bw) (f h) (fmap f props) +instance Functor SyntheticProps where+ fmap f (SyntheticProps hmin hmaj ang1 ang2) = + SyntheticProps (f hmin) (f hmaj) ang1 ang2 -------------------------------------------------------------------------------- -- Affine trans -mapTriangleCTM :: (ShapeCTM u -> ShapeCTM u) - -> Triangle u -> Triangle u-mapTriangleCTM f = (\s i -> s { tri_ctm = f i }) <*> tri_ctm--instance Num u => Scale (Triangle u) where- scale sx sy = mapTriangleCTM (scale sx sy)+mapCTM :: (ShapeCTM u -> ShapeCTM u) -> Triangle u -> Triangle u+mapCTM f = (\s i -> s { tri_ctm = f i }) <*> tri_ctm -instance Rotate (Triangle u) where- rotate ang = mapTriangleCTM (rotate ang)- -+instance (Real u, Floating u) => Rotate (Triangle u) where+ rotate ang = mapCTM (rotate ang)+ instance (Real u, Floating u) => RotateAbout (Triangle u) where- rotateAbout ang pt = mapTriangleCTM (rotateAbout ang pt)-+ rotateAbout ang pt = mapCTM (rotateAbout ang pt) -instance Num u => Translate (Triangle u) where- translate dx dy = mapTriangleCTM (translate dx dy)+instance Fractional u => Scale (Triangle u) where+ scale sx sy = mapCTM (scale sx sy) +instance InterpretUnit u => Translate (Triangle u) where+ translate dx dy = mapCTM (translate dx dy) -------------------------------------------------------------------------------- -- Anchors@@ -97,11 +101,11 @@ -- * base_ang -> Vec ) * traingle -> Point @ -- runDisplaceCenter :: (Real u, Floating u)- => (u -> u -> u -> Radian -> Vec2 u) -> Triangle u -> Point2 u+ => (u -> u -> u -> Radian -> Vec2 u) -> Triangle u -> Anchor u runDisplaceCenter fn (Triangle { tri_ctm = ctm , tri_base_width = bw , tri_syn_props = syn }) = - displaceCenter (fn (0.5*bw) hminor hmajor base_ang) ctm+ projectFromCtr (fn (0.5*bw) hminor hmajor base_ang) ctm where hminor = tri_hminor syn hmajor = tri_hmajor syn@@ -109,15 +113,18 @@ -instance (Real u, Floating u) => CenterAnchor (Triangle u) where+instance (Real u, Floating u) => + CenterAnchor (Triangle u) where center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0 -instance (Real u, Floating u) => ApexAnchor (Triangle u) where+instance (Real u, Floating u) => + ApexAnchor (Triangle u) where apex = runDisplaceCenter $ \_ _ hmaj _ -> V2 0 hmaj -instance (Real u, Floating u) => BottomCornerAnchor (Triangle u) where+instance (Real u, Floating u) => + BottomCornerAnchor (Triangle u) where bottomLeftCorner = runDisplaceCenter $ \hbw hmin _ _ -> V2 (-hbw) (-hmin) bottomRightCorner = runDisplaceCenter $ \hbw hmin _ _ -> V2 hbw (-hmin) @@ -125,18 +132,20 @@ -- east and west should be parallel to the centroid. -- -instance (Real u, Floating u) => CardinalAnchor (Triangle u) where+instance (Real u, Floating u) => + CardinalAnchor (Triangle u) where north = runDisplaceCenter $ \_ _ hmaj _ -> V2 0 hmaj south = runDisplaceCenter $ \_ hmin _ _ -> V2 0 (-hmin) east = runDisplaceCenter $ \hbw hmin _ ang -> findEast hbw hmin ang west = runDisplaceCenter $ \hbw hmin _ ang -> findWest hbw hmin ang -instance (Real u, Floating u) => SideMidpointAnchor (Triangle u) where+instance (Real u, Floating u) => + SideMidpointAnchor (Triangle u) where sideMidpoint n a = step (n `mod` 3) where- step 1 = midpoint (apex a) (bottomLeftCorner a)- step 2 = midpoint (bottomLeftCorner a) (bottomRightCorner a)+ step 1 = midpoint (apex a) (bottomLeftCorner a)+ step 2 = midpoint (bottomLeftCorner a) (bottomRightCorner a) step _ = midpoint (bottomRightCorner a) (apex a) @@ -151,7 +160,8 @@ -instance (Real u, Floating u) => CardinalAnchor2 (Triangle u) where+instance (Real u, Floating u) => + CardinalAnchor2 (Triangle u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi) southwest = radialAnchor (1.25*pi)@@ -159,7 +169,8 @@ -instance (Real u, Floating u) => RadialAnchor (Triangle u) where+instance (Real u, Floating u) => + RadialAnchor (Triangle u) where radialAnchor theta = runDisplaceCenter $ \hbw hmin hmaj _ -> triangleRadialVector hbw hmin hmaj theta @@ -170,20 +181,20 @@ -- | 'triangle' : @ base_width * height -> Shape @ -- ---triangle :: (Real u, Floating u, FromPtSize u) - => u -> u -> Shape u (Triangle u)+triangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Shape Triangle u triangle bw h = let props = synthesizeProps bw h hminor = tri_hminor props hmajor = tri_hmajor props- in makeShape (mkTriangle bw h props) (mkTrianglePath bw hminor hmajor)+ in makeShape (mkTriangle bw h props) (mkTrianglePath 0 bw hminor hmajor) -mkTriangle :: (Real u, Fractional u) - => u -> u -> SyntheticProps u -> LocThetaCF u (Triangle u)+mkTriangle :: (Real u, Fractional u, InterpretUnit u) + => u -> u -> SyntheticProps u -> LocThetaQuery u (Triangle u) mkTriangle bw h props = promoteR2 $ \ctrd theta -> pure $ Triangle { tri_ctm = makeShapeCTM ctrd theta , tri_base_width = bw@@ -208,11 +219,12 @@ -mkTrianglePath :: (Real u, Floating u, FromPtSize u) - => u -> u -> u -> LocThetaCF u (Path u)-mkTrianglePath bw hminor hmajor = promoteR2 $ \ctr theta -> - roundCornerShapePath $ map (rotateAbout theta ctr) - $ trianglePath bw hminor hmajor ctr+mkTrianglePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> u -> u -> LocThetaQuery u (AbsPath u)+mkTrianglePath rnd bw hminor hmajor = promoteR2 $ \ctr theta -> + let xs = trianglePath bw hminor hmajor ctr+ in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs+ trianglePath :: (Real u, Floating u)
− src/Wumpus/Drawing/Text/Base.hs
@@ -1,166 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Text.Base--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC------ Helpers for working with measured / advance text.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Text.Base- ( -- advtext- , textVector- , charVector-- , multilineHeight- , textObjectPos- , borderedTextObjectPos-- , centerToBaseline- , centerSpinePoints-- ) where--import Wumpus.Drawing.Chains--import Wumpus.Basic.Kernel -- package: wumpus-basic--import Wumpus.Core -- package: wumpus-core-import Wumpus.Core.Text.GlyphIndices--import Data.VectorSpace -- package: vector-space--import Control.Applicative-import Data.Char-import qualified Data.Map as Map-import Data.Maybe ----- | Single line text, returning its advance vector.----advtext :: FromPtSize u => EscapedText -> AdvGraphic u-advtext esc = lift0R1 (textVector esc) >>= \v -> replaceAns v $ escapedline esc----- kernchar versions to do...---textVector :: FromPtSize u => EscapedText -> DrawingInfo (AdvanceVec u)-textVector esc = - cwLookupTable >>= \table -> - let cs = destrEscapedText id esc - in return $ foldr (\c v -> v ^+^ (charWidth table c)) (vec 0 0) cs- -charVector :: FromPtSize u => EscapedChar -> DrawingInfo (AdvanceVec u)-charVector ch = cwLookupTable >>= \table -> return $ charWidth table ch- ---- | This is outside the Drawing context as we don\'t want to get--- the @cwLookupTable@ for every char.----charWidth :: FromPtSize u - => CharWidthTable u -> EscapedChar -> AdvanceVec u-charWidth fn (CharLiteral c) = fn $ ord c-charWidth fn (CharEscInt i) = fn i-charWidth fn (CharEscName s) = fn ix- where- ix = fromMaybe (-1) $ Map.lookup s ps_glyph_indices-------------------------------------------------------------------------------------- Measurement and start points for multiline text----- | Height of multiline text is cap_height to descender for the --- first line, then baseline-to-baseline span for the remaining--- lines.----multilineHeight :: (Real u, Floating u, FromPtSize u) - => Int -> DrawingInfo u-multilineHeight line_count - | line_count < 1 = return 0- | line_count == 1 = glyphVerticalSpan- | otherwise = fn <$> glyphVerticalSpan <*> baselineSpacing- where- fn h1 bspan = let rest_spans = bspan * fromIntegral (line_count - 1)- in h1 + rest_spans------ | Height of multiline text is cap_height to descender for the --- first line, then baseline-to-baseline span for the remaining--- lines.--- --- The answer is in centerform, i.e.:------ > ObjectPos half_width half_width half_height half_height ----textObjectPos :: (Real u, Floating u, FromPtSize u) - => Int -> u -> DrawingInfo (ObjectPos u)-textObjectPos line_count w =- fmap (0.5*) (multilineHeight line_count) >>= \hh ->- let hw = 0.5 * w- in return $ ObjectPos hw hw hh hh ----- | Variant of 'textObjectPos' where the calculation includes--- margins around all four sides of the enclosing rectangle.------ Margin sizes are taken from the 'text_margin' field in the --- 'DrawingContext'.----borderedTextObjectPos :: (Real u, Floating u, FromPtSize u) - => Int -> u -> DrawingInfo (ObjectPos u)-borderedTextObjectPos line_count w =- multilineHeight line_count >>= \h ->- getTextMargin >>= \(xsep,ysep) -> - let hw = (2 * xsep) + (0.5 * w)- hh = (2 * ysep) + (0.5 * h)- in return $ ObjectPos hw hw hh hh ------ | Calculate the distance from the center of a one-line textbox --- to the baseline. Note the height of a textbox is @vspan@ which --- is cap_height + descender----centerToBaseline :: (Fractional u, FromPtSize u) => DrawingInfo u-centerToBaseline = - (\ch vspan -> ch - 0.5 * vspan) <$> glyphCapHeight <*> glyphVerticalSpan---- | All drawing is done on a spine that plots points from the --- first line of text. The spine is calculated from its center and--- has to account for the inclination.----centerSpinePoints :: Floating u - => Int -> Radian -> LocChain u-centerSpinePoints n theta- | n <= 1 = promoteR1 $ \ctr -> return [ctr]- | otherwise = promoteR1 $ \ctr -> - baselineSpacing >>= \h1 -> - let dist_top = h1 * centerCount n- top = thetaNorthwards dist_top theta ctr - in return (take n $ iterate (thetaSouthwards h1 theta) top)----- | Count the steps from the center to an end:------ >--- > 1 = 0 .--- > 2 = 0.5 .__.--- > 3 = 1 .__.__.--- > 4 = 1.5 .__.__.__.--- >----centerCount :: Fractional u => Int -> u-centerCount i = (fromIntegral i) / 2 - 0.5
+ src/Wumpus/Drawing/Text/Base/Common.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Text.Base.Common+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Helpers for working with measured / advance text.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.Base.Common+ ( + posTextWithMargins+ , advtext+ , textVector+ , textOrientationZero++ , charVector+ , charOrientationZero+ , hkernVector+ , hkernOrientationZero++ ) where+++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Text.GlyphIndices++import Data.VectorSpace -- package: vector-space++import Control.Applicative+import Data.Char+import qualified Data.Map as Map+import Data.Maybe ++++posTextWithMargins :: (Fractional u, InterpretUnit u) + => PosObject u -> BoundedLocRectGraphic u+posTextWithMargins obj = + textMargin >>= \(xsep,ysep) -> + let body = extendPosObject xsep xsep ysep ysep obj+ in runPosObjectR2 body+++-- | Single line text, returning its advance vector.+--+advtext :: InterpretUnit u => EscapedText -> AdvGraphic u+advtext esc = textVector esc >>= body+ where+ body v = pushR1 (replaceAns v) $ escTextLine esc+++textVector :: (DrawingCtxM m, InterpretUnit u) + => EscapedText -> m (AdvanceVec u)+textVector esc = + cwLookupTable >>= \table -> + pointSize >>= \sz -> + let cs = destrEscapedText id esc + in return $ foldr (step sz table) (vec 0 0) cs+ where+ step sz table ch v = (v ^+^) $ charWidth sz table ch++charVector :: (DrawingCtxM m, InterpretUnit u) + => EscapedChar -> m (AdvanceVec u)+charVector ch = + (\table sz -> charWidth sz table ch) <$> cwLookupTable <*> pointSize++-- | Build the Orientation of a single line of EscapedText.+-- +-- The locus of the Orientation is baseline left - margins are +-- added.+--+textOrientationZero :: (DrawingCtxM m, InterpretUnit u )+ => EscapedText -> m (Orientation u)+textOrientationZero esc = textVector esc >>= bllOrientationZero++-- | Build the Orientation of an EscapedChar.+-- +-- The locus of the Orientation is baseline left - margins are +-- added.+--+charOrientationZero :: (DrawingCtxM m, InterpretUnit u)+ => EscapedChar -> m (Orientation u)+charOrientationZero ch = charVector ch >>= bllOrientationZero ++++-- NOTE - TextMargin should probably be added as a final step+-- not during construction...++bllOrientationZero :: (DrawingCtxM m, InterpretUnit u )+ => AdvanceVec u -> m (Orientation u)+bllOrientationZero (V2 w _) = + (\ymin ymaj -> Orientation 0 w ymin ymaj) + <$> fmap abs descender <*> capHeight+++ +-- | 'hkernVector' : @ [kerning_char] -> AdvanceVec @+-- +-- 'hkernvector' takes whatever length is paired with the +-- EscapedChar for the init of the the list, for the last element +-- it takes the charVector.+--+hkernVector :: (DrawingCtxM m, InterpretUnit u) + => [KernChar u] -> m (AdvanceVec u)+hkernVector = go 0+ where+ go w [] = return $ V2 w 0+ go w [(dx,ch)] = fmap (addWidth $ w + dx) (charVector ch)+ go w ((dx,_ ):xs) = go (w + dx) xs+ + addWidth w (V2 x y) = V2 (w+x) y++ -- ERROR this not the right way to count...+ ++hkernOrientationZero :: (DrawingCtxM m, InterpretUnit u )+ => [KernChar u] -> m (Orientation u)+hkernOrientationZero xs = hkernVector xs >>= bllOrientationZero+ +-- | This is outside the Drawing context as we don\'t want to get+-- the @cwLookupTable@ for every char.+--+charWidth :: InterpretUnit u + => FontSize -> CharWidthLookup -> EscapedChar -> AdvanceVec u+charWidth sz fn (CharLiteral c) = fmap (dinterp sz) $ fn $ ord c+charWidth sz fn (CharEscInt i) = fmap (dinterp sz) $ fn i+charWidth sz fn (CharEscName s) = fmap (dinterp sz) $ fn ix+ where+ ix = fromMaybe (-1) $ Map.lookup s ps_glyph_indices+
+ src/Wumpus/Drawing/Text/Base/DocTextZero.hs view
@@ -0,0 +1,453 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Text.Base.DocTextZero+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Flexible text type, composable with @pretty-print@ style +-- operators.+-- +-- Direction zero (left-to-right) only.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.Base.DocTextZero+ ( ++ Doc + , TextFrame+ , render ++ , leftAlign+ , centerAlign+ , rightAlign++ , blank+ , space+ , string+ , escaped+ , int+ , integer+ , float+ , ffloat++ , (<>)+ , (<+>) + , vcatl+ , vcatc + , vcatr++ , lfill+ , rfill+ , centerfill++ , fontColour+ , textSize+ , bold+ , italic+ , boldItalic + , strikethrough+ , underline+ , highlight++ ) where++import Wumpus.Drawing.Text.Base.Common++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++import Control.Applicative+import Data.Char ( ord )+import Numeric+++-- | Space is the width of a space in the current font - it is +-- filled in during interpretation.+--+data Doc u = Empty+ | Space + | Text EscapedText+ | Cat (Doc u) (Doc u)+ | VCat VAlign (Doc u) (Doc u)+ | Fill VAlign u (Doc u)+ | DLocal DrawingContextF (Doc u)+ | TLocal (TextContextF u) (Doc u)+ | Mono (WidthQuery u) [EscapedChar]+ | AElab (AElaborateF u) (Doc u)++type WidthQuery u = Query (AdvanceVec u)++type TextContextF u = TextContext u -> TextContext u++type AElaborateF u = Orientation u -> LocGraphic u++++-- | TextFrame is the result Graphic made from rendering multiple+-- lines of DocText.+--+type TextFrame u = BoundedLocRectGraphic u+++-- NOTE - should the API use @em@ for fill, padding etc.?++blank :: Doc u+blank = Empty++space :: Doc u+space = Space++string :: String -> Doc u+string = Text . escapeString++escaped :: EscapedText -> Doc u+escaped = Text++++int :: InterpretUnit u => Int -> Doc u+int i = integer $ fromIntegral i+++integer :: InterpretUnit u => Integer -> Doc u+integer i = Mono (charVector $ CharLiteral '0') (map CharLiteral $ show i)++-- | Specialized version of 'ffloat' - the answer is always +-- rendered at \"full precision\".+--+float :: (RealFloat a, InterpretUnit u) => a -> Doc u+float = ffloat Nothing+++-- | This is equivalent to 'showFFloat' in the Numeric module.+-- +-- Like 'showFFloat', the answer is rendered to supplied +-- precision. @Nothing@ indicated full precision.+--+ffloat :: (RealFloat a, InterpretUnit u) => (Maybe Int) -> a -> Doc u+ffloat mb d = Mono (charVector $ CharLiteral '0') xs+ where+ xs = (map CharLiteral $ ($ []) $ showFFloat mb d)+++++infixr 6 <>, <+>+++-- | Concatenate two DocTexts separated with no spacing.+--+-- (infixr 6)+--+(<>) :: Doc u -> Doc u -> Doc u+a <> b = Cat a b+ ++-- | Concatenate two Docs separated with a space.+--+-- (infixr 6)+--+(<+>) :: Doc u -> Doc u -> Doc u+a <+> b = a <> space <> b ++infixr 5 `vcatl`, `vcatc`, `vcatr`++-- | Vertically concatenate - aligning left.+-- +-- (infixr 5) +--+vcatl :: Doc u -> Doc u -> Doc u+vcatl = VCat VLeft++-- | Vertically concatenate - aligning center.+-- +-- (infixr 5) +--+vcatc :: Doc u -> Doc u -> Doc u+vcatc = VCat VCenter++-- | Vertically concatenate - aligning right.+-- +-- (infixr 5) +--+vcatr :: Doc u -> Doc u -> Doc u+vcatr = VCat VRight++leftAlign :: [Doc u] -> Doc u+leftAlign = multiline vcatl++centerAlign :: [Doc u] -> Doc u+centerAlign = multiline vcatc++rightAlign :: [Doc u] -> Doc u+rightAlign = multiline vcatr+++multiline :: (Doc u -> Doc u -> Doc u) -> [Doc u] -> Doc u+multiline _ [] = blank +multiline op (x:xs) = go x xs+ where+ go a [] = a+ go a (b:bs) = go (a `op` b) bs+++++rfill :: u -> Doc u -> Doc u+rfill = Fill VLeft++lfill :: u -> Doc u -> Doc u+lfill = Fill VRight+++centerfill :: u -> Doc u -> Doc u+centerfill = Fill VCenter++++fontColour :: RGBi -> Doc u -> Doc u+fontColour rgb = DLocal (text_colour rgb)++++textSize :: Int -> Doc u -> Doc u+textSize sz = DLocal (set_font_size sz)++++bold :: Doc u -> Doc u+bold = TLocal (\s -> s { text_bold = True, text_italic = False })++italic :: Doc u -> Doc u+italic = TLocal (\s -> s { text_bold = False, text_italic = True })++boldItalic :: Doc u -> Doc u+boldItalic = TLocal (\s -> s { text_bold = True, text_italic = True })+++strikethrough :: Doc u -> Doc u+strikethrough = TLocal (\s -> s { text_strikethrough = True })++underline :: Doc u -> Doc u+underline = TLocal (\s -> s { text_underline = True })++-- | Background fill.+--+highlight :: (Fractional u, InterpretUnit u) + => RGBi -> Doc u -> Doc u+highlight rgb = AElab (drawBackfill rgb)++++render :: (Real u, Floating u, InterpretUnit u) + => FontFamily -> Doc u -> BoundedLocRectGraphic u +render ff doc = localize (set_font $ regularWeight ff) $+ textlineSpace >>= \sep -> + posTextWithMargins $ runEvalM (initTextCtx sep ff) (interpret doc) +++data TextContext u = TextContext+ { text_strikethrough :: Bool+ , text_underline :: Bool+ , text_sep :: u+ , text_font_family :: FontFamily+ , text_bold :: Bool+ , text_italic :: Bool+ }+ +++initTextCtx :: u -> FontFamily -> TextContext u+initTextCtx sep ff = TextContext + { text_strikethrough = False+ , text_underline = False+ , text_sep = sep+ , text_font_family = ff+ , text_bold = False+ , text_italic = False + }++newtype EvalM u a = EvalM { getEvalM :: TextContext u -> a }+++instance Functor (EvalM u) where+ fmap f mf = EvalM $ \ctx -> f $ getEvalM mf ctx+++instance Applicative (EvalM u) where+ pure a = EvalM $ \_ -> a+ mf <*> ma = EvalM $ \ctx -> + let f = getEvalM mf ctx+ a = getEvalM ma ctx+ in f a++instance Monad (EvalM u) where+ return a = EvalM $ \_ -> a+ ma >>= k = EvalM $ \ctx -> + let a = getEvalM ma ctx+ in (getEvalM . k) a ctx++asks :: (TextContext u -> a) -> EvalM u a+asks f = EvalM $ \ctx -> f ctx++lineSpace :: EvalM u u+lineSpace = asks text_sep++local :: (TextContext u -> TextContext u) -> EvalM u a -> EvalM u a+local upd mf = EvalM $ \ctx -> getEvalM mf (upd ctx)++runEvalM :: TextContext u -> EvalM u a -> a+runEvalM ctx mf = getEvalM mf ctx++++interpret :: (Fractional u, Ord u, InterpretUnit u) + => Doc u -> EvalM u (PosObject u)+interpret Empty = interpEmpty+interpret Space = interpSpace+interpret (Text esc) = interpText esc+interpret (Cat a b) = hconcat <$> interpret a <*> interpret b+interpret (VCat va a b) = + valignSpace va <$> lineSpace <*> interpret a <*> interpret b++interpret (Fill va w a) = ppad va w <$> interpret a+interpret (DLocal upd a) = localizePO upd <$> interpret a+interpret (TLocal upd a) = local upd (interpret a)+interpret (Mono q1 xs) = interpMono q1 xs+interpret (AElab fn a) = aelaboratePO fn <$> interpret a+++++interpEmpty :: InterpretUnit u => EvalM u (PosObject u)+interpEmpty = return $ makePosObject (pure $ Orientation 0 0 0 0) emptyLocGraphic++++-- | Note - the current way of seeding the LocGraphic with the +-- DrawingContext looks dodgy (substantial copying). +-- +-- Maybe EvalM should have a private, much smaller +-- DrawingContext...+--+interpText :: (Fractional u, InterpretUnit u) + => EscapedText -> EvalM u (PosObject u)+interpText esc = interpretLeaf $+ makePosObject (textOrientationZero esc) (escTextLine esc)+ ++++-- | Note - a space character is not draw in the output, instead +-- 'space' advances the width vector by the width of a space in +-- the current font.+--+interpSpace :: InterpretUnit u + => EvalM u (PosObject u)+interpSpace = return $ makePosObject qy1 emptyLocGraphic+ where+ qy1 = charOrientationZero $ CharEscInt $ ord ' '+++ppad :: (Fractional u, Ord u) + => VAlign -> u -> PosObject u -> PosObject u+ppad VLeft = padLeftPO+ppad VCenter = padHorizontalPO+ppad VRight = padRightPO+++interpMono :: (Fractional u, InterpretUnit u)+ => Query (AdvanceVec u) -> [EscapedChar] + -> EvalM u (PosObject u)+interpMono qy1 chs = interpretLeaf $+ makeBindPosObject qy hkernOrientationZero hkernLine+ where+ qy = (\v1 -> monoSpace (advanceH v1) chs ) <$> qy1 +++++interpretLeaf :: (Fractional u, InterpretUnit u)+ => PosObject u -> EvalM u (PosObject u)+interpretLeaf po = + (\f1 f2 sty -> f1 $ f2 $ localizePO sty po) + <$> (fmap (condE drawUnderline) $ asks text_underline)+ <*> (fmap (condE drawStrikethrough) $ asks text_strikethrough)+ <*> textstyle+ where+ condE f b = if b then elaboratePO f else id++textstyle :: EvalM u DrawingContextF+textstyle = + fn <$> asks text_font_family <*> asks text_bold <*> asks text_italic+ where+ fn ff False False = set_font $ regularWeight ff+ fn ff True False = set_font $ boldWeight ff+ fn ff False True = set_font $ italicWeight ff+ fn ff _ _ = set_font $ boldItalicWeight ff++--------------------------------------------------------------------------------+-- Helpers+++monoSpace :: Num u => u -> [EscapedChar] -> [KernChar u]+monoSpace w1 (c:cs) = (0,c) : map (\ch -> (w1,ch)) cs+monoSpace _ [] = []++ ++-- API might be simple if we conditionally apply strikethrough on +-- interpText (possibly including spaces), but never on interpSpace.+--+-- Might want to derive stroke_colour from text_colour and linewidth+-- fromf font size as well...+--+drawStrikethrough :: (Fractional u, InterpretUnit u) + => Orientation u -> LocGraphic u+drawStrikethrough (Orientation xmin xmaj _ ymaj) = + linestyle $ moveStart (displaceVec $ vec (-xmin) vpos) hline + where+ vpos = 0.45 * ymaj+ hline = locStraightLine (hvec $ xmin + xmaj)++++drawUnderline :: (Fractional u, InterpretUnit u) + => Orientation u -> LocGraphic u+drawUnderline (Orientation xmin xmaj ymin _) = + linestyle $ moveStart (displaceVec $ vec (-xmin) vpos) hline + where+ vpos = negate $ 0.45 * ymin+ hline = locStraightLine (hvec $ xmin + xmaj)++linestyle :: LocGraphic u -> LocGraphic u+linestyle mf = + pointSize >>= \sz -> + localize (stroke_use_text_colour . set_line_width (lim sz)) mf+ where+ lim i | i < 10 = 1.0+ | otherwise = (fromIntegral i) / 15.0 +++-- | Note - halving the TextMargin looks good.+--+drawBackfill :: (Fractional u, InterpretUnit u) + => RGBi -> Orientation u -> LocGraphic u+drawBackfill rgb (Orientation xmin xmaj ymin ymaj) = + textMargin >>= \(dx,dy) -> + let hdx = 0.5 * dx+ hdy = 0.5 * dy + in localize (fill_colour rgb) $ moveStart (mkVec hdx hdy) (mkRect hdx hdy)+ where+ mkVec dx dy = displaceVec $ vec (negate $ xmin+dx) (negate $ ymin+dy)+ mkRect dx dy = let w = dx + xmin + xmaj + dx+ h = dy + ymin + ymaj + dy+ in filledRectangle w h
+ src/Wumpus/Drawing/Text/Base/Label.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Text.Base.Label+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Annotation labels.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.Base.Label+ ( ++ locImageLabel+ , label_center_of+ , label_left_of+ , label_right_of+ , label_above+ , label_below++ , connectorPathLabel+ , label_midway_of+ , label_atstart_of+ , label_atend_of++ ) where+++import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++++++locImageLabel :: Floating u + => (a -> Anchor u) -> RectAddress + -> BoundedLocRectGraphic u -> LocImage u a -> LocImage u a+locImageLabel fn rpos lbl obj = promoteR1 $ \pt -> + elaborateR0 (obj `at` pt) (\a -> graphic_ $ atStartAddr lbl (fn a) rpos)+++label_center_of :: (Floating u, CenterAnchor a, u ~ DUnit a) + => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a+label_center_of = locImageLabel center CENTER+++label_left_of :: (Floating u, CardinalAnchor a, u ~ DUnit a) + => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a+label_left_of = locImageLabel west EE++label_right_of :: (Floating u, CardinalAnchor a, u ~ DUnit a) + => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a+label_right_of = locImageLabel east WW+++label_above :: (Floating u, CardinalAnchor a, u ~ DUnit a) + => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a+label_above = locImageLabel north SS+++label_below :: (Floating u, CardinalAnchor a, u ~ DUnit a) + => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a+label_below = locImageLabel south NN+++++connectorPathLabel :: Floating u + => (AbsPath u -> Point2 u) + -> RectAddress+ -> BoundedLocRectGraphic u+ -> Image u (AbsPath u) + -> Image u (AbsPath u)+connectorPathLabel fn rpos lbl img = + elaborateR0 img (\a -> graphic_ $ atStartAddr lbl (fn a) rpos)+++label_midway_of :: (Real u, Floating u) + => RectAddress + -> BoundedLocRectGraphic u + -> Image u (AbsPath u) -> Image u (AbsPath u)+label_midway_of = connectorPathLabel midway_+++label_atstart_of :: (Real u, Floating u) + => RectAddress + -> BoundedLocRectGraphic u + -> Image u (AbsPath u) -> Image u (AbsPath u)+label_atstart_of = connectorPathLabel atstart_+++label_atend_of :: (Real u, Floating u) + => RectAddress + -> BoundedLocRectGraphic u+ -> Image u (AbsPath u) -> Image u (AbsPath u)+label_atend_of = connectorPathLabel atend_++++-- TikZ has label=below etc.+-- +-- This would probably translate to a functions:+-- @labelBelow@+--+++-- Design note - there aren\'t many Images that support anchors,+-- except for LocImages that have been /saturated/ (i.e. applied +-- to a point with @at@).+-- +-- For a saturated Image, getting at the anchors via bind does +-- not seem so bad (indeed, this was the original point of +-- anchors). Obviously it is important to add labels to LocImages+-- (the original point of the label functions) but what about +-- LocThetaImages and LocRectImages. Is it acceptable to /saturate/+-- them to LocImages before labelling them?+-- +-- Connectors support different /anchor-like/ positions so they +-- will different labelling functions.+-- + +
+ src/Wumpus/Drawing/Text/Base/PosChar.hs view
@@ -0,0 +1,73 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Text.Base.PosChar+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Drawing single a char as a PosImage.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.Base.PosChar+ ( + LocRectChar++ , posChar+ , posEscChar++ , charLabel+ , escCharLabel++ ) where++import Wumpus.Drawing.Text.Base.Common++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core+++type PosChar u = PosObject u++posChar :: InterpretUnit u => Char -> PosChar u+posChar = makePosChar . CharLiteral++posEscChar :: InterpretUnit u => EscapedChar -> PosChar u+posEscChar = makePosChar++++-- Note this type doesn\'t support concat...+-- +-- While it may be adequate, it does need another prefix.+--+type LocRectChar u = BoundedLocRectGraphic u+++++charLabel :: (Floating u, InterpretUnit u) => Char -> LocRectChar u+charLabel ch = escCharLabel $ CharLiteral ch+++escCharLabel :: (Floating u, InterpretUnit u) + => EscapedChar -> LocRectChar u+escCharLabel esc = runPosObjectR2 (makePosChar esc) +++makePosChar :: InterpretUnit u + => EscapedChar -> PosObject u+makePosChar esc = makePosObject (charOrientationZero esc) (escText1 esc)+++escText1 :: InterpretUnit u => EscapedChar -> LocGraphic u+escText1 ch = escTextLine $ wrapEscChar ch+++
+ src/Wumpus/Drawing/Text/Base/RotTextZero.hs view
@@ -0,0 +1,375 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Text.Base.RotTextZero+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Direction zero (left-to-right) measured text that supports +-- radial inclination. Caveat - rendering at any inclination other +-- than the horizontal may not look good in PostScript or SVG.+--+-- \*\* WARNING \*\* - the API for this module needs some polish.+--+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.Base.RotTextZero+ ( + LocRectTextLine+ , LocTextLine+ , TextObject++ , textline+ , bllTextline+ , blcTextline+ , ccTextline++ , multiAlignLeft+ , multiAlignCenter+ , multiAlignRight++ , rtextline+ , rescTextline++ ) where++import Wumpus.Drawing.Text.Base.Common++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++import Control.Applicative++type LocRectTextLine u = BoundedLocRectGraphic u+type LocTextLine u = BoundedLocGraphic u++type TextObject u = PosObject u++++-- | Draw a single line of text.+--+textline :: (Fractional u, InterpretUnit u) + => String -> LocRectTextLine u+textline ss = posTextWithMargins (makeTextObject ss)+++bllTextline :: (Floating u, InterpretUnit u) + => String -> LocTextLine u+bllTextline ss = startAddr (textline ss) BLL+++blcTextline :: (Floating u, InterpretUnit u) + => String -> LocTextLine u+blcTextline ss = startAddr (textline ss) BLC++ccTextline :: (Floating u, InterpretUnit u) + => String -> LocTextLine u+ccTextline ss = startAddr (textline ss) CENTER+++multiAlignLeft :: (Real u, Floating u, InterpretUnit u) + => String -> LocRectTextLine u+multiAlignLeft ss = + renderMultiLine VLeft (map makeTextObject $ lines ss)++multiAlignCenter :: (Real u, Floating u, InterpretUnit u) + => String -> LocRectTextLine u+multiAlignCenter ss = + renderMultiLine VCenter (map makeTextObject $ lines ss)++multiAlignRight :: (Real u, Floating u, InterpretUnit u) + => String -> LocRectTextLine u+multiAlignRight ss = + renderMultiLine VRight (map makeTextObject $ lines ss)+++renderMultiLine :: (Real u, Floating u, InterpretUnit u) + => VAlign -> [TextObject u] -> LocRectTextLine u+renderMultiLine va docs = body >>= posTextWithMargins+ where+ body = (\dy -> alignColumnSep va dy $ reverse docs) <$> textlineSpace+++makeTextObject :: InterpretUnit u => String -> TextObject u+makeTextObject = makeEscTextObject . escapeString +++makeEscTextObject :: InterpretUnit u => EscapedText -> TextObject u+makeEscTextObject esc = + makePosObject (textOrientationZero esc) (escTextLine esc)+++-- Note inclided text will (probably) have to construct with the +-- incline angle rather than apply it as part of the run function.+--++rtextline :: (Real u, Floating u, Ord u, InterpretUnit u) + => Radian -> String -> LocRectTextLine u+rtextline ang ss = rescTextline ang (escapeString ss) ++-- Is rotated text better with no margin?+rescTextline :: (Real u, Floating u, Ord u, InterpretUnit u) + => Radian -> EscapedText -> LocRectTextLine u+rescTextline ang esc = runPosObjectR2 $ makePosObject ortt body+ where+ ortt = fmap (rotOrientation ang) $ textOrientationZero esc+ body = incline (rescTextLine esc) ang++-- | Rotate an Orientation about its locus.+--+rotOrientation :: (Real u, Floating u, Ord u) + => Radian -> Orientation u -> Orientation u+rotOrientation ang (Orientation xmin xmaj ymin ymaj) = + orthoOrientation bl br tl tr + where+ bl = rotateCorner ang $ P2 (-xmin) (-ymin)+ br = rotateCorner ang $ P2 xmaj (-ymaj)+ tr = rotateCorner ang $ P2 xmaj ymaj+ tl = rotateCorner ang $ P2 (-xmin) ymaj+ ++-- | This is not necessarily correct...+--+orthoOrientation :: (Num u, Ord u)+ => Point2 u -> Point2 u -> Point2 u -> Point2 u + -> Orientation u+orthoOrientation (P2 x0 y0) (P2 x1 y1) (P2 x2 y2) (P2 x3 y3) = + Orientation { or_x_minor = abs $ min4 x0 x1 x2 x3+ , or_x_major = max4 x0 x1 x2 x3+ , or_y_minor = abs $ min4 y0 y1 y2 y3+ , or_y_major = max4 y0 y1 y2 y3+ }+++rotateCorner :: (Real u, Floating u) => Radian -> Point2 u -> Point2 u+rotateCorner ang pt = displaceVec v2 zeroPt+ where+ v1 = pvec zeroPt pt + theta = vdirection v1+ hyp = vlength v1+ v2 = avec (ang+theta) hyp++min4 :: Ord u => u -> u -> u -> u -> u+min4 a b c d = min (min a b) (min c d)++max4 :: Ord u => u -> u -> u -> u -> u+max4 a b c d = max (max a b) (max c d)+++{-++type RotText u = PosThetaImage BoundingBox u+++-------------------++-- | One line of multiline text+--+data OnelineText u = OnelineText + { text_content :: EscapedText+ , oneline_adv :: AdvanceVec u+ }++++type OnelineGraphicF u = u -> OnelineText u -> LocThetaGraphic u+++++rotTextStart :: PosThetaImage u a -> RectPosition -> Radian -> LocImage u a+rotTextStart = startPosRot+++textbox :: (Real u, Floating u, InterpretUnit u) + => String -> PosImage BoundingBox u+textbox ss = multiAlignCenter ss `ptRot` 0++++rtextbox :: (Real u, Floating u, InterpretUnit u) + => String -> PosThetaImage BoundingBox u+rtextbox ss = multiAlignCenter ss+++-- multi line text allows rotation ++multiAlignLeft :: (Real u, Floating u, InterpretUnit u) + => String -> PosThetaImage BoundingBox u+multiAlignLeft ss = + drawMultiline onelineALeft (map escapeString $ lines ss)++multiAlignCenter :: (Real u, Floating u, InterpretUnit u) + => String -> PosThetaImage BoundingBox u+multiAlignCenter ss = + drawMultiline onelineACenter (map escapeString $ lines ss)++multiAlignRight :: (Real u, Floating u, InterpretUnit u) + => String -> RotText u+multiAlignRight ss = + drawMultiline onelineARight (map escapeString $ lines ss)+++textAlignLeft :: (Real u, Floating u, InterpretUnit u) + => String -> LocImage BoundingBox u+textAlignLeft ss = startPosRot (multiAlignLeft ss) CENTER 0++textAlignCenter :: (Real u, Floating u, InterpretUnit u) + => String -> LocImage BoundingBox u+textAlignCenter ss = startPosRot (multiAlignCenter ss) CENTER 0 ++textAlignRight :: (Real u, Floating u, InterpretUnit u) + => String -> LocImage BoundingBox u+textAlignRight ss = startPosRot (multiAlignRight ss) CENTER 0++++++drawMultiline :: (Real u, Floating u, InterpretUnit u) + => OnelineGraphicF u -> [EscapedText] + -> PosThetaImage BoundingBox u+drawMultiline _ [] = lift1R3 emptyBoundedLocGraphic+drawMultiline drawF xs = promoteR3 $ \start rpos ang ->+ linesToInterims xs >>= \(max_w, ones) ->+ borderedRotTextPos ang line_count max_w >>= \opos -> + let gf = multilineGraphic drawF max_w ang ones+ bbf = orthoBB max_w line_count ang+ img = intoLocImage bbf gf+ posG = makePosImage opos img+ in atStartPos posG start rpos + where+ line_count = length xs+++multilineGraphic :: (Floating u, InterpretUnit u)+ => OnelineGraphicF u + -> u + -> Radian + -> [OnelineText u]+ -> LocGraphic u+multilineGraphic drawF max_w ang xs = + lift0R1 (centerSpineDisps (length xs) ang) >>= \(disp_top, disp_next) ->+ let gs = map (\a -> rot (drawF max_w a) ang) xs+ in ignoreAns $ moveStart disp_top $ chainDisplace disp_next gs++-- | Draw left-aligned text. Effictively this is:+--+-- > Leftwards for the half the max vector+-- >+-- > Down to the baseline from the center.+--+onelineALeft :: (Real u, Floating u, InterpretUnit u) + => OnelineGraphicF u +onelineALeft width otext = promoteR2 $ \ctr theta -> + centerToBaseline >>= \down -> + let pt = move down theta ctr + in atRot (rescTextLine $ text_content otext) pt theta+ where+ vec1 = hvec $ negate $ 0.5 * width+ move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang+++-- | Draw center-aligned text. Effictively this is:+--+-- > Leftwards for the half the width vector+-- >+-- > Down to the baseline from the center.+--+-- The max_adv is ignored.+--+onelineACenter :: (Real u, Floating u, InterpretUnit u) + => OnelineGraphicF u+onelineACenter _ otext = promoteR2 $ \ctr theta -> + centerToBaseline >>= \down -> + let pt = move down theta ctr + in atRot (rescTextLine $ text_content otext) pt theta+ where+ vec1 = negateV $ 0.5 *^ oneline_adv otext+ move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang+++-- | Draw right-aligned text. Effictively this is:+--+-- > Rightwards for the half the max width+-- >+-- > Leftwards for the width vector+-- >+-- > Down to the baseline from the center.+--+onelineARight :: (Real u, Floating u, InterpretUnit u) + => OnelineGraphicF u+onelineARight max_w otext = promoteR2 $ \ctr theta -> + centerToBaseline >>= \down -> + let pt = move down theta ctr + in atRot (rescTextLine $ text_content otext) pt theta+ where+ vec1 = hvec (0.5 * max_w) ^-^ oneline_adv otext+ move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang++++++-- Note - for multiline text, the bounding box (of one line) is +-- always the same size regardless of the alignment of the textlines.+--++-- | Its easy to find top-left and top-right, then bottom-left is +-- the vector from top-right to center added to the center. +-- Likewise bottom-right is the vector from top-left-to center +-- added to the center. Visually this construction forms a bow of +-- two triangles meeting at the (rectangle) center.++orthoBB :: (Real u, Floating u, InterpretUnit u) + => u -> Int -> Radian -> LocQuery u (BoundingBox u)+orthoBB w line_count theta = promoteR1 $ \ctr ->+ fmap (0.5*) verticalSpan >>= \hh1 ->+ textMargin >>= \(xsep,ysep) -> + centerSpineDisps line_count theta >>= \(disp_top,_) ->+ let top_ctr = disp_top ctr+ hw = 0.5 * w+ tr = displaceOrtho (V2 (hw+xsep) (hh1+ysep)) theta top_ctr+ tl = displaceOrtho (V2 (negate $ hw+xsep) (hh1+ysep)) theta top_ctr+ bl = ctr .+^ pvec tr ctr + br = ctr .+^ pvec tl ctr+ in return $ traceBoundary [tr,tl,bl,br]++++-- Note - displaceOrtho would be more convenient if it wasn\'t a +-- vector.++++--------------------------------------------------------------------------------++-- This isn't worth the complexity to get down to one traversal...++-- | Turn the input list of lines of 'EscapedText' into +-- 'OnelineText' and return the result list twinned with the +-- largest width.+--+linesToInterims :: (InterpretUnit u, Ord u) + => [EscapedText] -> Query (u, [OnelineText u])+linesToInterims = fmap post . mapM onelineEscText+ where+ post xs = let vmax = foldr fn 0 xs in (vmax,xs)+ fn (OnelineText _ av) wmax = max (advanceH av) wmax+++++onelineEscText :: InterpretUnit u => EscapedText -> Query (OnelineText u)+onelineEscText esc = fmap (OnelineText esc) $ textVector esc+++-}
− src/Wumpus/Drawing/Text/CatText.hs
@@ -1,207 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Text.Text--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC------ Left-to-right text.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Text.CatText- ( - - CatText- , leftAlign- , centerAlign- , rightAlign-- , blank- , space- , string- , (<>)- , (<+>) -- , fontColour-- ) where--import Wumpus.Drawing.Chains-import Wumpus.Drawing.Text.Base--import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.Utils.JoinList ( JoinList, ViewL(..), viewl )-import qualified Wumpus.Basic.Utils.JoinList as JL--import Wumpus.Core -- package: wumpus-core--import Data.Char ( ord )---- Need to know line width (horizontal) and line count (vertical) --- to render...------ Can obviously access line count if we avoid avoid operators --- for vertical composition operator and delegate it to rendering--- instead:------ > rightAlign :: [CatText u] -> PosImage u (BoundingBox u)------- A CatPrim returns a drawing function (AdvGraphic) to be used--- drawing final rendering.----type CatPrim u = CF (u, AdvGraphic u)--newtype CatText u = CatText { getCatText :: JoinList (CatPrim u) }------ | 'HMove' : @ half_max_width * line_width -> Horizontal_Displacement @----type HMove u = u -> u -> u--leftAMove :: Num u => HMove u-leftAMove half_max _ = negate half_max- -centerAMove :: Fractional u => HMove u-centerAMove _ elt_w = negate $ 0.5 * elt_w--rightAMove :: Num u => HMove u-rightAMove half_max elt_w = half_max - elt_w----leftAlign :: (Real u, FromPtSize u, Floating u) - => [CatText u] -> PosImage u (BoundingBox u)-leftAlign = drawMulti leftAMove--centerAlign :: (Real u, FromPtSize u, Floating u) - => [CatText u] -> PosImage u (BoundingBox u)-centerAlign = drawMulti centerAMove--rightAlign :: (Real u, FromPtSize u, Floating u) - => [CatText u] -> PosImage u (BoundingBox u)-rightAlign = drawMulti rightAMove----drawMulti :: (Real u, FromPtSize u, Floating u) - => HMove u -> [CatText u] -> PosImage u (BoundingBox u)-drawMulti moveF xs = promoteR2 $ \start rpos -> - evalAllLines xs >>= \all_lines -> - centerToBaseline >>= \down -> - borderedTextObjectPos line_count (fst all_lines) >>= \opos ->- let chn = centerSpinePoints line_count 0 - gs = positionHLines moveF down all_lines - gf = unchainZip emptyLocGraphic gs chn- posG = makePosImage opos gf- bbox = objectPosBounds start rpos opos- in replaceAns bbox $ atStartPos posG start rpos - where- line_count = length xs--positionHLines :: Fractional u - => HMove u -> u -> (u,[(u, AdvGraphic u)]) -> [LocGraphic u]-positionHLines mkH down (max_w,xs) = map fn xs- where- half_max = 0.5 * max_w- moveF w1 = let v = vec (mkH half_max w1) (-down) - in moveStart $ displaceVec v - fn (elt_w, gf) = ignoreAns $ moveF elt_w $ gf---evalAllLines :: (Num u, Ord u) - => [CatText u] -> DrawingInfo (u, [(u, AdvGraphic u)])-evalAllLines = fmap post . mapM evalLine- where- post xs = let mx = foldr (\(a,_) x -> max a x) 0 xs in (mx,xs)- -----evalLine :: Num u => CatText u -> DrawingInfo (u, AdvGraphic u)-evalLine ct = case viewl $ getCatText ct of- EmptyL -> return (0, replaceAns (hvec 0) $ emptyLocGraphic)- af :< rest -> af >>= \a -> go a (viewl rest)- where- go acc EmptyL = return acc- go (dx,af) (mf :< ms) = let moveF = moveStart (displaceH dx)- in mf >>= \(u,gf) -> - go (dx+u, af `oplus` moveF gf) (viewl ms)-------- | Build a blank CatText with no output and a 0 width vector.----blank :: Num u => CatText u-blank = catOne $ return (0, replaceAns (hvec 0) $ emptyLocGraphic)---- | Note - a space character is not draw in the output, instead --- 'space' advances the width vector by the width of a space in --- the current font.----space :: FromPtSize u => CatText u-space = catOne $ - charVector (CharEscInt $ ord ' ') >>= \v -> - return (advanceH v, replaceAns v $ emptyLocGraphic)---- | Build a CatText from a string.----string :: FromPtSize u => String -> CatText u-string = catOne . stringPrim---infixr 6 <>, <+>---- | Concatenate two CatTexts separated with no spacing.----(<>) :: CatText u -> CatText u -> CatText u-a <> b = CatText $ JL.join (getCatText a) (getCatText b) ----- | Concatenate two CatTexts separated with a space.----(<+>) :: FromPtSize u => CatText u -> CatText u -> CatText u-a <+> b = a <> space <> b ------ Note - @fill@ combinators cf. @wl-pprint@ (but left and right) --- will be very useful.------ Also PosImages can be inlined in text...-----catOne :: CatPrim u -> CatText u-catOne = CatText . JL.one ---stringPrim :: FromPtSize u => String -> CatPrim u-stringPrim = escapedPrim . escapeString--escapedPrim :: FromPtSize u => EscapedText -> CatPrim u-escapedPrim esc = textVector esc >>= \v -> - return (vector_x v, replaceAns v $ escapedline esc)---catMap :: (AdvGraphic u -> AdvGraphic u) -> CatText u -> CatText u-catMap f = CatText . fmap (fmap (\(u,ag) -> (u, f $ ag))) . getCatText--catlocal :: DrawingContextF -> CatText u -> CatText u-catlocal fn = catMap (localize fn)---fontColour :: RGBi -> CatText u -> CatText u-fontColour rgb = catlocal (strokeColour rgb)--
+ src/Wumpus/Drawing/Text/DirectionZero.hs view
@@ -0,0 +1,27 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.DirectionZero+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Common import module for the Writing Direction 0 modules+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.DirectionZero+ ( + module Wumpus.Drawing.Text.Base.DocTextZero+ , module Wumpus.Drawing.Text.Base.PosChar+ , module Wumpus.Drawing.Text.Base.RotTextZero++ ) where++import Wumpus.Drawing.Text.Base.DocTextZero+import Wumpus.Drawing.Text.Base.PosChar+import Wumpus.Drawing.Text.Base.RotTextZero
− src/Wumpus/Drawing/Text/LRText.hs
@@ -1,292 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Text.LRText--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC------ Left-to-right measured text that supports radial inclination.--- Caveat - rendering at any degree other than the horizontal may--- not look good in PostScript or SVG.--- --- Note - LRText does not use the 'text_margin' setting from the --- 'DrawingContext'.------ \*\* WARNING \*\* - the API for this module needs some polish.------ -----------------------------------------------------------------------------------module Wumpus.Drawing.Text.LRText- ( -- singleLine- , escSingleLine- , rsingleLine- , rescSingleLine-- , multiAlignLeft- , multiAlignCenter- , multiAlignRight-- , textAlignCenter- , textAlignLeft- , textAlignRight-- ) where--import Wumpus.Drawing.Chains-import Wumpus.Drawing.Text.Base--import Wumpus.Basic.Kernel -- package: wumpus-basic--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space-import Data.VectorSpace-------- Note - margins are not added to the text. This seems to be the --- right thing to do in the case of rotated text, where the ortho--- projection of the rectangle already can add spacing between --- the RectPos and the actual text.----------------------------- | One line of multiline text----data OnelineText u = OnelineText - { text_content :: EscapedText- , oneline_adv :: AdvanceVec u- }---- Design note - using a LocThetaImage could be used instead, but--- as the angle of inclination is interior to the final type the --- it is used explicitly.----type OnelineDrawF u = - Radian -> AdvanceVec u -> OnelineText u -> LocImage u (BoundingBox u)-----singleLine :: (Real u, Floating u, FromPtSize u) - => String -> PosImage u (BoundingBox u)-singleLine ss = onelineDraw onelineACenter 0 (escapeString ss)--escSingleLine :: (Real u, Floating u, FromPtSize u) - => EscapedText -> PosImage u (BoundingBox u)-escSingleLine = onelineDraw onelineACenter 0---rsingleLine :: (Real u, Floating u, FromPtSize u) - => Radian -> String -> PosImage u (BoundingBox u)-rsingleLine theta ss = onelineDraw onelineACenter theta (escapeString ss)--rescSingleLine :: (Real u, Floating u, FromPtSize u) - => Radian -> EscapedText -> PosImage u (BoundingBox u)-rescSingleLine = onelineDraw onelineACenter--multiAlignLeft :: (Real u, Floating u, FromPtSize u) - => Radian -> String -> PosImage u (BoundingBox u)-multiAlignLeft theta ss = - drawMultiline onelineALeft theta (map escapeString $ lines ss)--multiAlignCenter :: (Real u, Floating u, FromPtSize u) - => Radian -> String -> PosImage u (BoundingBox u)-multiAlignCenter theta ss = - drawMultiline onelineACenter theta (map escapeString $ lines ss)--multiAlignRight :: (Real u, Floating u, FromPtSize u) - => Radian -> String -> PosImage u (BoundingBox u)-multiAlignRight theta ss = - drawMultiline onelineARight theta (map escapeString $ lines ss)---textAlignLeft :: (Real u, Floating u, FromPtSize u) - => String -> LocImage u (BoundingBox u)-textAlignLeft ss = multiAlignLeft 0 ss `startPos` CENTER--textAlignCenter :: (Real u, Floating u, FromPtSize u) - => String -> LocImage u (BoundingBox u)-textAlignCenter ss = multiAlignCenter 0 ss `startPos` CENTER --textAlignRight :: (Real u, Floating u, FromPtSize u) - => String -> LocImage u (BoundingBox u)-textAlignRight ss = multiAlignRight 0 ss `startPos` CENTER ------- Note - inclination is not part of the ContextFunction...--drawMultiline :: (Real u, Floating u, FromPtSize u) - => OnelineDrawF u -> Radian -> [EscapedText] - -> PosImage u (BoundingBox u)-drawMultiline _ _ [] = lift1R2 emptyBoundedLocGraphic-drawMultiline drawF theta [x] = onelineDraw drawF theta x-drawMultiline drawF theta xs = promoteR2 $ \start rpos ->- linesToInterims xs >>= \(max_adv, ones) -> - rotObjectPos theta line_count (advanceH max_adv) >>= \opos -> - let chn = centerSpinePoints line_count theta- gs = map (drawF theta max_adv) ones- gf = unchainZip emptyBoundedLocGraphic gs chn- posG = makePosImage opos gf- in atStartPos posG start rpos - where- line_count = length xs-----onelineDraw :: (Real u, Floating u, FromPtSize u) - => OnelineDrawF u -> Radian -> EscapedText -> PosImage u (BoundingBox u)-onelineDraw drawF theta esc = promoteR2 $ \start rpos ->- onelineEscText esc >>= \otext -> - rotObjectPos theta 1 (advanceH $ oneline_adv otext) >>= \opos -> - let max_adv = oneline_adv otext - gf = drawF theta max_adv otext- posG = makePosImage opos gf- in atStartPos posG start rpos ----- | LR text needs the objectPos under rotation.----rotObjectPos :: (Real u, Floating u, FromPtSize u) - => Radian -> Int -> u -> DrawingInfo (ObjectPos u)-rotObjectPos theta line_count max_w =- fmap (orthoObjectPos theta) $ textObjectPos line_count max_w ---- ---- | Note - this returns the answer in center form, regardless--- of whether the input was in center form.--- --- So it is probably not a general enough function for the --- PosImage library.----orthoObjectPos :: (Real u, Floating u) - => Radian -> ObjectPos u -> ObjectPos u-orthoObjectPos theta (ObjectPos xmin xmaj ymin ymaj) = - ObjectPos bbox_hw bbox_hw bbox_hh bbox_hh- where- input_hw = 0.5 * (xmin + xmaj)- input_hh = 0.5 * (ymin + ymaj)- bbox0 = BBox (P2 (-input_hw) (-input_hh)) (P2 input_hw input_hh)- bbox1 = retraceBoundary (rotateAbout theta zeroPt) bbox0- bbox_hw = 0.5 * (boundaryWidth bbox1)- bbox_hh = 0.5 * (boundaryHeight bbox1)---------- | Draw left-aligned text. Effictively this is:------ > Leftwards for the half the max vector--- >--- > Down to the baseline from the center.----onelineALeft :: (Real u, Floating u, FromPtSize u) - => OnelineDrawF u -onelineALeft theta max_adv otext = promoteR1 $ \ctr -> - centerToBaseline >>= \down -> - atRot (orthoBB max_adv) ctr theta >>= \bbox -> - let pt = move down theta ctr - in replaceAns bbox $ atRot (rescapedline $ text_content otext) pt theta- where- vec1 = negateV $ 0.5 *^ max_adv- move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang----- | Draw center-aligned text. Effictively this is:------ > Leftwards for the half the width vector--- >--- > Down to the baseline from the center.----onelineACenter :: (Real u, Floating u, FromPtSize u) - => OnelineDrawF u-onelineACenter theta max_adv otext = promoteR1 $ \ctr -> - centerToBaseline >>= \down -> - atRot (orthoBB max_adv) ctr theta >>= \bbox -> - let pt = move down theta ctr - in replaceAns bbox $ atRot (rescapedline $ text_content otext) pt theta- where- vec1 = negateV $ 0.5 *^ oneline_adv otext- move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang----- | Draw right-aligned text. Effictively this is:------ > Rightwards for the half the max vector--- >--- > Leftwards for the width vector--- >--- > Down to the baseline from the center.----onelineARight :: (Real u, Floating u, FromPtSize u) - => OnelineDrawF u-onelineARight theta max_adv otext = promoteR1 $ \ctr -> - centerToBaseline >>= \down -> - atRot (orthoBB max_adv) ctr theta >>= \bbox -> - let pt = move down theta ctr - in replaceAns bbox $ atRot (rescapedline $ text_content otext) pt theta- where- vec1 = (0.5 *^ max_adv) ^-^ oneline_adv otext- move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang------ Note - for multiline text, the bounding box (of one line) is --- always the same size regardless of the alignment of the textlines.----orthoBB :: (Real u, Floating u, FromPtSize u) - => AdvanceVec u -> LocThetaDrawingInfo u (BoundingBox u)-orthoBB (V2 w _) = promoteR2 $ \ctr theta -> - glyphVerticalSpan >>= \h ->- let bl = ctr .-^ V2 (0.5 * w) (0.5 * h)- bb1 = boundingBox bl (bl .+^ V2 w h)- bb2 = retraceBoundary (rotateAbout theta ctr) bb1- in return bb2---------------------------------------------------------------------------------------- This isn't worth the complexity to get down to one traversal...---- | Turn the input list of lines of 'EscapedText' into --- 'OnelineText' and return the result list twinned with the --- largest 'AdvanceVec'.----linesToInterims :: (FromPtSize u, Ord u) - => [EscapedText] -> DrawingInfo (AdvanceVec u, [OnelineText u])-linesToInterims = fmap post . mapM onelineEscText- where- post xs = let vmax = foldr fn (hvec 0) xs in (vmax,xs)- fn (OnelineText _ av) vmax = avMaxWidth av vmax-----avMaxWidth :: Ord u => AdvanceVec u -> AdvanceVec u -> AdvanceVec u-avMaxWidth a@(V2 w1 _) b@(V2 w2 _) = if w2 > w1 then b else a--onelineEscText :: FromPtSize u => EscapedText -> DrawingInfo (OnelineText u)-onelineEscText esc = fmap (OnelineText esc) $ textVector esc--
− src/Wumpus/Drawing/Text/SafeFonts.hs
@@ -1,167 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Text.SafeFonts--- Copyright : (c) Stephen Tetley 2009-2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Safe to use \"Core 13\" fonts that are expected to be present--- for any PostScript interpreter.------ Note - regrettably Symbol is not safe to use for SVG.------ \*\* WARNING \*\* - this module is in flux due to changes to --- Text encoding in Wumpus-Core and adding font metrics to --- Wumpus-Basic. The code here is likely to be revised.--------------------------------------------------------------------------------------module Wumpus.Drawing.Text.SafeFonts- ( - -- * Times Roman- times_roman- , times_italic- , times_bold- , times_bold_italic-- -- * Helvetica- , helvetica- , helvetica_oblique- , helvetica_bold- , helvetica_bold_oblique-- -- * Courier- , courier- , courier_oblique- , courier_bold- , courier_bold_oblique-- -- * Symbol- , symbol-- ) where----import Wumpus.Core-import Wumpus.Core.Text.StandardEncoding-import Wumpus.Core.Text.Symbol---- Supported fonts are:------ Times-Roman Times-Italic Times-Bold Times-BoldItalic--- Helvetica Helvetica-Oblique Helvetica-Bold Helvetica-Bold-Oblique--- Courier Courier-Oblique Courier-Bold Courier-Bold-Oblique--- Symbol------------------------------------------------------------------------------------- ---- | Times-Roman--- -times_roman :: FontFace-times_roman = - FontFace "Times-Roman" "Times New Roman" SVG_REGULAR standard_encoding---- | Times Italic----times_italic :: FontFace-times_italic = - FontFace "Times-Italic" "Times New Roman" SVG_ITALIC standard_encoding- --- | Times Bold----times_bold :: FontFace-times_bold = - FontFace "Times-Bold" "Times New Roman" SVG_BOLD standard_encoding---- | Times Bold Italic----times_bold_italic :: FontFace-times_bold_italic = FontFace "Times-BoldItalic" - "Times New Roman" - SVG_BOLD_ITALIC - standard_encoding-------------------------------------------------------------------------------------- Helvetica---- | Helvetica ----helvetica :: FontFace-helvetica = FontFace "Helvetica" "Helvetica" SVG_REGULAR standard_encoding----- | Helvetica Oblique----helvetica_oblique :: FontFace-helvetica_oblique = - FontFace "Helvetica-Oblique" "Helvetica" SVG_OBLIQUE standard_encoding---- | Helvetica Bold--- -helvetica_bold :: FontFace-helvetica_bold = - FontFace "Helvetica-Bold" "Helvetica" SVG_BOLD standard_encoding----- | Helvetica Bold Oblique----helvetica_bold_oblique :: FontFace-helvetica_bold_oblique = FontFace "Helvetica-Bold-Oblique" - "Helvetica" - SVG_BOLD_OBLIQUE - standard_encoding---------------------------------------------------------------------------------------- | Courier--- -courier :: FontFace-courier = FontFace "Courier" "Courier New" SVG_REGULAR standard_encoding---- | Courier Oblique--- -courier_oblique :: FontFace-courier_oblique = - FontFace "Courier-Oblique" "Courier New" SVG_OBLIQUE standard_encoding---- | Courier Bold--- -courier_bold :: FontFace-courier_bold = - FontFace "Courier-Bold" "Courier New" SVG_BOLD standard_encoding----- | Courier Bold Oblique--- -courier_bold_oblique :: FontFace-courier_bold_oblique = FontFace "Courier-Bold-Oblique" - "Courier New" - SVG_BOLD_OBLIQUE - standard_encoding------------------------------------------------------------------------------------- Symbol---- | Symbol------ Note - Symbol is intentionally not supported for SVG by some --- renderers (Firefox). Chrome is fine, but the use of symbol --- should be still be avoided for web graphics.--- -symbol :: FontFace-symbol = FontFace "Symbol" "Symbol" SVG_REGULAR symbol_encoding-----
+ src/Wumpus/Drawing/Text/StandardFontDefs.hs view
@@ -0,0 +1,323 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Text.StandardFontDefs+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Safe to use \"Core 13\" fonts that are expected to be present+-- for any PostScript interpreter.+--+-- Note - regrettably Symbol is not safe to use for SVG.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Text.StandardFontDefs+ ( + -- * Times Roman+ times_roman_family+ + , times_roman+ , times_italic+ , times_bold+ , times_bold_italic++ -- * Helvetica+ , helvetica_family++ , helvetica+ , helvetica_oblique+ , helvetica_bold+ , helvetica_bold_oblique++ -- * Courier+ , courier_family++ , courier+ , courier_oblique+ , courier_bold+ , courier_bold_oblique++ -- * Symbol+ , symbol++ ) where+++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Text.StandardEncoding+import Wumpus.Core.Text.Symbol++-- Supported fonts are:+--+-- Times-Roman Times-Italic Times-Bold Times-BoldItalic+-- Helvetica Helvetica-Oblique Helvetica-Bold Helvetica-Bold-Oblique+-- Courier Courier-Oblique Courier-Bold Courier-Bold-Oblique+-- Symbol++--------------------------------------------------------------------------------+-- ++-- | 'FontFamily' definition for Times-Roman.+--+times_roman_family :: FontFamily+times_roman_family = + FontFamily { ff_regular = times_roman+ , ff_bold = Just times_bold+ , ff_italic = Just times_italic+ , ff_bold_italic = Just times_bold_italic+ }+++-- | Times-Roman+-- +times_roman :: FontDef+times_roman = + FontDef { font_def_face = face+ , gs_file_name = "n021003l.afm" -- NimbusRomNo9L-Regu+ , afm_file_name = "Times-Roman.afm"+ }+ where+ face = FontFace { ps_font_name = "Times-Roman" + , svg_font_family = "Times New Roman" + , svg_font_style = SVG_REGULAR + , font_enc_vector = standard_encoding+ }+++-- | Times Italic+--+times_italic :: FontDef+times_italic =+ FontDef { font_def_face = face+ , gs_file_name = "n021023l.afm" -- NimbusRomNo9L-ReguItal+ , afm_file_name = "Times-Italic.afm"+ }+ where+ face = FontFace { ps_font_name = "Times-Italic"+ , svg_font_family = "Times New Roman"+ , svg_font_style = SVG_ITALIC+ , font_enc_vector = standard_encoding+ }+++-- | Times Bold+--+times_bold :: FontDef+times_bold = + FontDef { font_def_face = face+ , gs_file_name = "n021004l.afm" -- NimbusRomNo9L-Medi+ , afm_file_name = "Times-Bold.afm"+ }+ where+ face = FontFace { ps_font_name = "Times-Bold"+ , svg_font_family = "Times New Roman"+ , svg_font_style = SVG_BOLD+ , font_enc_vector = standard_encoding+ }+++-- | Times Bold Italic+--+times_bold_italic :: FontDef+times_bold_italic = + FontDef { font_def_face = face+ , gs_file_name = "n021024l.afm" -- NimbusRomNo9L-MediItal+ , afm_file_name = "Times-BoldItalic.afm"+ }+ where+ face = FontFace { ps_font_name = "Times-BoldItalic"+ , svg_font_family = "Times New Roman"+ , svg_font_style = SVG_BOLD_ITALIC+ , font_enc_vector = standard_encoding+ }+++--------------------------------------------------------------------------------+-- Helvetica++-- | 'FontFamily' definition for Helvetica.+--+helvetica_family :: FontFamily+helvetica_family = + FontFamily { ff_regular = helvetica+ , ff_bold = Just helvetica_bold+ , ff_italic = Just helvetica_oblique+ , ff_bold_italic = Just helvetica_bold_oblique+ }++++-- | Helvetica regular weight.+--+helvetica :: FontDef+helvetica =+ FontDef { font_def_face = face+ , gs_file_name = "n019003l.afm" -- NimbusSanL-Regu+ , afm_file_name = "Helvetica.afm"+ }+ where+ face = FontFace { ps_font_name = "Helvetica"+ , svg_font_family = "Helvetica"+ , svg_font_style = SVG_REGULAR+ , font_enc_vector = standard_encoding+ }+++-- | Helvetica Oblique+--+helvetica_oblique :: FontDef+helvetica_oblique = + FontDef { font_def_face = face+ , gs_file_name = "n019023l.afm" -- NimbusSanL-ReguItal+ , afm_file_name = "Helvetica-Oblique.afm"+ }+ where+ face = FontFace { ps_font_name = "Helvetica-Oblique"+ , svg_font_family = "Helvetica"+ , svg_font_style = SVG_OBLIQUE+ , font_enc_vector = standard_encoding+ }++-- | Helvetica Bold+-- +helvetica_bold :: FontDef+helvetica_bold = + FontDef { font_def_face = face+ , gs_file_name = "n019004l.afm" -- NimbusSanL-Bold+ , afm_file_name = "Helvetica-Bold.afm"+ }+ where+ face = FontFace { ps_font_name = "Helvetica-Bold"+ , svg_font_family = "Helvetica"+ , svg_font_style = SVG_BOLD+ , font_enc_vector = standard_encoding+ }+++-- | Helvetica Bold Oblique+--+helvetica_bold_oblique :: FontDef+helvetica_bold_oblique = + FontDef { font_def_face = face+ , gs_file_name = "n019024l.afm" -- NimbusSanL-BoldItal+ , afm_file_name = "Helvetica-BoldOblique.afm"+ }+ where+ face = FontFace { ps_font_name = "Helvetica-Bold-Oblique"+ , svg_font_family = "Helvetica"+ , svg_font_style = SVG_BOLD_OBLIQUE+ , font_enc_vector = standard_encoding+ }++++--------------------------------------------------------------------------------++-- | 'FontFamily' definition for Courier.+--+courier_family :: FontFamily+courier_family = + FontFamily { ff_regular = courier+ , ff_bold = Just courier_bold+ , ff_italic = Just courier_oblique+ , ff_bold_italic = Just courier_bold_oblique+ }++++-- | Courier+-- +courier :: FontDef+courier = + FontDef { font_def_face = face+ , gs_file_name = "n022003l.afm" -- NimbusMonL-Regu+ , afm_file_name = "Courier.afm"+ }+ where+ face = FontFace { ps_font_name = "Courier"+ , svg_font_family = "Courier New"+ , svg_font_style = SVG_REGULAR+ , font_enc_vector = standard_encoding+ }++-- | Courier Oblique+-- +courier_oblique :: FontDef+courier_oblique = + FontDef { font_def_face = face+ , gs_file_name = "n022023l.afm" -- NimbusMonL-ReguObli+ , afm_file_name = "Courier-Oblique.afm"+ }+ where+ face = FontFace { ps_font_name = "Courier-Oblique"+ , svg_font_family = "Courier New"+ , svg_font_style = SVG_OBLIQUE+ , font_enc_vector = standard_encoding+ }+++-- | Courier Bold+-- +courier_bold :: FontDef+courier_bold =+ FontDef { font_def_face = face+ , gs_file_name = "n022004l.afm" -- NimbusMonL-Bold+ , afm_file_name = "Courier-Bold.afm"+ }+ where+ face = FontFace { ps_font_name = "Courier-Bold"+ , svg_font_family = "Courier New"+ , svg_font_style = SVG_BOLD+ , font_enc_vector = standard_encoding+ }+++-- | Courier Bold Oblique+-- +courier_bold_oblique :: FontDef+courier_bold_oblique = + FontDef { font_def_face = face+ , gs_file_name = "n022024l.afm" -- NimbusMonL-BoldObli+ , afm_file_name = "Courier-BoldOblique.afm"+ }+ where+ face = FontFace { ps_font_name = "Courier-Bold-Oblique"+ , svg_font_family = "Courier New"+ , svg_font_style = SVG_BOLD_OBLIQUE+ , font_enc_vector = standard_encoding+ }++--------------------------------------------------------------------------------+-- Symbol++-- | Symbol+--+-- Note - Symbol is intentionally not supported for SVG by some +-- renderers (Firefox). Chrome is fine, but the use of symbol +-- should be still be avoided for web graphics.+-- +symbol :: FontDef+symbol = + FontDef { font_def_face = face+ , gs_file_name = "s050000l.afm" -- StandardSymL+ , afm_file_name = "Symbol.afm"+ }+ where+ face = FontFace { ps_font_name = "Symbol"+ , svg_font_family = "Symbol"+ , svg_font_style = SVG_REGULAR+ , font_enc_vector = symbol_encoding+ }+++++
− src/Wumpus/Drawing/Turtle/TurtleClass.hs
@@ -1,91 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Turtle.TurtleClass--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Turtle monad and monad transformer.------ The Turtle monad embodies the LOGO style of imperative --- drawing - sending commands to update the a cursor.------ While Wumpus generally aims for a more compositional,--- \"coordinate-free\" style of drawing, some types of diagram --- are more easily expressed in the LOGO style.------ Note - as turtle drawing with Wumpus is a /local effect/, --- there is only one instance of TurtleM. Potentially TurtleM --- will be removed and the functions implemented directly. --------------------------------------------------------------------------------------module Wumpus.Drawing.Turtle.TurtleClass- (-- Coord-- , TurtleM(..)-- , setsLoc- , setsLoc_-- -- * movement- , resetLoc- , moveLeft- , moveRight- , moveUp- , moveDown- , nextLine- -- ) where----type Coord = (Int,Int)---class Monad m => TurtleM m where- getLoc :: m (Int,Int)- setLoc :: (Int,Int) -> m ()- getOrigin :: m (Int,Int)- setOrigin :: (Int,Int) -> m ()----setsLoc :: TurtleM m => (Coord -> (a,Coord)) -> m a-setsLoc f = getLoc >>= \coord -> - let (a,coord') = f coord in setLoc coord' >> return a--setsLoc_ :: TurtleM m => (Coord -> Coord) -> m ()-setsLoc_ f = getLoc >>= \coord -> setLoc (f coord)---resetLoc :: TurtleM m => m ()-resetLoc = getOrigin >>= setLoc---moveRight :: TurtleM m => m ()-moveRight = setsLoc_ $ \(x,y)-> (x+1, y)---moveLeft :: TurtleM m => m ()-moveLeft = setsLoc_ $ \(x,y) -> (x-1,y)--moveUp :: TurtleM m => m ()-moveUp = setsLoc_ $ \(x,y) -> (x,y+1)--moveDown :: TurtleM m => m ()-moveDown = setsLoc_ $ \(x,y) -> (x ,y-1)---nextLine :: TurtleM m => m ()-nextLine = getOrigin >>= \(ox,_) ->- setsLoc_ $ \(_,y) -> (ox,y-1)-
− src/Wumpus/Drawing/Turtle/TurtleMonad.hs
@@ -1,139 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Turtle.TurtleMonad--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Turtle monad transformer.------ The Turtle monad embodies the LOGO style of imperative --- drawing - sending commands to update the a cursor.------ While Wumpus generally aims for a more compositional,--- \"coordinate-free\" style of drawing, some types of --- diagram are more easily expressed in the LOGO style.------ Turtle is only a transformer - it is intended to be run within--- a 'Drawing'.--------------------------------------------------------------------------------------module Wumpus.Drawing.Turtle.TurtleMonad- (- -- * Re-exports- module Wumpus.Drawing.Turtle.TurtleClass-- -- * Turtle transformer- , TurtleT- , runTurtleT-- - ) where--import Wumpus.Basic.Kernel-import Wumpus.Drawing.Turtle.TurtleClass----import Control.Applicative-import Control.Monad----- Note - if Turtle is now just a /local effect/ monad is the --- Turtle class still needed? Afterall, there is (probably)--- only ever going to be one instance.------- Turtle is a Reader / State monad--- --- The env is the horizontal and vertical move distances.--- --- The state is the current coordinate and the origin.-----data TurtleState = TurtleState - { _turtle_origin :: (Int,Int)- , _current_coord :: (Int,Int)- }--newtype TurtleT u m a = TurtleT { - getTurtleT :: ScalingContext Int Int u - -> TurtleState - -> m (a, TurtleState) }--type instance MonUnit (TurtleT u m) = u- ----- Functor----instance Monad m => Functor (TurtleT u m) where- fmap f m = TurtleT $ \r s -> getTurtleT m r s >>= \(a,s') ->- return (f a, s')----- Applicative --instance Monad m => Applicative (TurtleT u m) where- pure a = TurtleT $ \_ s -> return (a,s)- mf <*> ma = TurtleT $ \r s -> getTurtleT mf r s >>= \(f,s') ->- getTurtleT ma r s' >>= \(a,s'') ->- return (f a,s'') ----- Monad --instance Monad m => Monad (TurtleT u m) where- return a = TurtleT $ \_ s -> return (a,s)- m >>= k = TurtleT $ \r s -> getTurtleT m r s >>= \(a,s') ->- (getTurtleT . k) a r s' >>= \(b,s'') ->- return (b,s'')-----instance Monad m => TurtleM (TurtleT u m) where- getLoc = TurtleT $ \_ s@(TurtleState _ c) -> return (c,s)- setLoc c = TurtleT $ \_ (TurtleState o _) -> return ((),TurtleState o c)- getOrigin = TurtleT $ \_ s@(TurtleState o _) -> return (o,s)- setOrigin o = TurtleT $ \_ (TurtleState _ c) -> return ((),TurtleState o c)---runTurtleT :: (Monad m, Num u) - => (Int,Int) -> ScalingContext Int Int u -> TurtleT u m a -> m a-runTurtleT ogin cfg mf = getTurtleT mf cfg st0 >>= \(a,_) -> return a- where - st0 = TurtleState ogin ogin ----------------------------------------------------------------------------------------- Cross instances--instance DrawingCtxM m => DrawingCtxM (TurtleT u m) where- askDC = TurtleT $ \_ s -> askDC >>= \ ctx -> return (ctx,s)- localize upd mf = TurtleT $ \r s -> localize upd (getTurtleT mf r s)----- This needs undecidable instances...--instance (Monad m, TraceM m, u ~ MonUnit m) => TraceM (TurtleT u m) where- trace a = TurtleT $ \_ s -> trace a >> return ((),s)---instance (Monad m, u ~ MonUnit m, Num u) => PointSupplyM (TurtleT u m) where- position = TurtleT $ \r s@(TurtleState _ (x,y)) -> return (scalePt r x y,s)-
src/Wumpus/Drawing/VersionNumber.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.VersionNumber--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -23,7 +23,7 @@ -- | Version number ----- > (0,2,0)+-- > (0,3,0) -- wumpus_drawing_version :: (Int,Int,Int)-wumpus_drawing_version = (0,2,0)+wumpus_drawing_version = (0,3,0)
wumpus-drawing.cabal view
@@ -1,5 +1,5 @@ name: wumpus-drawing-version: 0.2.0+version: 0.3.0 license: BSD3 license-file: LICENSE copyright: Stephen Tetley <stephen.tetley@gmail.com>@@ -12,7 +12,7 @@ \*\* WARNING \*\* - this package is sub-alpha. Although many of the drawing objects have been improved since the code was split from Wumpus-Basic, the code is still prototypical. Essentially- this package is a /technology preview/ and not a re-usable + this package is a /technology preview/ and not yet a re-usable library. . NOTE - many of the demos use font metrics. Font metrics for@@ -24,7 +24,7 @@ links below. To run the demos properly you will need one of these sets of metrics. .- Adobe Font techinal notes:+ Adobe Font technical notes: <https://www.adobe.com/devnet/font.html> . Core 14 AFM metrics:@@ -38,8 +38,23 @@ . Changelog: .- v0.1.0 to 0.2.0:+ v0.2.0 to v0.3.0: .+ * Moved Turtle and Grids into the @Wumpus.Drawing.Extras@+ name-space. Modules here are considered sketches.+ .+ * Re-implemented arrowheads and connectors.+ .+ * Re-implemented monadic path construction. This is now + essentially \"turtle drawing\" with a path trace.+ .+ * Removed chains - a simplified implementation is now + provided by Wumpus-Basic.+ .+ * Re-implemented and expanded Text. + .+ v0.1.0 to v0.2.0:+ . * Added new Shapes. . * Move Geometry modules to Wumpus-Basic.@@ -73,16 +88,17 @@ LICENSE, demo/ArrowCircuit.hs, demo/Arrowheads.hs,+ demo/Automata.hs, demo/ClipPic.hs, demo/ColourCharts.hs, demo/ColourChartUtils.hs, demo/Connectors.hs demo/DotPic.hs, demo/FeatureModel.hs,- demo/FontLoaderUtils.hs, demo/FontPic.hs, demo/LeftRightText.hs, demo/PetriNet.hs,+ demo/SingleChar.hs, demo/SingleLine.hs, demo/SampleShapes.hs, demo/Symbols.hs,@@ -93,27 +109,33 @@ build-depends: base < 5, containers >= 0.3 && <= 0.6, vector-space >= 0.6 && < 1.0,- wumpus-core >= 0.43.0 && < 0.44.0,- wumpus-basic == 0.16.0+ wumpus-core >= 0.50.0 && < 0.51.0,+ wumpus-basic == 0.17.0 exposed-modules:- Wumpus.Drawing.Arrows,- Wumpus.Drawing.Arrows.Connectors,- Wumpus.Drawing.Arrows.Tips,- Wumpus.Drawing.Chains,- Wumpus.Drawing.Chains.Base,- Wumpus.Drawing.Chains.Derived, Wumpus.Drawing.Colour.SVGColours, Wumpus.Drawing.Colour.X11Colours,+ Wumpus.Drawing.Connectors,+ Wumpus.Drawing.Connectors.Arrowheads,+ Wumpus.Drawing.Connectors.Base,+ Wumpus.Drawing.Connectors.BoxConnectors,+ Wumpus.Drawing.Connectors.ConnectorPaths,+ Wumpus.Drawing.Connectors.Loop, Wumpus.Drawing.Dots.AnchorDots, Wumpus.Drawing.Dots.Marks,- Wumpus.Drawing.Grids,- Wumpus.Drawing.Paths,- Wumpus.Drawing.Paths.Base,- Wumpus.Drawing.Paths.Connectors,- Wumpus.Drawing.Paths.MonadicConstruction,- Wumpus.Drawing.Paths.ControlPoints,+ Wumpus.Drawing.Extras.Axes,+ Wumpus.Drawing.Extras.Grids,+ Wumpus.Drawing.Extras.Turtle.TurtleClass,+ Wumpus.Drawing.Extras.Turtle.TurtleMonad,+ Wumpus.Drawing.Paths.Absolute,+ Wumpus.Drawing.Paths.Base.AbsBuilder,+ Wumpus.Drawing.Paths.Base.AbsPath,+ Wumpus.Drawing.Paths.Base.BuildCommon,+ Wumpus.Drawing.Paths.Base.RelBuilder,+ Wumpus.Drawing.Paths.Base.RelPath,+ Wumpus.Drawing.Paths.Relative,+ Wumpus.Drawing.Paths.Vamps, Wumpus.Drawing.Shapes, Wumpus.Drawing.Shapes.Base, Wumpus.Drawing.Shapes.Circle,@@ -128,12 +150,13 @@ Wumpus.Drawing.Shapes.Semicircle, Wumpus.Drawing.Shapes.Semiellipse, Wumpus.Drawing.Shapes.Triangle,- Wumpus.Drawing.Text.Base,- Wumpus.Drawing.Text.CatText,- Wumpus.Drawing.Text.LRText,- Wumpus.Drawing.Text.SafeFonts,- Wumpus.Drawing.Turtle.TurtleClass,- Wumpus.Drawing.Turtle.TurtleMonad,+ Wumpus.Drawing.Text.Base.Common,+ Wumpus.Drawing.Text.Base.DocTextZero,+ Wumpus.Drawing.Text.Base.Label,+ Wumpus.Drawing.Text.Base.PosChar,+ Wumpus.Drawing.Text.Base.RotTextZero,+ Wumpus.Drawing.Text.DirectionZero,+ Wumpus.Drawing.Text.StandardFontDefs, Wumpus.Drawing.VersionNumber other-modules: