packages feed

wumpus-basic 0.15.0 → 0.16.0

raw patch · 28 files changed

+3203/−774 lines, 28 filesdep ~wumpus-corePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: wumpus-core

API changes (from Hackage documentation)

- Wumpus.Basic.Kernel.Base.Anchors: eastwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: northeastwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor2 t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: northwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: northwestwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor2 t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: southeastwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor2 t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: southwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: southwestwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor2 t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: westwards :: (Real u, Floating u, CenterAnchor t, CardinalAnchor t, u ~ (DUnit t)) => u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.BaseDefs: displace :: Num u => u -> u -> PointDisplace u
- Wumpus.Basic.Kernel.Base.BaseDefs: displaceH :: Num u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Base.BaseDefs: displaceParallel :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Base.BaseDefs: displacePerpendicular :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Base.BaseDefs: displaceV :: Num u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Base.BaseDefs: displaceVec :: Num u => Vec2 u -> PointDisplace u
- Wumpus.Basic.Kernel.Base.BaseDefs: type PointDisplace u = Point2 u -> Point2 u
- Wumpus.Basic.Kernel.Base.BaseDefs: type ThetaPointDisplace u = Radian -> PointDisplace u
- Wumpus.Basic.Kernel.Base.QueryDC: glyphHeight :: (FromPtSize u, DrawingCtxM m) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: glyphHeightRange :: (FromPtSize u, DrawingCtxM m) => m (u, u)
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advplus :: AdvGraphic u -> AdvGraphic u -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: extractLocGraphic :: AdvGraphic u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: makeAdvGraphic :: DrawingInfo (PointDisplace u) -> LocGraphic u -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: runAdvGraphic :: DrawingContext -> Point2 u -> AdvGraphic u -> (Point2 u, PrimGraphic u)
- Wumpus.Basic.Kernel.Objects.BaseObjects: hyperlink :: XLink -> Image u a -> Image u a
- Wumpus.Basic.Kernel.Objects.CtxPicture: alignH :: (Fractional u, Ord u) => HAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: alignHSep :: (Fractional u, Ord u) => HAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: alignV :: (Fractional u, Ord u) => VAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: alignVSep :: (Fractional u, Ord u) => VAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: atPoint :: (Num u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: centeredAt :: (Fractional u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: centric :: (Fractional u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: hcat :: (Real u, Floating u, FromPtSize u) => [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: hcatA :: (Real u, Floating u, FromPtSize u) => HAlign -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: hsep :: (Real u, Floating u, FromPtSize u) => u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: hsepA :: (Real u, Floating u, FromPtSize u) => HAlign -> u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: hspace :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: nextToH :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: nextToV :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: over :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: under :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: vcat :: (Real u, Floating u, FromPtSize u) => [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: vcatA :: (Real u, Floating u, FromPtSize u) => VAlign -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: vsep :: (Real u, Floating u, FromPtSize u) => u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: vsepA :: (Real u, Floating u, FromPtSize u) => VAlign -> u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: vspace :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: zconcat :: (Real u, Floating u, FromPtSize u) => [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.Graphic: borderedCircle :: Floating u => Int -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: borderedDisk :: Num u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: borderedEllipse :: Num u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: borderedPath :: Num u => PrimPath u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Graphic: borderedRectangle :: Fractional u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: closedStroke :: Num u => PrimPath u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Graphic: curveBetween :: Fractional u => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Graphic: emptyLocPath :: Num u => LocCF u (PrimPath u)
- Wumpus.Basic.Kernel.Objects.Graphic: escapedline :: Num u => EscapedText -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: filledCircle :: Floating u => Int -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: filledDisk :: Num u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: filledEllipse :: Num u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: filledPath :: Num u => PrimPath u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Graphic: filledRectangle :: Fractional u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: hkernline :: Num u => [KerningChar u] -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: locPath :: Num u => [Vec2 u] -> LocCF u (PrimPath u)
- Wumpus.Basic.Kernel.Objects.Graphic: moveStartPoint :: PointDisplace u -> LocCF u a -> LocCF u a
- Wumpus.Basic.Kernel.Objects.Graphic: moveStartPointTheta :: PointDisplace u -> LocThetaCF u a -> LocThetaCF u a
- Wumpus.Basic.Kernel.Objects.Graphic: openStroke :: Num u => PrimPath u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Graphic: rborderedEllipse :: Num u => u -> u -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: rescapedline :: Num u => EscapedText -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: rfilledEllipse :: Num u => u -> u -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: rstrokedEllipse :: Num u => u -> u -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: rtextline :: Num u => String -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: straightLine :: Fractional u => Vec2 u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: straightLineBetween :: Fractional u => Point2 u -> Point2 u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Graphic: strokedCircle :: Floating u => Int -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: strokedDisk :: Num u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: strokedEllipse :: Num u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: strokedRectangle :: Fractional u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: textline :: Num u => String -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: vkernline :: Num u => [KerningChar u] -> LocGraphic u
+ Wumpus.Basic.Geometry.Base: BezierCurve :: !Point2 u -> !Point2 u -> !Point2 u -> !Point2 u -> BezierCurve u
+ Wumpus.Basic.Geometry.Base: LineEquation :: !u -> !u -> !u -> LineEquation u
+ Wumpus.Basic.Geometry.Base: LineSegment :: (Point2 u) -> (Point2 u) -> LineSegment u
+ Wumpus.Basic.Geometry.Base: M2'2 :: !u -> !u -> !u -> !u -> Matrix2'2 u
+ Wumpus.Basic.Geometry.Base: affineComb :: Real u => u -> Point2 u -> Point2 u -> Point2 u
+ Wumpus.Basic.Geometry.Base: bezierArcPoints :: Floating u => Radian -> u -> Radian -> Point2 u -> [Point2 u]
+ Wumpus.Basic.Geometry.Base: bezierLength :: (Floating u, Ord u, FromPtSize u) => BezierCurve u -> u
+ Wumpus.Basic.Geometry.Base: bezierMinorArc :: Floating u => Radian -> u -> Radian -> Point2 u -> BezierCurve u
+ Wumpus.Basic.Geometry.Base: data BezierCurve u
+ Wumpus.Basic.Geometry.Base: data LineEquation u
+ Wumpus.Basic.Geometry.Base: data LineSegment u
+ Wumpus.Basic.Geometry.Base: data Matrix2'2 u
+ Wumpus.Basic.Geometry.Base: det2'2 :: Num u => Matrix2'2 u -> u
+ Wumpus.Basic.Geometry.Base: half_pi :: Floating u => u
+ Wumpus.Basic.Geometry.Base: identity2'2 :: Num u => Matrix2'2 u
+ Wumpus.Basic.Geometry.Base: instance Eq u => Eq (BezierCurve u)
+ Wumpus.Basic.Geometry.Base: instance Eq u => Eq (LineEquation u)
+ Wumpus.Basic.Geometry.Base: instance Eq u => Eq (LineSegment u)
+ Wumpus.Basic.Geometry.Base: instance Eq u => Eq (Matrix2'2 u)
+ Wumpus.Basic.Geometry.Base: instance Functor Matrix2'2
+ Wumpus.Basic.Geometry.Base: instance Num u => Num (Matrix2'2 u)
+ Wumpus.Basic.Geometry.Base: instance Ord u => Ord (BezierCurve u)
+ Wumpus.Basic.Geometry.Base: instance Ord u => Ord (LineSegment u)
+ Wumpus.Basic.Geometry.Base: instance Show u => Show (BezierCurve u)
+ Wumpus.Basic.Geometry.Base: instance Show u => Show (LineEquation u)
+ Wumpus.Basic.Geometry.Base: instance Show u => Show (LineSegment u)
+ Wumpus.Basic.Geometry.Base: instance Show u => Show (Matrix2'2 u)
+ Wumpus.Basic.Geometry.Base: lineAngle :: (Floating u, Real u) => Point2 u -> Point2 u -> Radian
+ Wumpus.Basic.Geometry.Base: lineEquation :: Num u => Point2 u -> Point2 u -> LineEquation u
+ Wumpus.Basic.Geometry.Base: line_eqn_A :: LineEquation u -> !u
+ Wumpus.Basic.Geometry.Base: line_eqn_B :: LineEquation u -> !u
+ Wumpus.Basic.Geometry.Base: line_eqn_C :: LineEquation u -> !u
+ Wumpus.Basic.Geometry.Base: midpoint :: Fractional u => Point2 u -> Point2 u -> Point2 u
+ Wumpus.Basic.Geometry.Base: pointLineDistance :: Floating u => Point2 u -> LineEquation u -> u
+ Wumpus.Basic.Geometry.Base: pointViaX :: Fractional u => u -> LineEquation u -> Point2 u
+ Wumpus.Basic.Geometry.Base: pointViaY :: Fractional u => u -> LineEquation u -> Point2 u
+ Wumpus.Basic.Geometry.Base: polygonLineSegments :: [Point2 u] -> [LineSegment u]
+ Wumpus.Basic.Geometry.Base: rectangleLineSegments :: Num u => u -> u -> Point2 u -> [LineSegment u]
+ Wumpus.Basic.Geometry.Base: subdivide :: Fractional u => BezierCurve u -> (BezierCurve u, BezierCurve u)
+ Wumpus.Basic.Geometry.Base: subdividet :: Real u => u -> BezierCurve u -> (BezierCurve u, BezierCurve u)
+ Wumpus.Basic.Geometry.Base: transpose2'2 :: Matrix2'2 u -> Matrix2'2 u
+ Wumpus.Basic.Geometry.Base: two_pi :: Floating u => u
+ Wumpus.Basic.Geometry.Base: type DBezierCurve = BezierCurve Double
+ Wumpus.Basic.Geometry.Base: type DLineEquation = LineEquation Double
+ Wumpus.Basic.Geometry.Base: type DLineSegment = LineSegment Double
+ Wumpus.Basic.Geometry.Base: type DMatrix2'2 = Matrix2'2 Double
+ Wumpus.Basic.Geometry.Intersection: data LineSegment u
+ Wumpus.Basic.Geometry.Intersection: findIntersect :: (Floating u, Real u, Ord u, FromPtSize u) => Point2 u -> Radian -> [LineSegment u] -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interCurveLine :: (Floating u, Ord u, FromPtSize u) => BezierCurve u -> (Point2 u, Point2 u) -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interLineLine :: Fractional u => (Point2 u, Point2 u) -> (Point2 u, Point2 u) -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interLinesegLine :: (Fractional u, Ord u, FromPtSize u) => LineSegment u -> (Point2 u, Point2 u) -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interLinesegLineseg :: (Fractional u, Ord u, FromPtSize u) => LineSegment u -> LineSegment u -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: makePlane :: Floating u => Point2 u -> Radian -> (Point2 u, Point2 u)
+ Wumpus.Basic.Geometry.Intersection: polygonLineSegments :: [Point2 u] -> [LineSegment u]
+ Wumpus.Basic.Geometry.Intersection: rectangleLineSegments :: Num u => u -> u -> Point2 u -> [LineSegment u]
+ Wumpus.Basic.Geometry.Paths: coordinatePrimPath :: Num u => Point2 u -> LocCoordPath u -> PrimPath u
+ Wumpus.Basic.Geometry.Paths: diamondCoordPath :: Num u => u -> u -> LocCoordPath u
+ Wumpus.Basic.Geometry.Paths: equilateralTriangleCoordPath :: Floating u => u -> LocCoordPath u
+ Wumpus.Basic.Geometry.Paths: equilateralTrianglePoints :: Floating u => u -> Point2 u -> (Point2 u, Point2 u, Point2 u)
+ Wumpus.Basic.Geometry.Paths: isoscelesTriangleCoordPath :: Floating u => u -> u -> LocCoordPath u
+ Wumpus.Basic.Geometry.Paths: isoscelesTrianglePoints :: Floating u => u -> u -> Point2 u -> (Point2 u, Point2 u, Point2 u)
+ Wumpus.Basic.Geometry.Paths: polygonCoordPath :: Floating u => Int -> u -> LocCoordPath u
+ Wumpus.Basic.Geometry.Paths: rectangleCoordPath :: Num u => u -> u -> LocCoordPath u
+ Wumpus.Basic.Geometry.Paths: type LocCoordPath u = Point2 u -> [Point2 u]
+ Wumpus.Basic.Geometry.Quadrant: QUAD_NE :: Quadrant
+ Wumpus.Basic.Geometry.Quadrant: QUAD_NW :: Quadrant
+ Wumpus.Basic.Geometry.Quadrant: QUAD_SE :: Quadrant
+ Wumpus.Basic.Geometry.Quadrant: QUAD_SW :: Quadrant
+ Wumpus.Basic.Geometry.Quadrant: data Quadrant
+ Wumpus.Basic.Geometry.Quadrant: diamondRadialVector :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u
+ Wumpus.Basic.Geometry.Quadrant: instance Enum Quadrant
+ Wumpus.Basic.Geometry.Quadrant: instance Eq Quadrant
+ Wumpus.Basic.Geometry.Quadrant: instance Ord Quadrant
+ Wumpus.Basic.Geometry.Quadrant: instance Show Quadrant
+ Wumpus.Basic.Geometry.Quadrant: qiModulo :: Radian -> Radian
+ Wumpus.Basic.Geometry.Quadrant: quadrant :: Radian -> Quadrant
+ Wumpus.Basic.Geometry.Quadrant: rectRadialVector :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u
+ Wumpus.Basic.Geometry.Quadrant: rectangleQI :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u
+ Wumpus.Basic.Geometry.Quadrant: rightTrapeziumBaseWidth :: Fractional u => u -> u -> Radian -> u
+ Wumpus.Basic.Geometry.Quadrant: rightTrapezoidQI :: (Real u, Floating u) => u -> u -> Radian -> Radian -> Vec2 u
+ Wumpus.Basic.Geometry.Quadrant: triangleQI :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u
+ Wumpus.Basic.Geometry.Quadrant: triangleRadialVector :: (Real u, Floating u) => u -> u -> u -> Radian -> Vec2 u
+ Wumpus.Basic.Kernel.Base.Anchors: apex :: (ApexAnchor t, (DUnit t) ~ u) => t -> Point2 u
+ Wumpus.Basic.Kernel.Base.Anchors: bottomLeftCorner :: (BottomCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
+ Wumpus.Basic.Kernel.Base.Anchors: bottomRightCorner :: (BottomCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
+ Wumpus.Basic.Kernel.Base.Anchors: class ApexAnchor t
+ Wumpus.Basic.Kernel.Base.Anchors: class BottomCornerAnchor t
+ Wumpus.Basic.Kernel.Base.Anchors: class SideMidpointAnchor t
+ Wumpus.Basic.Kernel.Base.Anchors: class TopCornerAnchor t
+ Wumpus.Basic.Kernel.Base.Anchors: projectAnchor :: (Real u, Floating u, u ~ (DUnit t), CenterAnchor t) => (t -> Point2 u) -> u -> t -> Point2 u
+ Wumpus.Basic.Kernel.Base.Anchors: sideMidpoint :: (SideMidpointAnchor t, (DUnit t) ~ u) => Int -> t -> Point2 u
+ Wumpus.Basic.Kernel.Base.Anchors: topLeftCorner :: (TopCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
+ Wumpus.Basic.Kernel.Base.Anchors: topRightCorner :: (TopCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
+ Wumpus.Basic.Kernel.Base.BaseDefs: EAST :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: NORTH :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: NORTH_EAST :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: NORTH_WEST :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: SOUTH :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: SOUTH_EAST :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: SOUTH_WEST :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: WEST :: Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: data Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance (OPlus a, OPlus b, OPlus c) => OPlus (a, b, c)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance (OPlus a, OPlus b, OPlus c, OPlus d) => OPlus (a, b, c, d)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Enum Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Eq Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Num u => OPlus (Vec2 u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Ord Cardinal
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Show Cardinal
+ Wumpus.Basic.Kernel.Base.GlyphMetrics: get_descender :: MetricsOps -> forall u. FromPtSize u => PtSize -> u
+ Wumpus.Basic.Kernel.Base.QueryDC: glyphDescender :: (FromPtSize u, DrawingCtxM m) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: glyphVerticalSpan :: (FromPtSize u, DrawingCtxM m) => m u
+ Wumpus.Basic.Kernel.Base.UpdateDC: scalesize :: Ratio Int -> DrawingContextF
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advcat :: Num u => AdvGraphic u -> AdvGraphic u -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advfill :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advpunctuate :: Num u => AdvGraphic u -> [AdvGraphic u] -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advsep :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advspace :: Num u => Vec2 u -> [AdvGraphic u] -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: emptyAdvGraphic :: Num u => AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: intoAdvGraphic :: LocCF u (Vec2 u) -> LocGraphic u -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: bbrectangle :: Fractional u => BoundingBox u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: emptyBoundedLocThetaGraphic :: Num u => BoundedLocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.Connector: emptyConnectorGraphic :: Num u => ConnectorGraphic u
+ Wumpus.Basic.Kernel.Objects.Connector: intoConnectorImage :: ConnectorCF u a -> ConnectorGraphic u -> ConnectorImage u a
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignColumn :: (Real u, Floating u, FromPtSize u) => VAlign -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignColumnSep :: (Real u, Floating u, FromPtSize u) => VAlign -> u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignH :: (Fractional u, Ord u) => HAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignRow :: (Real u, Floating u, FromPtSize u) => HAlign -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignRowSep :: (Real u, Floating u, FromPtSize u) => HAlign -> u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignSepH :: (Fractional u, Ord u) => HAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignSepV :: (Fractional u, Ord u) => VAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignV :: (Fractional u, Ord u) => VAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpBeneath :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpCenteredAt :: (Fractional u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpColumn :: (Real u, Floating u, FromPtSize u) => CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpColumnSep :: (Real u, Floating u, FromPtSize u) => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpDown :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpDownSep :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRight :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRightSep :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRow :: (Real u, Floating u, FromPtSize u) => CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRowSep :: (Real u, Floating u, FromPtSize u) => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: cxpUniteCenter :: (Fractional u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance (Num u, Ord u) => OPlus (CtxPicture u)
+ Wumpus.Basic.Kernel.Objects.Displacement: displace :: Num u => u -> u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: displaceH :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: displaceOrtho :: Floating u => Vec2 u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: displaceParallel :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: displacePerpendicular :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: displaceV :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: displaceVec :: Num u => Vec2 u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: eastwards :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStart :: PointDisplace u -> LocCF u a -> LocCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStartTheta :: ThetaPointDisplace u -> LocThetaCF u a -> LocThetaCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStartThetaAngle :: ThetaDisplace -> LocThetaCF u a -> LocThetaCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStartThetaPoint :: PointDisplace u -> LocThetaCF u a -> LocThetaCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: northeastwards :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: northwards :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: northwestwards :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: southeastwards :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: southwards :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: southwestwards :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaEastwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaNortheastwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaNorthwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaNorthwestwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaSoutheastwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaSouthwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaSouthwestwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: thetaWestwards :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: type PointDisplace u = Point2 u -> Point2 u
+ Wumpus.Basic.Kernel.Objects.Displacement: type ThetaDisplace = Radian -> Radian
+ Wumpus.Basic.Kernel.Objects.Displacement: type ThetaPointDisplace u = Radian -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: westwards :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedCircle :: Floating u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedDisk :: Num u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedEllipse :: Floating u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedEllipseDisk :: Num u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedPath :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedRectangle :: Fractional u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: closedStroke :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: curveGraphic :: Fractional u => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: emptyLocPath :: Num u => LocCF u (PrimPath u)
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: escapedline :: Num u => EscapedText -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledCircle :: Floating u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledDisk :: Num u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledEllipse :: Floating u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledEllipseDisk :: Num u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledPath :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledRectangle :: Fractional u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: hkernline :: Num u => [KerningChar u] -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: locPath :: Num u => [Vec2 u] -> LocCF u (PrimPath u)
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: openStroke :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rborderedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rescapedline :: Num u => EscapedText -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rfilledEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rstrokedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rtextline :: Num u => String -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: straightLine :: Fractional u => Vec2 u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: straightLineGraphic :: Fractional u => Point2 u -> Point2 u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedCircle :: Floating u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedDisk :: Num u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedEllipse :: Floating u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedEllipseDisk :: Num u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedRectangle :: Fractional u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: textline :: Num u => String -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: vkernline :: Num u => [KerningChar u] -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.Graphic: adecorate :: Monad m => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Graphic: decorate :: Monad m => m (ImageAns u a) -> m (ImageAns u zz) -> m (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Graphic: emptyLocThetaGraphic :: Num u => LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.Graphic: hyperlink :: Functor m => XLink -> m (ImageAns u a) -> m (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Graphic: ignoreAns :: Functor f => f (a, b) -> f (UNil u, b)
+ Wumpus.Basic.Kernel.Objects.Graphic: mapAns :: Functor f => (a -> z) -> f (a, b) -> f (z, b)
+ Wumpus.Basic.Kernel.Objects.Graphic: replaceAns :: Functor f => z -> f (a, b) -> f (z, b)
+ Wumpus.Basic.Kernel.Objects.Graphic: safeconcat :: OPlus a => Image u a -> [Image u a] -> Image u a
+ Wumpus.Basic.Kernel.Objects.Graphic: sdecorate :: Monad m => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.PosImage: CENTER :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: EE :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: NE :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: NN :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: NW :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: ObjectPos :: !u -> !u -> !u -> !u -> ObjectPos u
+ Wumpus.Basic.Kernel.Objects.PosImage: SE :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: SS :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: SW :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: WW :: RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: atStartPos :: Floating u => PosImage u a -> Point2 u -> RectPosition -> Image u a
+ Wumpus.Basic.Kernel.Objects.PosImage: data ObjectPos u
+ Wumpus.Basic.Kernel.Objects.PosImage: data RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: instance (Fractional u, Ord u) => OPlus (ObjectPos u)
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Enum RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Eq RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Eq u => Eq (ObjectPos u)
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Ord RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Ord u => Ord (ObjectPos u)
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Show RectPosition
+ Wumpus.Basic.Kernel.Objects.PosImage: instance Show u => Show (ObjectPos u)
+ Wumpus.Basic.Kernel.Objects.PosImage: makePosImage :: Fractional u => ObjectPos u -> LocImage u a -> PosImage u a
+ Wumpus.Basic.Kernel.Objects.PosImage: objectPosBounds :: Fractional u => Point2 u -> RectPosition -> ObjectPos u -> BoundingBox u
+ Wumpus.Basic.Kernel.Objects.PosImage: op_x_major :: ObjectPos u -> !u
+ Wumpus.Basic.Kernel.Objects.PosImage: op_x_minor :: ObjectPos u -> !u
+ Wumpus.Basic.Kernel.Objects.PosImage: op_y_major :: ObjectPos u -> !u
+ Wumpus.Basic.Kernel.Objects.PosImage: op_y_minor :: ObjectPos u -> !u
+ Wumpus.Basic.Kernel.Objects.PosImage: startPos :: Floating u => PosImage u a -> RectPosition -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.PosImage: type DPosGraphic = PosGraphic Double
+ Wumpus.Basic.Kernel.Objects.PosImage: type DPosImage a = PosImage Double a
+ Wumpus.Basic.Kernel.Objects.PosImage: type PosGraphic u = PosImage u (UNil u)
+ Wumpus.Basic.Kernel.Objects.PosImage: type PosImage u a = CF2 (Point2 u) RectPosition (ImageAns u a)
+ Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_descender :: AfmFile -> Maybe AfmUnit
+ Wumpus.Basic.System.FontLoader.Base.Datatypes: default_descender :: MonospaceDefaults cu -> cu
+ Wumpus.Basic.System.FontLoader.Base.Datatypes: fp_descender :: FontProps cu -> cu
- Wumpus.Basic.Kernel.Base.GlyphMetrics: MetricsOps :: (forall u. FromPtSize u => PtSize -> BoundingBox u) -> (forall u. FromPtSize u => PtSize -> CharWidthTable u) -> (forall u. FromPtSize u => PtSize -> u) -> MetricsOps
+ Wumpus.Basic.Kernel.Base.GlyphMetrics: MetricsOps :: (forall u. FromPtSize u => PtSize -> BoundingBox u) -> (forall u. FromPtSize u => PtSize -> CharWidthTable u) -> (forall u. FromPtSize u => PtSize -> u) -> (forall u. FromPtSize u => PtSize -> u) -> MetricsOps
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: type AdvGraphic u = LocImage u (Point2 u)
+ Wumpus.Basic.Kernel.Objects.AdvanceGraphic: type AdvGraphic u = LocImage u (Vec2 u)
- Wumpus.Basic.Kernel.Objects.CtxPicture: clipCtxPicture :: (Num u, Ord u) => (PrimPath u) -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: clipCtxPicture :: (Num u, Ord u) => PrimPath u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.System.FontLoader.Base.Datatypes: AfmFile :: Maybe String -> Maybe AfmBoundingBox -> Maybe AfmUnit -> [AfmGlyphMetrics] -> AfmFile
+ Wumpus.Basic.System.FontLoader.Base.Datatypes: AfmFile :: Maybe String -> Maybe AfmBoundingBox -> Maybe AfmUnit -> Maybe AfmUnit -> [AfmGlyphMetrics] -> AfmFile
- Wumpus.Basic.System.FontLoader.Base.Datatypes: FontProps :: BoundingBox cu -> Vec2 cu -> IntMap (Vec2 cu) -> cu -> FontProps cu
+ Wumpus.Basic.System.FontLoader.Base.Datatypes: FontProps :: BoundingBox cu -> Vec2 cu -> IntMap (Vec2 cu) -> cu -> cu -> FontProps cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: MonospaceDefaults :: BoundingBox cu -> cu -> Vec2 cu -> MonospaceDefaults cu
+ Wumpus.Basic.System.FontLoader.Base.Datatypes: MonospaceDefaults :: BoundingBox cu -> cu -> cu -> Vec2 cu -> MonospaceDefaults cu

Files

+ demo/SimpleAdvGraphic.hs view
@@ -0,0 +1,52 @@+{-# OPTIONS -Wall #-}+++module SimpleAdvGraphic where++import Wumpus.Basic.Kernel++import Wumpus.Core                      -- package: wumpus-core++import System.Directory++main :: IO ()+main = do +    createDirectoryIfMissing True "./out/"+    let pic1 = runCtxPictureU std_attr drawing01+    writeEPS "./out/simple_adv_graphic01.eps" pic1+    writeSVG "./out/simple_adv_graphic01.svg" pic1+++std_attr :: DrawingContext+std_attr = standardContext 24+++drawing01 :: DCtxPicture+drawing01 = drawTracing $ mf +++mf :: (Floating u, FromPtSize u) => TraceDrawing u ()+mf = do+    drawi_ $ advspace (hvec 10) [text01, text02, text01] `at` P2 0 120+    drawi_ $ advconcat [text01, text02, text01] `at` P2 0 80+    drawi_ $ (miniDisk `advcat` text01 `advcat` miniDisk) `at` P2 0 40 +    drawi_ $ (miniDisk `advcat` text02 `advcat` miniDisk) `at` P2 0 0 +++-- Normally, text calculate the advance vector from the font +-- metrics...+--+text01 :: Num u => AdvGraphic u +text01 = replaceAns (hvec 84) $ textline "text01"+    ++text02 :: Num u => AdvGraphic u +text02 = replaceAns (hvec 210) $ textline "text number two"+++miniDisk :: Num u => AdvGraphic u+miniDisk = replaceAns (V2 0 0) $ localize (fillColour sienna) $ filledDisk 3+++sienna :: RGBi+sienna = RGBi 160 82 45
+ demo/SimplePosImage.hs view
@@ -0,0 +1,98 @@+{-# OPTIONS -Wall #-}+++module SimplePosImage where++import Wumpus.Basic.Kernel++import Wumpus.Core                      -- package: wumpus-core+import Wumpus.Core.Colour ( red )++import System.Directory++main :: IO ()+main = do +    createDirectoryIfMissing True "./out/"+    let pic1 = runCtxPictureU std_attr drawing01+    writeEPS "./out/simple_pos_image01.eps" pic1+    writeSVG "./out/simple_pos_image01.svg" pic1+++std_attr :: DrawingContext+std_attr = standardContext 24+++drawing01 :: DCtxPicture+drawing01 = drawTracing $ localize (fillColour red) $ mf +++mf :: (Floating u, FromPtSize u) => TraceDrawing u ()+mf = do+    draw $ testDrawMinor NN     `at` (P2   0 300)+    draw $ testDrawMinor SS     `at` (P2  75 300)+    draw $ testDrawMinor EE     `at` (P2 150 300)+    draw $ testDrawMinor WW     `at` (P2 225 300)+    draw $ testDrawMinor NE     `at` (P2   0 225)+    draw $ testDrawMinor SE     `at` (P2  75 225)+    draw $ testDrawMinor SW     `at` (P2 150 225)+    draw $ testDrawMinor NW     `at` (P2 225 225)+    draw $ testDrawMinor CENTER `at` (P2   0 150)+    draw $ testDrawBl    CENTER `at` (P2 225 150)+    draw $ testDrawBl    NN     `at` (P2   0 75)+    draw $ testDrawBl    SS     `at` (P2  75 75)+    draw $ testDrawBl    EE     `at` (P2 150 75)+    draw $ testDrawBl    WW     `at` (P2 225 75)+    draw $ testDrawBl    NE     `at` (P2   0 0)+    draw $ testDrawBl    SE     `at` (P2  75 0)+    draw $ testDrawBl    SW     `at` (P2 150 0)+    draw $ testDrawBl    NW     `at` (P2 225 0)+    ++testDrawBl :: Floating u => RectPosition -> LocGraphic u+testDrawBl rpos = filledDisk 2 `oplus` (rectBl `startPos` rpos)++rectBl :: Floating u => PosGraphic u +rectBl = makePosImage opos (mkRectBl w h)+  where+    w    = 40 +    h    = 20+    opos = ObjectPos { op_x_minor = 0+                     , op_x_major = w+                     , op_y_minor = 0+                     , op_y_major = h }+ ++-- start-point - bottom left+mkRectBl :: Floating u => u -> u -> LocGraphic u+mkRectBl w h = promoteR1 $ \bl -> +    let br = displaceH w bl+        tr = displaceV h br+        tl = displaceV h bl+    in closedStroke $ vertexPath [bl, br, tr, tl]++++testDrawMinor :: Floating u => RectPosition -> LocGraphic u+testDrawMinor rpos = filledDisk 2 `oplus` (rectMinor `startPos` rpos)++rectMinor :: Floating u => PosGraphic u +rectMinor = makePosImage opos (mkRectMinor m w h)+  where+    m    = 10+    w    = 40 +    h    = 20+    opos = ObjectPos { op_x_minor = m+                     , op_x_major = (w-m)+                     , op_y_minor = m+                     , op_y_major = (h-m) }+ ++-- start-point - +10 +10+mkRectMinor :: Floating u => u -> u -> u -> LocGraphic u+mkRectMinor m w h = promoteR1 $ \pt -> +    let bl = displaceVec (vec (-m) (-m)) pt+        br = displaceH w bl+        tr = displaceV h br+        tl = displaceV h bl+    in closedStroke $ vertexPath [bl, br, tr, tl]+
+ src/Wumpus/Basic/Geometry/Base.hs view
@@ -0,0 +1,468 @@+{-# LANGUAGE TypeFamilies               #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Basic.Geometry.Base+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Base geometric types and operations.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Geometry.Base+  ( ++  -- * constants+    half_pi+  , two_pi++  -- * 2x2 Matrix+  , Matrix2'2(..)+  , DMatrix2'2+  , identity2'2+  , det2'2+  , transpose2'2+  +  -- * Line in equational form +  , LineEquation(..)+  , DLineEquation+  , lineEquation+  , pointViaX+  , pointViaY+  , pointLineDistance++  -- * Line segment+  , LineSegment(..)+  , DLineSegment+  +  , rectangleLineSegments+  , polygonLineSegments++  -- * Cubic Bezier curves+  +  , BezierCurve(..)+  , DBezierCurve++  , bezierLength+  , subdivide+  , subdividet+  +  , bezierArcPoints+  , bezierMinorArc++  -- * Functions+  , affineComb+  , midpoint+  , lineAngle+++  ) +  where++import Wumpus.Basic.Kernel                      -- package: wumpus-basic++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space+import Data.VectorSpace+++++half_pi :: Floating u => u+half_pi = 0.5*pi++two_pi  :: Floating u => u+two_pi  = 2*pi+++--------------------------------------------------------------------------------+-- 2x2 matrix+++-- | 2x2 matrix, considered to be in row-major form.+-- +-- > (M2'2 a b+-- >       c d)+--+-- ++data Matrix2'2 u = M2'2 !u !u   !u !u+  deriving (Eq)++type DMatrix2'2 = Matrix2'2 Double+++type instance DUnit (Matrix2'2 u)   = u+++instance Functor Matrix2'2 where+  fmap f (M2'2 a b  c d) = M2'2 (f a) (f b)  (f c) (f d)++instance Show u => Show (Matrix2'2 u) where+  show (M2'2 a b c d) = "(M2'2 " ++ body ++ ")" +    where+      body = show [[a,b],[c,d]]++lift2Matrix2'2 :: (u -> u -> u) -> Matrix2'2 u -> Matrix2'2 u -> Matrix2'2 u+lift2Matrix2'2 op (M2'2 a b c d) (M2'2 m n o p) = +      M2'2 (a `op` m) (b `op` n) +           (c `op` o) (d `op` p)++instance Num u => Num (Matrix2'2 u) where+  (+) = lift2Matrix2'2 (+) +  (-) = lift2Matrix2'2 (-)++  (*) (M2'2 a b c d) (M2'2 m n o p) = +      M2'2 (a*m + b*o) (a*n + b*p)  +           (c*m + d*o) (c*n + d*p) +  +  abs    = fmap abs +  negate = fmap negate+  signum = fmap signum+  fromInteger a = M2'2 a' a'  a' a' where a' = fromInteger a+++-- | Construct the identity 2x2 matrix:+--+-- > (M2'2 1 0 +-- >       0 1 )+--+identity2'2 :: Num u => Matrix2'2 u+identity2'2 = M2'2  1 0  +                    0 1+++-- | Determinant of a 2x2 matrix.+--+det2'2 :: Num u => Matrix2'2 u -> u+det2'2 (M2'2 a b c d) = a*d - b*c+++-- | Transpose a 2x2 matrix.+--+transpose2'2 :: Matrix2'2 u -> Matrix2'2 u+transpose2'2 (M2'2 a b +                   c d) = M2'2 a c+                               b d+++--------------------------------------------------------------------------------++-- | Line in equational form, i.e. @Ax + By + C = 0@.+--+data LineEquation u = LineEquation +      { line_eqn_A :: !u+      , line_eqn_B :: !u+      , line_eqn_C :: !u +      }+  deriving (Eq,Show)++type DLineEquation = LineEquation Double++type instance DUnit (LineEquation u) = u++-- | 'lineEquation' : @ point1 * point2 -> LineEquation @+-- +-- Construct a line in equational form bisecting the supplied +-- points.+--+lineEquation :: Num u => Point2 u -> Point2 u -> LineEquation u+lineEquation (P2 x1 y1) (P2 x2 y2) = LineEquation a b c +  where+    a = y1 - y2+    b = x2 - x1+    c = (x1*y2) - (x2*y1)++-- | 'pointViaX' : @ x * line_equation -> Point @+--+-- Calculate the point on the line for the supplied @x@ value.+-- +pointViaX :: Fractional u => u -> LineEquation u -> Point2 u+pointViaX x (LineEquation a b c) = P2 x y+  where+    y = ((a*x) + c) / (-b)+++-- | 'pointViaY' : @ y * line_equation -> Point @+--+-- Calculate the point on the line for the supplied @y@ value.+-- +pointViaY :: Fractional u => u -> LineEquation u -> Point2 u+pointViaY y (LineEquation a b c) = P2 x y+  where+    x = ((b*y) + c) / (-a)+++-- | 'pointLineDistance' : @ point -> line -> Distance @+--+-- Find the distance from a point to a line in equational form+-- using this formula:+-- +-- > P(u,v) +-- > L: Ax + By + C = 0+-- >+-- > (A*u) + (B*v) + C +-- > -----------------+-- > sqrt $ (A^2) +(B^2)+--+-- A positive distance indicates the point is above the line, +-- negative indicates below.+--+pointLineDistance :: Floating u => Point2 u -> LineEquation u -> u+pointLineDistance (P2 u v) (LineEquation a b c) = +    ((a*u) + (b*v) + c) / base+  where+    base = sqrt $ (a^two) + (b^two)+    two  :: Integer+    two  = 2++--------------------------------------------------------------------------------++data LineSegment u = LineSegment (Point2 u) (Point2 u)+  deriving (Eq,Ord,Show)++type DLineSegment = LineSegment Double++type instance DUnit (LineSegment u) = u++++-- | 'rectangleLineSegments' : @ half_width * half_height -> [LineSegment] @+--+-- Compute the line segments of a rectangle.+--+rectangleLineSegments :: Num u => u -> u -> Point2 u -> [LineSegment u]+rectangleLineSegments hw hh ctr = +    [ LineSegment br tr, LineSegment tr tl, LineSegment tl bl+    , LineSegment bl br +    ]+  where+    br = ctr .+^ vec hw    (-hh)+    tr = ctr .+^ vec hw    hh+    tl = ctr .+^ vec (-hw) hh+    bl = ctr .+^ vec (-hw) (-hh)+++-- | 'polygonLineSegments' : @ [point] -> [LineSegment] @+--+-- Build the line segments of a polygon fome a list of +-- its vertices.+--+polygonLineSegments :: [Point2 u] -> [LineSegment u]+polygonLineSegments []     = []+polygonLineSegments (x:xs) = step x xs +  where+    step a []        = [LineSegment a x]+    step a (b:bs)    = (LineSegment a b) : step b bs+++++--------------------------------------------------------------------------------+-- Bezier curves+++-- | A Strict cubic Bezier curve.+--+data BezierCurve u = BezierCurve !(Point2 u) !(Point2 u) !(Point2 u) !(Point2 u)+  deriving (Eq,Ord,Show)++type DBezierCurve = BezierCurve Double++type instance DUnit (BezierCurve u) = u++++-- | 'bezierLength' : @ start_point * control_1 * control_2 * +--        end_point -> Length @ +--+-- Find the length of a Bezier curve. The result is an +-- approximation, with the /tolerance/ is 0.1 of a point. This+-- seems good enough for drawing (potentially the tolerance could +-- be larger still). +--+-- The result is found through repeated subdivision so the +-- calculation is potentially costly.+--+bezierLength :: (Floating u, Ord u, FromPtSize u)      +             => BezierCurve u -> u+bezierLength = gravesenLength (fromPtSize 0.1)++++-- | Jens Gravesen\'s bezier arc-length approximation. +--+-- Note this implementation is parametrized on error tolerance.+--+gravesenLength :: (Floating u, Ord u) => u -> BezierCurve u -> u+gravesenLength err_tol crv = step crv +  where+    step c = let l1 = ctrlPolyLength c+                 l0 = cordLength c+             in if   l1-l0 > err_tol+                then let (a,b) = subdivide c in step a + step b+                else 0.5*l0 + 0.5*l1++-- | Length of the tree lines spanning the control points.+--+ctrlPolyLength :: Floating u => BezierCurve u -> u+ctrlPolyLength (BezierCurve p0 p1 p2 p3) = len p0 p1 + len p1 p2 + len p2 p3+  where+    len pa pb = vlength $ pvec pa pb+++-- | Length of the cord - start point to end point.+--+cordLength :: Floating u => BezierCurve u -> u+cordLength (BezierCurve p0 _ _ p3) = vlength $ pvec p0 p3+++++-- | Curve subdivision via de Casteljau\'s algorithm.+--+subdivide :: Fractional u +          => BezierCurve u -> (BezierCurve u, BezierCurve u)+subdivide (BezierCurve p0 p1 p2 p3) =+    (BezierCurve p0 p01 p012 p0123, BezierCurve p0123 p123 p23 p3)+  where+    p01   = midpoint p0    p1+    p12   = midpoint p1    p2+    p23   = midpoint p2    p3+    p012  = midpoint p01   p12+    p123  = midpoint p12   p23+    p0123 = midpoint p012  p123++-- | subdivide with an affine weight along the line...+--+subdividet :: Real u+           => u -> BezierCurve u -> (BezierCurve u, BezierCurve u)+subdividet t (BezierCurve p0 p1 p2 p3) = +    (BezierCurve p0 p01 p012 p0123, BezierCurve p0123 p123 p23 p3)+  where+    p01   = affineComb t p0    p1+    p12   = affineComb t p1    p2+    p23   = affineComb t p2    p3+    p012  = affineComb t p01   p12+    p123  = affineComb t p12   p23+    p0123 = affineComb t p012  p123+++++kappa :: Floating u => u+kappa = 4 * ((sqrt 2 - 1) / 3)++++-- | 'bezierArcPoints' : @ apex_angle * radius * rotation * center -> [Point] @+--+-- > ang should be in the range 0 < ang < 360deg.+--+-- > if   0 < ang <=  90 returns 4 points+-- > if  90 < ang <= 180 returns 7 points+-- > if 180 < ang <= 270 returns 10 points+-- > if 270 < ang <  360 returns 13 points+--+bezierArcPoints ::  Floating u +                => Radian -> u -> Radian -> Point2 u -> [Point2 u]+bezierArcPoints ang radius theta pt = go (circularModulo ang)+  where+    go a | a <= half_pi = wedge1 a+         | a <= pi      = wedge2 (a/2)+         | a <= 1.5*pi  = wedge3 (a/3)+         | otherwise    = wedge4 (a/4)+    +    wedge1 a = +      let (BezierCurve p0 p1 p2 p3) = bezierMinorArc a radius theta pt+      in [p0,p1,p2,p3]++    wedge2 a = +      let (BezierCurve  p0 p1 p2 p3) = bezierMinorArc a radius theta pt+          (BezierCurve _   p4 p5 p6) = bezierMinorArc a radius (theta+a) pt+      in [ p0,p1,p2,p3, p4,p5,p6 ] ++    wedge3 a = +      let (BezierCurve p0 p1 p2 p3) = bezierMinorArc a radius theta pt+          (BezierCurve _  p4 p5 p6) = bezierMinorArc a radius (theta+a) pt+          (BezierCurve _  p7 p8 p9) = bezierMinorArc a radius (theta+a+a) pt+      in [ p0,p1,p2,p3, p4,p5,p6, p7, p8, p9 ] +  +    wedge4 a = +      let (BezierCurve p0 p1 p2 p3)    = bezierMinorArc a radius theta pt+          (BezierCurve _  p4 p5 p6)    = bezierMinorArc a radius (theta+a) pt+          (BezierCurve _  p7 p8 p9)    = bezierMinorArc a radius (theta+a+a) pt+          (BezierCurve _  p10 p11 p12) = bezierMinorArc a radius (theta+a+a+a) pt+      in [ p0,p1,p2,p3, p4,p5,p6, p7,p8,p9, p10,p11, p12 ] +++-- | 'bezierMinorArc' : @ apex_angle * radius * rotation * center -> BezierCurve @+--+-- > ang should be in the range 0 < ang <= 90deg.+--+bezierMinorArc :: Floating u +                 => Radian -> u -> Radian -> Point2 u -> BezierCurve u+bezierMinorArc ang radius theta pt = BezierCurve p0 c1 c2 p3+  where+    kfactor = fromRadian $ ang / (0.5*pi)+    rl      = kfactor * radius * kappa+    totang  = circularModulo $ ang + theta++    p0      = displaceParallel radius theta pt+    c1      = displacePerpendicular rl theta p0+    c2      = displacePerpendicular (-rl) totang p3+    p3      = displaceParallel radius totang pt+++--------------------------------------------------------------------------------+--+++-- | Affine combination...+--+affineComb :: Real u => u -> Point2 u -> Point2 u -> Point2 u+affineComb t p1 p2 = p1 .+^ t *^ (p2 .-. p1)+++-- | 'midpoint' : @ start_point * end_point -> Midpoint @+-- +-- Mid-point on the line formed between the two supplied points.+--+midpoint :: Fractional u => Point2 u -> Point2 u -> Point2 u+midpoint p0 p1 = p0 .+^ v1 ^/ 2 where v1 = p1 .-. p0++++-- | 'lineAngle' : @ start_point * end_point -> Angle @+--+-- Calculate the counter-clockwise angle between the line formed +-- by the two points and the horizontal plane.+--+lineAngle :: (Floating u, Real u) => Point2 u -> Point2 u -> Radian+lineAngle (P2 x1 y1) (P2 x2 y2) = step (x2 - x1) (y2 - y1)+  where+    -- north-east quadrant +    step x y | pve x && pve y = toRadian $ atan (y/x)          +    +    -- north-west quadrant+    step x y | pve y          = pi     - (toRadian $ atan (y / abs x))++    -- south-east quadrant+    step x y | pve x          = (2*pi) - (toRadian $ atan (abs y / x)) ++    -- otherwise... south-west quadrant+    step x y                  = pi     + (toRadian $ atan (y/x))++    pve a                     = signum a >= 0++-- Ideally this would be in Geometry.Quadrant.+-- And surely there is a simpler formulation...++
+ src/Wumpus/Basic/Geometry/Intersection.hs view
@@ -0,0 +1,223 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Basic.Geometry.Intersection+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Intersection of line to line and line to plane.+-- +-- \*\* - WARNING \*\* - this uses quite a high tolerance for +-- floating point equality. +--+--------------------------------------------------------------------------------++module Wumpus.Basic.Geometry.Intersection+  ( ++    LineSegment+  , interLineLine+  , interLinesegLineseg+  , interLinesegLine+  , interCurveLine++  , findIntersect+  , makePlane+  , rectangleLineSegments+  , polygonLineSegments+++  ) +  where++import Wumpus.Basic.Geometry.Base++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space++++-- Potentially lines hould be a new datatype.+++-- | 'interLineLine' : @ line1 * line2 -> Maybe Point @+-- +-- Find the intersection of two lines, if there is one. +--+-- Lines are infinite they are represented by points on them, +-- they are not line segments.+--+-- An answer of @Nothing@ may indicate wither the lines coincide+-- or the are parallel.+--+interLineLine :: Fractional u +              => (Point2 u, Point2 u) -> (Point2 u, Point2 u) +              -> Maybe (Point2 u)+interLineLine (p1,p2) (q1,q2) = +    if det_co == 0 then Nothing +                   else Just $ P2 (det_xm / det_co) (det_ym / det_co)+  where+    -- Ax + By + C = 0+    LineEquation a1 b1 c1 = lineEquation p1 p2+    LineEquation a2 b2 c2 = lineEquation q1 q2++    coeffM                = M2'2 a1 b1  a2 b2+    det_co                = det2'2 coeffM++    xM                    = M2'2  (negate c1) b1  (negate c2) b2+    det_xm                = det2'2 xM++    yM                    = M2'2  a1 (negate c1) a2 (negate c2)+    det_ym                = det2'2 yM++++-- | 'interLinesegLineseg' : @ line_segment1 * line_segment2 -> Maybe Point @+-- +-- Find the intersection of two line segments, if there is one. +--+-- An answer of @Nothing@ indicates that the line segments +-- coincide, or that there is no intersection.+--+interLinesegLineseg :: (Fractional u, Ord u, FromPtSize u)+                    => LineSegment u -> LineSegment u -> Maybe (Point2 u)+interLinesegLineseg a@(LineSegment p q) b@(LineSegment s t) = +    interLineLine (p,q) (s,t) >>= segcheck+  where+    segcheck = mbCheck (\pt -> withinPoints pt a && withinPoints pt b)+ ++-- | 'interLinesegLine' : @ line_segment * line -> Maybe Point @+-- +-- Find the intersection of a line and a line segment, if there +-- is one. +--+-- An answer of @Nothing@ indicates that the the line and line+-- segment coincide, or that there is no intersection.+--+interLinesegLine :: (Fractional u, Ord u, FromPtSize u)+                 => LineSegment u -> (Point2 u, Point2 u) -> Maybe (Point2 u)+interLinesegLine a@(LineSegment p q) line = +    interLineLine (p,q) line >>= segcheck+  where+    segcheck = mbCheck (\pt -> withinPoints pt a)+++mbCheck :: (a -> Bool) -> a -> Maybe a+mbCheck test a = if test a then Just a else Nothing++-- | Check the point is \"within\" the span of the line.+--+-- Note - this function is to be used \*after\* an intersection+-- has been found. Hence it is not export.+--+withinPoints :: (Ord u, FromPtSize u) => Point2 u -> LineSegment u -> Bool+withinPoints (P2 x y) (LineSegment (P2 x0 y0) (P2 x1 y1)) =  +    between x (ordpair x0 x1) && between y (ordpair y0 y1)+  where+    ordpair a b     = (min a b, max a b)+    between a (s,t) = (s `tGT` a) && (a `tGT` t)++    tGT a b         = a < b || abs (a-b) < tolerance++-- | Note - its important to use tolerance for the @withPoints@ +-- function.+--+tolerance :: FromPtSize u => u+tolerance = fromPtSize 0.01+++++++--------------------------------------------------------------------------------+-- intersection of line and Bezier curve++interCurveLine :: (Floating u , Ord u, FromPtSize u)+               => BezierCurve u -> (Point2 u, Point2 u) -> Maybe (Point2 u)+interCurveLine c0 (p,q) = step c0+  where+    eqline  = lineEquation p q+    step c  = case cut c eqline of+                Left pt     -> Just pt      -- cut at start or end+                Right False -> Nothing+                Right True  -> let (a,b) = subdivide c+                               in case step a of+                                   Just pt -> Just pt+                                   Nothing -> step b+ +-- | Is the curve cut by the line? +--+-- The curve might cut at the start or end points - which is good+-- as it saves performing a subdivision. But make the return type+-- a bit involved.+--+cut :: (Floating u , Ord u, FromPtSize u)+    => BezierCurve u -> LineEquation u -> Either (Point2 u) Bool+cut (BezierCurve p0 p1 p2 p3) line = +    if d0 `tEQ` 0 then Left p0 else+    if d3 `tEQ` 0 then Left p3 else+    let ds = [d0,d1,d2,d3] in Right $ not $ all pve ds || all nve ds+  where+    tEQ = \a b -> abs (a-b) < tolerance+    pve = \a -> a > tolerance+    nve = \a -> a < (negate tolerance)+    d0  = pointLineDistance p0 line +    d1  = pointLineDistance p1 line +    d2  = pointLineDistance p2 line +    d3  = pointLineDistance p3 line ++++    +++--------------------------------------------------------------------------------+-- Intersection of shape boundaries...++++-- | 'findIntersect' :: @ radial_origin * theta * [line_segment] -> Maybe Point @+--+-- Find the first intersection of a line through @radial_origin@ +-- at angle @theta@ and the supplied line segments, if there +-- is one. +--+findIntersect :: (Floating u, Real u, Ord u, FromPtSize u)+               => Point2 u -> Radian -> [LineSegment u] +               -> Maybe (Point2 u)+findIntersect radial_ogin ang = step +  where+    plane       = makePlane radial_ogin ang+    step []     = Nothing+    step (x:xs) = case interLinesegLine x plane of +                     Just pt | quadrantCheck ang radial_ogin pt -> Just pt+                     _       -> step xs+++-- | The tolerance on Radian equality should be acceptable...+--+quadrantCheck :: (Real u, Floating u) +              => Radian -> Point2 u -> Point2 u -> Bool+quadrantCheck theta ctr pt = theta == lineAngle ctr pt++++++-- | 'makePlane' : @ point * ang -> Line @+--+-- Make an infinite line \/ plane passing through the supplied +-- with elevation @ang@.+--+makePlane :: Floating u => Point2 u -> Radian -> (Point2 u, Point2 u)+makePlane radial_ogin ang = (radial_ogin, radial_ogin .+^ avec ang 100)++
+ src/Wumpus/Basic/Geometry/Paths.hs view
@@ -0,0 +1,138 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Drawing.Basic.Paths+-- Copyright   :  (c) Stephen Tetley 2010-2011+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Paths for /elementary/ shapes - rectangles...+-- +-- \*\* - WARNING \*\* - half baked. +--+--------------------------------------------------------------------------------++module Wumpus.Basic.Geometry.Paths+  ( +    LocCoordPath+  , coordinatePrimPath++  , rectangleCoordPath+  , diamondCoordPath+  , polygonCoordPath+  , isoscelesTriangleCoordPath+  , isoscelesTrianglePoints+  , equilateralTriangleCoordPath+  , equilateralTrianglePoints+  ) +  where++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space+++import Data.List ( unfoldr )+++-- | A functional type from /initial point/ to point list.+--+type LocCoordPath u = Point2 u -> [Point2 u]+++-- Note - extraction needs a naming scheme - extractFROM or +-- extractTO? - in either case this might be queuing up +-- name-clash problems.+--+-- The Path data type will also need a similar function...+--+ +coordinatePrimPath :: Num u => Point2 u -> LocCoordPath u -> PrimPath u+coordinatePrimPath pt fn = go (fn pt)+  where+    go ps@(_:_) = vertexPath ps+    go []       = emptyPath pt        -- fallback+++-- NOTE - These functions need changing to generate LocCoordPaths...++-- | Supplied point is /bottom-left/, subsequenct points are +-- counter-clockise so [ bl, br, tr, tl ] .+--+rectangleCoordPath :: Num u => u -> u -> LocCoordPath u+rectangleCoordPath w h bl = [ bl, br, tr, tl ]+  where+    br = bl .+^ hvec w+    tr = br .+^ vvec h+    tl = bl .+^ vvec h ++++-- | 'diamondPath' : @ half_width * half_height * center_point -> PrimPath @+--+diamondCoordPath :: Num u => u -> u -> LocCoordPath u+diamondCoordPath hw hh ctr = [ s,e,n,w ]+  where+    s     = ctr .+^ vvec (-hh)+    e     = ctr .+^ hvec hw+    n     = ctr .+^ vvec hh+    w     = ctr .+^ hvec (-hw)+    ++-- | 'polygonCoordPath' : @ num_points * radius * center -> [point] @ +--+polygonCoordPath :: Floating u => Int -> u -> LocCoordPath u+polygonCoordPath n radius ctr = unfoldr phi (0,(pi*0.5))+  where+    theta = (pi*2) / fromIntegral n+    +    phi (i,ang) | i < n     = Just (ctr .+^ avec ang radius, (i+1,ang+theta))+                | otherwise = Nothing++++-- | @isocelesTriangle bw h pt@+--+-- Supplied point is the centriod of the triangle. This has a +-- nicer visual balance than using half-height.+--+isoscelesTriangleCoordPath :: Floating u => u -> u -> LocCoordPath u+isoscelesTriangleCoordPath bw h ctr = [bl,br,top]+  where+    (bl,br,top) = isoscelesTrianglePoints bw h ctr+++-- | @isocelesTriangle bw h pt@+--+-- Supplied point is the centriod of the triangle. This has a +-- nicer visual balance than using half-height.+--+isoscelesTrianglePoints :: Floating u +                        => u -> u -> Point2 u -> (Point2 u, Point2 u, Point2 u)+isoscelesTrianglePoints bw h ctr = (bl, br, top) +  where+    hw         = 0.5*bw +    theta      = atan $ h / hw+    centroid_h = hw * tan (0.5*theta)+    top        = ctr .+^ vvec (h - centroid_h)+    br         = ctr .+^ V2   hw  (-centroid_h)+    bl         = ctr .+^ V2 (-hw) (-centroid_h)+++-- | @ side_length * ctr -> [Points] @+--+equilateralTriangleCoordPath :: Floating u => u -> LocCoordPath u+equilateralTriangleCoordPath sl ctr = [bl, br, top] +  where+    (bl,br,top) = equilateralTrianglePoints sl ctr++equilateralTrianglePoints :: Floating u +                          => u -> Point2 u -> (Point2 u, Point2 u, Point2 u)+equilateralTrianglePoints sl = isoscelesTrianglePoints sl h+  where+    h = sl * sin (pi/3)+
+ src/Wumpus/Basic/Geometry/Quadrant.hs view
@@ -0,0 +1,306 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Basic.Geometry.Quadrant+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Quadrants and trigonometric calculations.+-- +-- \*\* - WARNING \*\* - in progress. +--+--------------------------------------------------------------------------------++module Wumpus.Basic.Geometry.Quadrant+  ( +    Quadrant(..)++  , quadrant+  , qiModulo++  , rectRadialVector+  , rectangleQI++  , diamondRadialVector+  , triangleRadialVector+  , triangleQI+  , rightTrapezoidQI+  +  , rightTrapeziumBaseWidth++  ) +  where++import Wumpus.Core                              -- package: wumpus-core++data Quadrant = QUAD_NE | QUAD_NW | QUAD_SW | QUAD_SE+  deriving (Enum,Eq,Ord,Show)++-- | 'quadrant' : @ ang -> Quadrant @+--+-- Get the quadrant of an angle.+--+quadrant :: Radian -> Quadrant+quadrant = fn . circularModulo+  where+    fn a | a < 0.5*pi   = QUAD_NE+         | a < pi       = QUAD_NW+         | a < 1.5*pi   = QUAD_SW+         | otherwise    = QUAD_SE+++-- | 'qiModulo' : @ ang -> Radian @+-- +-- Modulo an angle so it lies in quadrant I (north east), +-- i.e. modulo into the range @0..(pi/2)@.+--+qiModulo :: Radian -> Radian +qiModulo r = d2r $ dec + (fromIntegral $ i `mod` 90)+  where+    i       :: Integer+    dec     :: Double+    (i,dec) = properFraction $ r2d r+++--------------------------------------------------------------------------------++negateX :: Num u => Vec2 u -> Vec2 u+negateX (V2 x y) = V2 (-x) y++negateY :: Num u => Vec2 u -> Vec2 u+negateY (V2 x y) = V2 x (-y)++negateXY :: Num u => Vec2 u -> Vec2 u+negateXY (V2 x y) = V2 (-x) (-y)+++-- | 'rectRadialVector' : @ half_width * half_height * ang -> Vec @+--+-- Find where a radial line extended from (0,0) with the elevation+-- @ang@ intersects with an enclosing rectangle. The rectangle is +-- centered at (0,0).+-- +-- Internally the calculation is made in quadrant I (north east),+-- symmetry is used to translate result to the other quadrants.+--+rectRadialVector :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u+rectRadialVector hw hh ang = fn $ circularModulo ang+  where+    fn a | a < 0.5*pi   = rectangleQI hw hh a+         | a < pi       = negateX  $ rectangleQI hw hh (pi - a)+         | a < 1.5*pi   = negateXY $ rectangleQI hw hh (a - pi) +         | otherwise    = negateY  $ rectangleQI hw hh (2*pi - a)+++-- | 'rectangleQI' : @ width * height * ang -> Vec @+--+-- Find where a line from (0,0) in direction @ang@ intersects the +-- top or right side of a rectangle in QI (left side is the +-- y-axis, bottom is the x-axis).  +--+-- > ang must be in the @range 0 < ang <= 90 deg@.+-- >+-- > width and height must be positive.+--+rectangleQI :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u    +rectangleQI w h ang+    | ang < theta  = let y = w * fromRadian (tan ang) in V2 w y+    | otherwise    = let x = h / fromRadian (tan ang) in V2 x h+  where+    theta               = toRadian $ atan (h/w)+++-- | 'diamondRadialVector' : @ half_width * half_height * ang -> Vec @+--+-- Find where a radial line extended from (0,0) with the elevation+-- @ang@ intersects with an enclosing diamond. The diamond is +-- centered at (0,0).+-- +-- Internally the calculation is made in quadrant I (north east),+-- symmetry is used to translate result to the other quadrants.+--+diamondRadialVector :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u+diamondRadialVector hw hh ang = fn $ circularModulo ang+  where+    fn a | a < 0.5*pi   = triangleQI hw hh a+         | a < pi       = negateX  $ triangleQI hw hh (pi - a)+         | a < 1.5*pi   = negateXY $ triangleQI hw hh (a - pi) +         | otherwise    = negateY  $ triangleQI hw hh (2*pi - a)+++-- | 'triangleRadialVector' : @ half_base_width * height_minor * +--        height_minor * ang -> Vec @+--+-- Find where a radial line extended from (0,0) with the elevation+-- @ang@ intersects with an enclosing triangle. The triangle has +-- the centroid at (0,0), so solutions in quadrants I and II are +-- intersections with a simple line. Intersections in quadrants+-- III and IV can intersect either the respective side or the +-- base.+-- +--+triangleRadialVector :: (Real u, Floating u) => u -> u -> u -> Radian -> Vec2 u+triangleRadialVector hbw hminor hmajor ang = fn $ circularModulo ang+  where+    fn a | a < 0.5*pi   = triangleQI major_width hmajor a+         | a < pi       = negateX  $ triangleQI major_width hmajor (pi - a)+         | a < 1.5*pi   = negateXY $ rightTrapezoidQI hbw hminor base_rang (a - pi) +         | otherwise    = negateY  $ rightTrapezoidQI hbw hminor base_rang (2*pi - a)++    height              = hmajor + hminor+    base_rang           = toRadian $ atan (height / hbw)+    major_width         = hmajor / (fromRadian $ tan base_rang)+++-- | 'triangleQI' : @ width * height * ang -> Vec @+--+-- Find where a line from (0,0) with elevation @ang@ intersects +-- the hypotenuse a right triangle in QI (the legs of the triangle +-- take the x and y-axes).  +--+-- > ang must be in the @range 0 < ang <= 90@.+-- >+-- > width and height must be positive.+--+triangleQI :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u+triangleQI w h ang = avec ang dist+  where+    base_ang = atan (h / w)+    apex     = pi - (base_ang + fromRadian ang)+    dist     = sin base_ang * (w / sin apex)++++-- | 'rightTrapezoidQI' : @ top_width * height * top_right_ang -> Vec @+--+-- Find where a line from (0,0) with elevation @ang@ intersects +-- the either the lines A_B or B_D in a right trapezoid in QI. +-- +-- The right trapezoid has a variable right side. Left side is the+-- y-axis (C_A), bottom side is the x-axis (C_D), top side is +-- parallel to the x-axis (A_B).+--+-- >  A   B+-- >  -----+-- >  |    \+-- >  |     \     +-- >  -------+-- >  C      D+--+-- >  A      B+-- >  -------+-- >  |     /+-- >  |    /     +-- >  -----+-- >  C   D+--+-- > ang must be in the range 0 < ang <= 90.+-- >+-- > top_width and height must be positive.+--+rightTrapezoidQI :: (Real u, Floating u) +                 => u -> u -> Radian -> Radian -> Vec2 u+rightTrapezoidQI tw h top_rang ang = +    if w0 <= tw then dv else avec ang minor_dist+  where+    -- dist is hypotenuse of a right triangle1+    dist         = h / (fromRadian $ sin ang)+    +    -- potentially this vector is *too long*.+    dv@(V2 w0 _) = avec ang dist++    -- this is dist *cut short* because it intersects the right+    -- side rather than the top+    minor_dist   = triangleLeftSide base_width ang lr_ang+    +    lr_ang       = pi - top_rang++    base_width   = rightTrapeziumBaseWidth tw h top_rang+++-- Legend:+-- +-- > @top_rang@ is A/B\C.+-- >+-- > @ang@ is B/C\D.+-- > +-- > w (width) is A_B.+--+-- > h (height) is C_A.+-- +-- >  A     B+-- >  ------ +-- >  |    / .+-- >  |   /   .+-- >  |  /     .+-- >  | /       .     +-- >  |/..........+-- >  C          D+--+-- Synthetically:+--+-- > Right triangle 1 is ABC.+-- >+-- > @dist@ is C_B.+-- >+-- > @base_width@ is C_D.+-- >+-- > @lr_ang is C/D\B. +--   +++-- | 'traingleLeftSide' : @ base_width * left_ang * right_ang -> Length @+--+-- >  +-- >        C   +-- >       /\+-- >      /  \+-- >     /    \+-- >    /      \    +-- >   /________\+-- >  A          B+-- >+-- +-- > Calculate A_C given side A_B, angle C/A\B and angle A/B\C.+--+triangleLeftSide :: Fractional u => u -> Radian -> Radian -> u+triangleLeftSide base_width lang rang =+    (fromRadian $ sin rang) / factor +  where+    apex   = pi - (lang + rang)+    factor = (fromRadian $ sin apex) / base_width+++-- | 'rightTrapeziumBaseWidth' : @ top_width * height * top_right_ang -> Length @+-- +-- Find the length of the line C_D:+--+-- >  A   B+-- >  -----+-- >  |    \+-- >  |     \     +-- >  -------+-- >  C      D+--+-- >  A      B+-- >  -------+-- >  |     /+-- >  |    /     +-- >  -----+-- >  C   D+--+-- +rightTrapeziumBaseWidth :: Fractional u => u -> u -> Radian -> u+rightTrapeziumBaseWidth tw h tr_ang +    | tr_ang < half_pi = tw - shorten+    | tr_ang > half_pi = tw + extend+    | otherwise        = tw+  where+    half_pi  = 0.5*pi+    shorten  = h / fromRadian (tan tr_ang)+    extend   = let lr_ang = pi - tr_ang in h / fromRadian (tan lr_ang)
src/Wumpus/Basic/Kernel.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Basic.Kernel--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  stephen.tetley@gmail.com@@ -31,7 +31,10 @@   , module Wumpus.Basic.Kernel.Objects.Bounded   , module Wumpus.Basic.Kernel.Objects.Connector   , module Wumpus.Basic.Kernel.Objects.CtxPicture+  , module Wumpus.Basic.Kernel.Objects.Displacement+  , module Wumpus.Basic.Kernel.Objects.DrawingPrimitives   , module Wumpus.Basic.Kernel.Objects.Graphic+  , module Wumpus.Basic.Kernel.Objects.PosImage   , module Wumpus.Basic.Kernel.Objects.TraceDrawing   ) where @@ -49,5 +52,8 @@ import Wumpus.Basic.Kernel.Objects.Bounded import Wumpus.Basic.Kernel.Objects.Connector import Wumpus.Basic.Kernel.Objects.CtxPicture+import Wumpus.Basic.Kernel.Objects.Displacement+import Wumpus.Basic.Kernel.Objects.DrawingPrimitives import Wumpus.Basic.Kernel.Objects.Graphic+import Wumpus.Basic.Kernel.Objects.PosImage import Wumpus.Basic.Kernel.Objects.TraceDrawing
src/Wumpus/Basic/Kernel/Base/Anchors.hs view
@@ -17,6 +17,12 @@ -- anchors on node shapes to get the start and end points for  -- connectors in a network (graph) diagram. -- +-- \*\* WARNING \*\* - The API here needs some thought as to a+-- good balance of the type classes - in a nutshell \"are corners +-- better than cardinals\". Originally I tried to follow how I +-- understand the TikZ anchors to work, but this is perhaps not +-- ideal for dividing into type-classes.+-- --------------------------------------------------------------------------------  module Wumpus.Basic.Kernel.Base.Anchors@@ -24,19 +30,17 @@    -- * Anchors     CenterAnchor(..)+  , ApexAnchor(..)   , CardinalAnchor(..)   , CardinalAnchor2(..)   , RadialAnchor(..)+  , TopCornerAnchor(..)+  , BottomCornerAnchor(..)+  , SideMidpointAnchor(..) +   -- * Extended anchor points-  , northwards-  , southwards-  , eastwards-  , westwards-  , northeastwards-  , southeastwards-  , southwestwards-  , northwestwards+  , projectAnchor    , radialConnectorPoints @@ -52,6 +56,13 @@ class CenterAnchor t where   center :: DUnit t ~ u => t -> Point2 u ++-- | Apex of an object.+--+class ApexAnchor t where+  apex :: DUnit t ~ u => t -> Point2 u++ -- | Cardinal (compass) positions on an object.  --  -- Note - in TikZ cardinal anchors are not necessarily at the@@ -67,13 +78,23 @@   east  :: DUnit t ~ u => t -> Point2 u   west  :: DUnit t ~ u => t -> Point2 u +--+-- Note - a design change is probably in order where the cardinals +-- should /always/ represent their true cardinal position.+--+-- If this change is made, it is worthwhile having cardinals as+-- classes (rather than making them derived operations on +-- RadialAnchor) as classes allow for more efficient +-- implementations usually by trigonometry.+--  + -- | Secondary group of cardinal (compass) positions on an object.  --  -- It seems possible that for some objects defining the primary -- compass points (north, south,...) will be straight-forward  -- whereas defining the secondary compass points may be --- problemmatic, hence the compass points are split into two +-- problematic, hence the compass points are split into two  -- classes. -- class CardinalAnchor2 t where@@ -92,108 +113,71 @@   radialAnchor :: DUnit t ~ u => Radian -> t -> Point2 u  ---extendPtDist :: (Real u, Floating u) => u -> Point2 u -> Point2 u -> Point2 u-extendPtDist d p1 p2 = let v   = pvec p1 p2-                           ang = vdirection v-                           len = vlength v-                       in p1 .+^ avec ang (len+d)----- | 'northwards' : @ dist * object -> Point @--- --- Project the anchor along a line from the center that goes --- through the north anchor. ------ If the distance is zero the answer with be the north anchor.------ If the distance is negative the answer within the object before --- the north anchor.+-- | Anchors at the top left and right corners of a shape. ----- If the distance is positive the anchor outside the object.+-- For some shapes (Rectangle) the TikZ convention appears to be+-- have cardinals as the corner anchors, but this doesn\'t seem+-- to be uniform. Wumpus will need to reconsider anchors at some +-- point... ---northwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor t-              , u ~ DUnit t ) -           => u -> t -> Point2 u-northwards u a = extendPtDist u (center a) (north a)+class TopCornerAnchor t where+  topLeftCorner  :: DUnit t ~ u => t -> Point2 u+  topRightCorner :: DUnit t ~ u => t -> Point2 u  --- | 'southwards' : @ dist * object -> Point @--- --- Variant of the function 'northwards', but projecting the line --- southwards from the center of the object.+-- | Anchors at the bottom left and right corners of a shape. ---southwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor t-              , u ~ DUnit t ) -           => u -> t -> Point2 u-southwards u a = extendPtDist u (center a) (south a)+class BottomCornerAnchor t where+  bottomLeftCorner  :: DUnit t ~ u => t -> Point2 u+  bottomRightCorner :: DUnit t ~ u => t -> Point2 u  --- | 'eastwards' : @ dist * object -> Point @+-- | Anchors in the center of a side. -- --- Variant of the function 'northwards', but projecting the line --- eastwards from the center of the object.----eastwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor t-             , u ~ DUnit t ) -          => u -> t -> Point2 u-eastwards u a = extendPtDist u (center a) (east a)----- | 'westwards' : @ dist * object -> Point @+-- Sides are addressable by index. Following TikZ, side 1 is +-- expected to be the top of the shape. If the shape has an apex +-- instead of a side then side 1 is expected to be the first side +-- left of the apex. -- --- Variant of the function 'northwards', but projecting the line --- westwards from the center of the object.+-- Implementations are also expected to modulo the side number, +-- rather than throw an out-of-bounds error. ---westwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor t-             , u ~ DUnit t ) -          => u -> t -> Point2 u-westwards u a = extendPtDist u (center a) (west a)+class SideMidpointAnchor t where+  sideMidpoint :: DUnit t ~ u => Int -> t -> Point2 u  --- | 'northeastwards' : @ dist * object -> Point @--- --- Variant of the function 'northwards', but projecting the line --- northeastwards from the center of the object.----northeastwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor2 t-                  , u ~ DUnit t ) -               => u -> t -> Point2 u-northeastwards u a = extendPtDist u (center a) (northeast a) +-------------------------------------------------------------------------------- --- | 'southeastwards' : @ dist * object -> Point @+-- | 'projectAnchor' : @ extract_func * dist * object -> Point @ -- --- Variant of the function 'northwards', but projecting the line --- southeastwards from the center of the object.----southeastwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor2 t-                  , u ~ DUnit t ) -               => u -> t -> Point2 u-southeastwards u a = extendPtDist u (center a) (southeast a)----- | 'southwestwards' : @ dist * object -> Point @+-- Derive a anchor by projecting a line from the center of an +-- object through the intermediate anchor (produced by the +-- extraction function). The final answer point is located along+-- the projected line at the supplied distance @dist@. -- --- Variant of the function 'northwards', but projecting the line --- southwestwards from the center of the object.+-- E.g. take the north of a rectangle and project it 10 units +-- further on:+--  +-- > projectAnchor north 10 my_rect ---southwestwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor2 t-                  , u ~ DUnit t ) -               => u -> t -> Point2 u-southwestwards u a = extendPtDist u (center a) (southwest a)----- | 'northwestwards' : @ dist * object -> Point @--- --- Variant of the function 'northwards', but projecting the line --- northwestwards from the center of the object.+-- If the distance is zero the answer with be whatever point the +-- the extraction function produces. ---northwestwards :: ( Real u, Floating u, CenterAnchor t, CardinalAnchor2 t-                  , u ~ DUnit t ) -               => u -> t -> Point2 u-northwestwards u a = extendPtDist u (center a) (northwest a)+-- If the distance is negative the answer will be along the +-- projection line, between the center and the intermediate anchor.+--+-- If the distance is positive the anchor will be extend outwards +-- from the intermediate anchor.+--+projectAnchor :: (Real u, Floating u, u ~ DUnit t, CenterAnchor t) +              => (t -> Point2 u) -> u -> t -> Point2 u+projectAnchor f d a = p1 .+^ (avec ang d)+  where+    p1  = f a+    v   = pvec (center a) p1+    ang = vdirection v+        --------------------------------------------------------------------------------
src/Wumpus/Basic/Kernel/Base/BaseDefs.hs view
@@ -35,23 +35,15 @@   , HAlign(..)   , VAlign(..)   +  -- * Cardinal (compass) positions+  , Cardinal(..)+   -- * Advance vector   , AdvanceVec   , advanceH   , advanceV -  -- * Moving points-  , PointDisplace-  , displace-  , displaceVec-  , displaceH-  , displaceV -  , ThetaPointDisplace-  , displaceParallel-  , displacePerpendicular--   -- * Monadic drawing   , MonUnit @@ -61,7 +53,7 @@  import Wumpus.Core                              -- package: wumpus-core -import Data.AffineSpace                         -- package: vector-space+import Data.VectorSpace                         -- package: vector-space  infixr 6 `oplus` @@ -95,15 +87,26 @@   a `oplus` b = primGroup [a,b]  instance (OPlus a, OPlus b) => OPlus (a,b) where-  (a,b) `oplus` (a',b') = (a `oplus` a', b `oplus` b')+  (a,b) `oplus` (m,n) = (a `oplus` m, b `oplus` n) +instance (OPlus a, OPlus b, OPlus c) => OPlus (a,b,c) where+  (a,b,c) `oplus` (m,n,o) = (a `oplus` m, b `oplus` n, c `oplus` o) +instance (OPlus a, OPlus b, OPlus c, OPlus d) => OPlus (a,b,c,d) where+  (a,b,c,d) `oplus` (m,n,o,p) = (oplus a m, oplus b n, oplus c o, oplus d p)+++ instance OPlus a => OPlus (r -> a) where   f `oplus` g = \x -> f x `oplus` g x  -- The functional instance (r -> a) also covers (r1 -> r2 -> a), -- (r1 -> r2 -> r3 -> a) etc. +instance Num u => OPlus (Vec2 u) where +  oplus = (^+^)++ --------------------------------------------------------------------------------  -- | A Bifunctor class.@@ -154,7 +157,16 @@ data VAlign = VLeft | VCenter | VRight   deriving (Enum,Eq,Ord,Show) +-------------------------------------------------------------------------------- +-- Compass positions++-- | An enumeratied type representing the compass positions.+--+data Cardinal = NORTH | NORTH_EAST | EAST | SOUTH_EAST +              | SOUTH | SOUTH_WEST | WEST | NORTH_WEST+   deriving (Enum,Eq,Ord,Show) + --------------------------------------------------------------------------------  -- | Advance vectors provide an idiom for drawing consecutive@@ -181,85 +193,6 @@ -- advanceV :: AdvanceVec u -> u advanceV (V2 _ h)  = h------------------------------------------------------------------------------------- Displacing points---- | 'PointDisplace' is a type representing functions --- @from Point to Point@.------ It is especially useful for building composite graphics where --- one part of the graphic is drawn from a different start point --- to the other part.----type PointDisplace u = Point2 u -> Point2 u---- | 'displace' : @ x -> y -> PointDisplace @------ Build a combinator to move @Points@ by the supplied @x@ and --- @y@ distances.----displace :: Num u => u -> u -> PointDisplace u-displace dx dy (P2 x y) = P2 (x+dx) (y+dy)----- | 'displaceV' : @ (V2 x y) -> PointDisplace @--- --- Version of 'displace' where the displacement is supplied as--- a vector rather than two parameters.--- -displaceVec :: Num u => Vec2 u -> PointDisplace u-displaceVec (V2 dx dy) (P2 x y) = P2 (x+dx) (y+dy)----- | 'displaceH' : @ x -> PointDisplace @--- --- Build a combinator to move @Points@ by horizontally the --- supplied @x@ distance.----displaceH :: Num u => u -> PointDisplace u-displaceH dx (P2 x y) = P2 (x+dx) y---- | 'displaceV' : @ y -> PointDisplace @--- --- Build a combinator to move @Points@ vertically by the supplied --- @y@ distance.----displaceV :: Num u => u -> PointDisplace u-displaceV dy (P2 x y) = P2 x (y+dy)----- | 'ThetaPointDisplace' is a type representing functions --- @from Radian * Point to Point@.------ It is useful for building arrowheads which are constructed --- with an implicit angle representing the direction of the line --- at the arrow tip.----type ThetaPointDisplace u = Radian -> PointDisplace u------ | 'displaceParallel' : @ dist -> ThetaPointDisplace @--- --- Build a combinator to move @Points@ in parallel to the --- direction of the implicit angle by the supplied distance --- @dist@. ----displaceParallel :: Floating u => u -> ThetaPointDisplace u-displaceParallel d = \theta pt -> pt .+^ avec (circularModulo theta) d----- | 'displaceParallel' : @ dist -> ThetaPointDisplace @--- --- Build a combinator to move @Points@ perpendicular to the --- direction of the implicit angle by the supplied distance --- @dist@. ----displacePerpendicular :: Floating u => u -> ThetaPointDisplace u-displacePerpendicular d = -    \theta pt -> pt .+^ avec (circularModulo $ theta + (0.5*pi)) d-   
src/Wumpus/Basic/Kernel/Base/GlyphMetrics.hs view
@@ -66,9 +66,10 @@       { get_bounding_box  :: forall u. FromPtSize u => PtSize -> BoundingBox u        , get_cw_table      :: forall u. FromPtSize u => PtSize -> CharWidthTable u       , get_cap_height    :: forall u. FromPtSize u => PtSize -> u+      , get_descender     :: forall u. FromPtSize u => PtSize -> u       } --- | 'MetricsOps' tfor a particular named font.+-- | 'MetricsOps' for a particular named font. --  data FontMetricsOps = FontMetricsOps FontName MetricsOps @@ -101,17 +102,19 @@     { get_bounding_box  = \sz -> BBox (lowerLeft sz) (upperRight sz)     , get_cw_table      = \sz _ -> hvec (upscale sz width_vec)      , get_cap_height    = \sz -> upscale sz cap_height+    , get_descender     = \sz -> upscale sz descender     }   where-    llx           = (-23)  / 1000-    lly           = (-250) / 1000-    urx           = 715    / 1000-    ury           = 805    / 1000-    width_vec     = 600    / 1000-    cap_height    = 562    / 1000+    llx             = (-23)  / 1000+    lly             = (-250) / 1000+    urx             = 715    / 1000+    ury             = 805    / 1000+    width_vec       = 600    / 1000+    cap_height      = 562    / 1000+    descender       = (-157) / 1000 -    upscale sz d  = fromPtSize $ sz * d-    lowerLeft sz  = P2 (upscale sz llx) (upscale sz lly) -    upperRight sz = P2 (upscale sz urx) (upscale sz ury) +    upscale sz d    = fromPtSize $ sz * d+    lowerLeft sz    = P2 (upscale sz llx) (upscale sz lly) +    upperRight sz   = P2 (upscale sz urx) (upscale sz ury)   
src/Wumpus/Basic/Kernel/Base/QueryDC.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Basic.Kernel.Base.QueryDC--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>@@ -12,6 +12,10 @@ -- -- Querying the Drawing Context. --+-- \*\* WARNING \*\* - parts of this module especially the +-- mono-space glyph metrics need a re-think and will change or be +-- dropped.+-- --------------------------------------------------------------------------------  module Wumpus.Basic.Kernel.Base.QueryDC@@ -43,10 +47,9 @@    -- * Glyph metrics   , glyphBoundingBox-  , glyphHeightRange-  , glyphHeight   , glyphCapHeight-+  , glyphDescender+  , glyphVerticalSpan   , cwLookupTable    -- * Default monospace metrics@@ -108,8 +111,7 @@   --- | Vertical distance between baselines of consecutive text --- lines.+-- | Size of the round corner factor. -- getRoundCornerSize :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u getRoundCornerSize = (\factor -> (realToFrac factor) * fromPtSize 1)@@ -117,9 +119,11 @@   --- | Vertical distance between baselines of consecutive text --- lines.+-- | Get the (x,y) margin around text. --+-- Note - not all text operations in Wumpus are drawn with text +-- margin. +--  getTextMargin :: (DrawingCtxM m, Fractional u, FromPtSize u) => m (u,u) getTextMargin = (\(TextMargin xsep ysep) -> (fn xsep, fn ysep))                     <$> asksDC text_margin@@ -174,23 +178,32 @@ glyphQuery :: DrawingCtxM m => (MetricsOps -> PtSize -> u) -> m u glyphQuery fn = (\ctx -> withFontMetrics fn ctx) <$> askDC +-- | Get the font bounding box - this is the maximum boundary of +-- the glyphs in the font. The span of the height is expected to +-- be bigger than the cap_height plus descender depth.+-- glyphBoundingBox :: (FromPtSize u, DrawingCtxM m) => m (BoundingBox u) glyphBoundingBox = glyphQuery get_bounding_box  -glyphHeightRange :: (FromPtSize u, DrawingCtxM m) => m (u,u)-glyphHeightRange = fn <$> glyphBoundingBox-  where-    fn (BBox (P2 _ ymin) (P2 _ ymax)) = (ymin,ymax)  -glyphHeight :: (FromPtSize u, DrawingCtxM m) => m u-glyphHeight = (\(ymax,ymin) -> ymax - ymin) <$> glyphHeightRange - glyphCapHeight :: (FromPtSize u, DrawingCtxM m) => m u glyphCapHeight = glyphQuery get_cap_height +-- | Note - descender is expected to be negative.+--+glyphDescender :: (FromPtSize u, DrawingCtxM m) => m u+glyphDescender = glyphQuery get_descender++-- | This is the distance from cap_height to descender.+--+glyphVerticalSpan :: (FromPtSize u, DrawingCtxM m) => m u+glyphVerticalSpan = +    (\ch dd -> ch - dd) <$> glyphCapHeight <*> glyphDescender++ cwLookupTable :: (FromPtSize u, DrawingCtxM m) => m (CharWidthTable u) cwLookupTable = glyphQuery get_cw_table @@ -271,11 +284,14 @@     -- no longer quite works...    +{-# DEPRECATED monoDefaultPadding "Needs a rethink" #-}  -- | The default padding is half of the /char width/. -- monoDefaultPadding :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u monoDefaultPadding = (0.5*) <$> monoCharWidth++  -- | Vector from baseline left to center --
src/Wumpus/Basic/Kernel/Base/UpdateDC.hs view
@@ -58,6 +58,7 @@   , fontFace    -- * Font / mark drawing size+  , scalesize   , doublesize   , halfsize @@ -79,6 +80,7 @@  import Control.Applicative +import Data.Ratio  -------------------------------------------------------------------------------- @@ -214,12 +216,16 @@  -------------------------------------------------------------------------------- +scalesize           :: Ratio Int -> DrawingContextF+scalesize r         = let (n,d) = (numerator r, denominator r)+                      in (\s sz -> fontSize (n * sz `div` d) s) +                           <*> (font_size . font_props)+ -- | Set the font size to double the current size, note the font -- size also controls the size of dots, arrowsheads etc. --  doublesize          :: DrawingContextF-doublesize          = (\s sz -> fontSize (sz*2) s) -                        <*> (font_size . font_props)+doublesize          = scalesize 2    -- | Set the font size to half the current size, note the font@@ -229,8 +235,7 @@ -- 15pt type is 7pt. --  halfsize            :: DrawingContextF-halfsize            = (\s sz -> fontSize (sz `div` 2) s) -                        <*> (font_size . font_props)+halfsize            = scalesize (1%2)   --------------------------------------------------------------------------------
src/Wumpus/Basic/Kernel/Objects/AdvanceGraphic.hs view
@@ -13,7 +13,7 @@ -- Portability :  GHC  -- -- Extended Graphic object - an AdvanceGraphic is a Graphic --- twinned with and AdvanceV vector.+-- twinned with and advance vector. -- -------------------------------------------------------------------------------- @@ -25,33 +25,37 @@   , DAdvGraphic  -  , makeAdvGraphic-  , extractLocGraphic-  , runAdvGraphic+  , intoAdvGraphic+  , emptyAdvGraphic +   -- * Composition-  , advplus+  , advcat+  , advsep   , advconcat+  , advspace+  , advpunctuate+  , advfill    ) where  import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun-import Wumpus.Basic.Kernel.Base.DrawingContext-import Wumpus.Basic.Kernel.Base.WrappedPrimitive import Wumpus.Basic.Kernel.Objects.BaseObjects import Wumpus.Basic.Kernel.Objects.Graphic  import Wumpus.Core                              -- package: wumpus-core +import Data.AffineSpace                         -- package: vector-space+import Data.VectorSpace -import Control.Applicative + -- | /Advance vector/ graphic - this partially models the  -- PostScript @show@ command which moves the /current point/ by the--- width (advance) vector as each character is drawn.+-- advance (width) vector as each character is drawn. ---type AdvGraphic u      = LocImage u (Point2 u)+type AdvGraphic u      = LocImage u (Vec2 u)  type DAdvGraphic       = AdvGraphic Double @@ -61,27 +65,35 @@   --- | Construction is different to intoZZ functions hence the --- different name.++-- | 'intoAdvGraphic' : @ loc_context_function * graphic -> Image @ ---makeAdvGraphic :: DrawingInfo (PointDisplace u)+-- Build an 'AdvGraphic' from a context function ('CF') that +-- generates the answer displacement vector and a 'LocGraphic' +-- that draws the 'AdvGraphic'.+--+intoAdvGraphic :: LocCF u (Vec2 u)                -> LocGraphic u                 -> AdvGraphic u-makeAdvGraphic dispf gf = -    promoteR1 $ \pt -> dispf >>= \fn -> fmap (replaceL $ fn pt) (gf `at` pt)  +intoAdvGraphic = intoLocImage  +-- | 'emptyAdvGraphic' : @ AdvGraphic @+--+-- Build an empty 'AdvGraphic'.+-- +-- The 'emptyAdvGraphic' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, the answer vetor generated is+-- the empty vector @(V2 0 0)@.+-- +emptyAdvGraphic :: Num u => AdvGraphic u+emptyAdvGraphic = replaceAns (V2 0 0) $ emptyLocGraphic   --- This should probably go - the name is not exact enough...--extractLocGraphic :: AdvGraphic u -> LocGraphic u-extractLocGraphic = fmap (replaceL uNil)--runAdvGraphic :: DrawingContext  -> Point2 u -> AdvGraphic u -              -> (Point2 u, PrimGraphic u)-runAdvGraphic ctx pt df = runCF1 ctx pt df+-- runAdvGraphic :: DrawingContext  -> Point2 u -> AdvGraphic u +--               -> (Point2 u, PrimGraphic u)+-- runAdvGraphic ctx pt df = runCF1 ctx pt df   @@ -91,16 +103,64 @@ -- Note there are opportunities for extra composition operators -- like the /picture language/... -infixr 6 `advplus` +-- Naming convention - binary functions are favoured for shorter names. --- | \*\* WARNING \*\* - pending removal.+infixr 6 `advcat`+infixr 5 `advsep`++-- | Concatenate the two AdvGraphics. ---advplus :: AdvGraphic u -> AdvGraphic u -> AdvGraphic u-advplus = chain1+advcat :: Num u => AdvGraphic u -> AdvGraphic u -> AdvGraphic u+advcat af ag = promoteR1 $ \start -> +                 (af `at` start)        >>= \(v1,prim1) -> +                 (ag `at` start .+^ v1) >>= \(v2,prim2) -> +                 return (v1 ^+^ v2, prim1 `oplus` prim2)  +-- | Concatenate the two AdvGraphics spacing them by the supplied +-- vector.+--+advsep :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u -> AdvGraphic u+advsep sv af ag = promoteR1 $ \start -> +                 (af `at` start)        >>= \(v1,prim1) -> +                 (ag `at` start .+^ sv ^+^ v1) >>= \(v2,prim2) -> +                 return (v1 ^+^ sv ^+^  v2, prim1 `oplus` prim2)+++-- | Concatenate the list of AdvGraphic with 'advcat'.+-- advconcat :: Num u => [AdvGraphic u] -> AdvGraphic u-advconcat []     = makeAdvGraphic (pure id) emptyLocGraphic-advconcat [x]    = x-advconcat (x:xs) = x `chain1` advconcat xs +advconcat []     = emptyAdvGraphic+advconcat (x:xs) = step x xs+  where+    step a (b:bs) = step (a `advcat` b) bs+    step a []     = a+++-- | Concatenate the list of AdvGraphic with 'advsep'.+--+advspace :: Num u => Vec2 u -> [AdvGraphic u] -> AdvGraphic u+advspace _  []     = emptyAdvGraphic+advspace sv (x:xs) = step x xs+  where+    step a (b:bs) = step (advsep sv a b) bs+    step a []     = a+++-- | Concatenate the list of AdvGraphic with 'advsep'.+--+advpunctuate :: Num u => AdvGraphic u -> [AdvGraphic u] -> AdvGraphic u+advpunctuate _  []     = emptyAdvGraphic+advpunctuate sep (x:xs) = step x xs+  where+    step a (b:bs) = step (a `advcat` sep `advcat` b) bs+    step a []     = a+++-- | Render the supplied AdvGraphic, but swap the result advance+-- for the supplied vector. This function has behaviour analogue +-- to @fill@ in the @wl-pprint@ library.+-- +advfill :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u+advfill sv = replaceAns sv
src/Wumpus/Basic/Kernel/Objects/BaseObjects.hs view
@@ -38,8 +38,6 @@   , DLocImage   , DLocThetaImage -  , hyperlink-   ) where  import Wumpus.Basic.Kernel.Base.ContextFun@@ -180,9 +178,6 @@ --------------------------------------------------------------------------------  -hyperlink :: XLink -> Image u a -> Image u a-hyperlink hypl = -    fmap (\(a,prim) -> (a, metamorphPrim (xlink hypl) prim))   
src/Wumpus/Basic/Kernel/Objects/Bounded.hs view
@@ -30,12 +30,15 @@   , DBoundedLocThetaGraphic    , emptyBoundedLocGraphic+  , emptyBoundedLocThetaGraphic    , centerOrthoBBox   , illustrateBoundedGraphic   , illustrateBoundedLocGraphic   , illustrateBoundedLocThetaGraphic +  , bbrectangle+   ) where  import Wumpus.Basic.Kernel.Base.BaseDefs@@ -43,10 +46,10 @@ import Wumpus.Basic.Kernel.Base.DrawingContext import Wumpus.Basic.Kernel.Base.UpdateDC import Wumpus.Basic.Kernel.Objects.BaseObjects+import Wumpus.Basic.Kernel.Objects.DrawingPrimitives import Wumpus.Basic.Kernel.Objects.Graphic  import Wumpus.Core                              -- package: wumpus-core-import Wumpus.Core.Colour ( blue )  import Control.Applicative @@ -81,7 +84,7 @@   --- | 'openStroke' : @ theta * bbox -> BBox @+-- | 'centerOrthoBBox' : @ theta * bbox -> BBox @ --  -- Rotate a bounding box by @theta@ about its center. Take the  -- new bounding box.@@ -99,11 +102,36 @@     ctr = boundaryCenter bb  +++-- | 'emptyBoundedLocGraphic' : @ BoundedLocGraphic @+--+-- Build an empty 'BoundedLocGraphic'.+-- +-- The 'emptyBoundedLocGraphic' is treated as a /null primitive/ +-- by @Wumpus-Core@ and is not drawn, although it does generate+-- the minimum bounding box with both the bottom-left and +-- upper-right corners at the implicit start point.+-- emptyBoundedLocGraphic :: Num u => BoundedLocGraphic u-emptyBoundedLocGraphic = intoLocImage fn  emptyLocGraphic+emptyBoundedLocGraphic = intoLocImage fn emptyLocGraphic   where     fn = promoteR1 $ \pt -> pure (BBox pt pt) ++-- | 'emptyBoundedLocThetaGraphic' : @ BoundedLocThetaGraphic @+--+-- Build an empty 'BoundedLocThetaGraphic'.+-- +-- The 'emptyBoundedLocThetaGraphic' is treated as a /null primitive/ +-- by @Wumpus-Core@ and is not drawn, although it does generate+-- the minimum bounding box with both the bottom-left and +-- upper-right corners at the implicit start point (the implicit +-- inclination can be ignored).+--+emptyBoundedLocThetaGraphic :: Num u => BoundedLocThetaGraphic u+emptyBoundedLocThetaGraphic = lift1R2 emptyBoundedLocGraphic+ -------------------------------------------------------------------------------- --  @@ -126,15 +154,15 @@     promoteR2 $ \pt theta-> illustrateBoundedGraphic $ apply2R2 mf pt theta  -+--  bbrectangle :: Fractional u => BoundingBox u -> Graphic u bbrectangle (BBox p1@(P2 llx lly) p2@(P2 urx ury))     | llx == urx && lly == ury = emptyLocGraphic `at` p1     | otherwise                =          localize drawing_props $ rect1 `oplus` cross   where-    drawing_props = strokeColour blue . capRound . dashPattern (Dash 0 [(1,2)])+    drawing_props = capRound . dashPattern (Dash 0 [(1,2)])     rect1         = strokedRectangle (urx-llx) (ury-lly) `at` p1-    cross         = straightLineBetween p1 p2 -                      `oplus` straightLineBetween (P2 llx ury) (P2 urx lly)+    cross         = straightLineGraphic p1 p2 +                      `oplus` straightLineGraphic (P2 llx ury) (P2 urx lly) 
src/Wumpus/Basic/Kernel/Objects/Connector.hs view
@@ -29,15 +29,19 @@   , ConnectorImage   , DConnectorImage -+  , intoConnectorImage+  , emptyConnectorGraphic    ) where +import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Objects.BaseObjects+import Wumpus.Basic.Kernel.Objects.Graphic  -- import Wumpus.Core                              -- package: wumpus-core +import Control.Applicative  -------------------------------------------------------------------------------- -- Connector Graphic@@ -48,7 +52,9 @@ -- type ConnectorGraphic u         = ConnectorCF u (GraphicAns u) -+-- | Alias of 'ConnectorGraphic' where the unit type is +-- specialized to Double. +-- type DConnectorGraphic          = ConnectorGraphic Double  @@ -61,14 +67,46 @@ -- | ConnectorImage is a connector drawn between two points  -- constructing an Image. ----- Usually the answer type of a ConnectorImage will be a Path so--- the Points ar @midway@, @atstart@ etc. can be taken on it.+-- Usually the answer type of a ConnectorImage will be a Path +-- (defined in Wumpus-Drawing) so the points at @midway@, +-- @atstart@ etc. or the end directions and tangents can be taken +-- on it. -- type ConnectorImage u a = ConnectorCF u (ImageAns u a)  +-- | Alias of 'ConnectorImage' where the unit type is +-- specialized to Double. +-- type DConnectorImage a  = ConnectorImage Double a  ++-- | 'intoConnectorImage' : @ conn_context_function * conn_graphic -> LocImage @+--+-- /Connector/ version of 'intoImage'. +-- +-- The 'ConnectorImage' is built as a function from an implicit +-- start and end points to the answer.+--+intoConnectorImage :: ConnectorCF u a -> ConnectorGraphic u +                   -> ConnectorImage u a+intoConnectorImage = liftA2 (\a (_,b) -> (a,b))+++-- | 'emptyConnectorGraphic' : @ ConnectorGraphic @+--+-- Build an empty 'ConnectorGraphic'.+-- +-- The 'emptyConnectorGraphic' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, although it does generate a +-- bounding box around the rectangular hull of the start and end +-- points.+-- +emptyConnectorGraphic :: Num u => ConnectorGraphic u +emptyConnectorGraphic = promoteR2 $ \start end -> +    let a = emptyLocGraphic `at` start+        b = emptyLocGraphic `at` end+    in a `oplus` b  
src/Wumpus/Basic/Kernel/Objects/CtxPicture.hs view
@@ -4,7 +4,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Basic.Kernel.Objects.CtxPicture--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  stephen.tetley@gmail.com@@ -15,14 +15,16 @@ --  -- This is the corresponding type to Picture in the Wumpus-Core. -- --- CtxPicture is a function from the DrawingContext to a Picture.--- Internally the result is actually a (Maybe Picture) and not a --- Picture, this is a trick to promote the extraction from --- possibly empty drawings (created by TraceDrawing) to the --- top-level of the type hierarchy where client code can deal --- with empty drawings explicitly (empty Pictures cannot be --- rendered by Wumpus-Core).+-- Note - many of the composition functions are in +-- /destructor form/. As Wumpus cannot make a Picture from an +-- empty list of Pictures, /destructor form/ decomposes the +-- list into the @head@ and @rest@ as arguments in the function +-- signature, rather than take a possibly empty list and have to +-- throw an error. -- +-- TODO - PosImage no longer supports composition operators, so +-- better names are up for grabs...+--  --------------------------------------------------------------------------------  module Wumpus.Basic.Kernel.Objects.CtxPicture@@ -38,36 +40,33 @@   , mapCtxPicture    -- * Composition-  , over -  , under+  , cxpBeneath -  , centric-  , nextToH-  , nextToV+  , cxpUniteCenter+  , cxpRight+  , cxpDown   -  , atPoint -  , centeredAt+  , cxpCenteredAt -  , zconcat -  , hcat -  , vcat+  , cxpRow +  , cxpColumn  -  , hspace-  , vspace-  , hsep-  , vsep+  , cxpRightSep+  , cxpDownSep+  , cxpRowSep+  , cxpColumnSep     -- * Compose with alignment-  , alignH-  , alignV-  , alignHSep-  , alignVSep-  , hcatA-  , vcatA-  , hsepA-  , vsepA+  , cxpAlignH+  , cxpAlignV+  , cxpAlignSepH+  , cxpAlignSepV+  , cxpAlignRow+  , cxpAlignColumn+  , cxpAlignRowSep+  , cxpAlignColumnSep     ) where@@ -87,9 +86,34 @@ import Data.List ( foldl' )  +-- Note - PosGraphic should take priority for the good names. +-- | A /Contextual Picture/.+-- +-- This type corresponds to the 'Picture' type in Wumpus-Core, but+-- it is embedded with a 'DrawingContext' (for font properties, +-- fill colour etc.). So it is a function +-- /from DrawingContext to Picture/.+--+-- Internally the result is actually a (Maybe Picture) and not a +-- Picture, this is a trick to promote the extraction from +-- possibly empty drawings (created by TraceDrawing) to the +-- top-level of the type hierarchy where client code can deal +-- with empty drawings explicitly (empty Pictures cannot be +-- rendered by Wumpus-Core).+--+-- > a `oplus` b+--+-- The 'OPlus' (semigroup) instance for 'CtxPicture' draws picture +-- a in front of picture b in the z-order, neither picture is +-- moved. (Usually the picture composition operators in this +-- module move the second picture aligning it somehow with the +-- first).+-- newtype CtxPicture u = CtxPicture { getCtxPicture :: CF (Maybe (Picture u)) } +-- | Version of CtxPicture specialized to Double for the unit type.+-- type DCtxPicture = CtxPicture Double  @@ -97,22 +121,40 @@   -+-- | 'runCtxPicture' : @ drawing_ctx * ctx_picture -> Maybe Picture @+--+-- Run a 'CtxPicture' with the supplied 'DrawingContext' +-- producing a 'Picture'.+--+-- The resulting Picture may be empty. Wumpus-Core cannot +-- generate empty pictures as they have no bounding box, so the +-- result is wrapped within a Maybe. This delegates reponsibility +-- for handling empty pictures to client code.+-- runCtxPicture :: DrawingContext -> CtxPicture u -> Maybe (Picture u) runCtxPicture ctx drw = runCF ctx (getCtxPicture drw)   -+-- | 'runCtxPictureU' : @ drawing_ctx * ctx_picture -> Picture @+--+-- /Unsafe/ version of 'runCtxPicture'.+--+-- This function throws a runtime error when supplied with an+-- empty CtxPicture.+-- runCtxPictureU :: DrawingContext -> CtxPicture u -> Picture u runCtxPictureU ctx df = maybe fk id $ runCtxPicture ctx df   where     fk = error "runCtxPictureU - empty CtxPicture."     -+-- | 'drawTracing' : @ trace_drawing  -> CtxPicture @+--+-- Transform a 'TraceDrawing' into a 'CtxPicture'.+-- drawTracing :: (Real u, Floating u, FromPtSize u)              => TraceDrawing u a -> CtxPicture u drawTracing mf = CtxPicture $ -    drawingCtx >>= \ctx -> return (liftToPictureMb (execTraceDrawing ctx mf) )+    drawingCtx >>= \ctx -> return (liftToPictureMb $ execTraceDrawing ctx mf)   -- Note - cannot get an answer from a TraceDrawing with this @@ -127,15 +169,34 @@ -- a where this would be useful (rather than just making things  -- more complicated)?  ----------------------------------------------------------------------------------- -clipCtxPicture :: (Num u, Ord u) => (PrimPath u) -> CtxPicture u -> CtxPicture u+-- | 'clipCtxPicture' : @ path * ctx_picture -> CtxPicture @+--+-- Clip a picture with a path.+-- +clipCtxPicture :: (Num u, Ord u) => PrimPath u -> CtxPicture u -> CtxPicture u clipCtxPicture cpath = mapCtxPicture (clip cpath) +-- Note - it seems preferable to clip a smaller type in the +-- hierarchy than CtxPicture. But which one Graphic, TraceDrawing? +-- ...+-- ++-- | 'mapCtxPicture' : @ trafo * ctx_picture -> CtxPicture @+--+-- Apply a picture transformation function to the 'Picture'+-- warpped in a 'CtxPicture'.+-- mapCtxPicture :: (Picture u -> Picture u) -> CtxPicture u -> CtxPicture u mapCtxPicture pf = CtxPicture . fmap (fmap pf) . getCtxPicture ++--------------------------------------------------------------------------------++++ instance (Real u, Floating u) => Rotate (CtxPicture u) where    rotate ang = mapCtxPicture (rotate ang) @@ -226,23 +287,24 @@   -  --- Note - do not export the empty drawing. It is easier to --- pretend it doesn't exist.--- -empty_drawing :: (Real u, Floating u, FromPtSize u) => CtxPicture u-empty_drawing = drawTracing $ return ()  -- -------------------------------------------------------------------------------- -- Composition operators +-- Naming convention - Wumpus-Core already prefixes operations+-- on Pictures with pic. As the picture operators here work on a+-- different type, they merit a different naming scheme.+--+-- Unfortunately the @cxp_@ prefix is rather ugly...+--+-- Directional names seem better than positional ones (less +-- ambiguous as when used as binary operators).+-- -drawingConcat :: (Picture u -> Picture u -> Picture u) -              -> CtxPicture u -> CtxPicture u -> CtxPicture u-drawingConcat op a b = CtxPicture $ mbpostcomb op (getCtxPicture a) (getCtxPicture b)+cxpConcat :: (Picture u -> Picture u -> Picture u) +          -> CtxPicture u -> CtxPicture u -> CtxPicture u+cxpConcat op a b = CtxPicture $ mbpostcomb op (getCtxPicture a) (getCtxPicture b)   @@ -273,49 +335,39 @@           -> (a -> a -> Picture u -> Picture u)            -> CtxPicture u -> CtxPicture u           -> CtxPicture u-megaCombR qL qR trafoR = drawingConcat fn+megaCombR qL qR trafoR = cxpConcat fn   where     fn pic1 pic2 = let a    = qL pic1                        b    = qR pic2                        p2   = trafoR a b pic2                    in pic1 `picOver` p2 ------ | > a `over` b+-- | > a `oplus` b --  -- Place \'drawing\' a over b. The idea of @over@ here is in  -- terms z-ordering, nither picture a or b are actually moved. ---over    :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-over    = drawingConcat picOver-+instance (Num u, Ord u) => OPlus (CtxPicture u) where+  oplus = cxpConcat picOver  --- | > a `under` b------ Similarly @under@ draws the first drawing behind --- the second but move neither.+-- | 'cxpBeneath' : @ ctx_picture1 * ctx_picture2 -> CtxPicture @+-- +-- > a `cxpBeneath` b ---under :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-under = flip over------ | Move in both the horizontal and vertical.+-- Similarly @beneath@ draws the first picture behind the second +-- picture in the z-order, neither picture is moved. ---move :: (Num u, Ord u) => Vec2 u -> CtxPicture u -> CtxPicture u-move v = mapCtxPicture (\p -> p `picMoveBy` v)-+cxpBeneath :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u+cxpBeneath = flip oplus    -------------------------------------------------------------------------------- -- Composition -infixr 5 `nextToV`-infixr 6 `nextToH`, `centric`+infixr 5 `cxpDown`+infixr 6 `cxpRight`, `cxpUniteCenter`   @@ -323,51 +375,47 @@ -- | Draw @a@, move @b@ so its center is at the same center as  -- @a@, @b@ is drawn over underneath in the zorder. ----- > a `centeric` b ---+-- > a `cxpUniteCenter` b  ---centric :: (Fractional u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-centric = megaCombR boundaryCtr boundaryCtr moveFun++cxpUniteCenter :: (Fractional u, Ord u) +               => CtxPicture u -> CtxPicture u -> CtxPicture u+cxpUniteCenter = megaCombR boundaryCtr boundaryCtr moveFun   where     moveFun p1 p2 pic =  let v = p1 .-. p2 in pic `picMoveBy` v -+--+-- Are combinator names less ambiguous if they name direction+-- rather than position?+-- --- | > a `nextToH` b+-- | > a `cxpRight` b -- --- Horizontal composition - move @b@, placing it to the right --- of @a@.+-- Horizontal composition - position picture @b@ to the right of +-- picture @a@. -- -nextToH :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-nextToH = megaCombR boundaryRightEdge boundaryLeftEdge moveFun+cxpRight :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u+cxpRight = megaCombR boundaryRightEdge boundaryLeftEdge moveFun   where      moveFun a b pic = pic `picMoveBy` hvec (a - b)   --- | > a `nextToV` b+-- | > a `cxpDown` b ----- Vertical composition - move @b@, placing it below @a@.+-- Vertical composition - position picture @b@ /down/ from picture+-- @a@. ---nextToV :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-nextToV = megaCombR boundaryBottomEdge boundaryTopEdge moveFun+cxpDown :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u+cxpDown = megaCombR boundaryBottomEdge boundaryTopEdge moveFun   where      moveFun a b drw = drw `picMoveBy` vvec (a - b)  --- | Place the picture at the supplied point.------ `atPoint` was previous the `at` operator.--- -atPoint :: (Num u, Ord u) => CtxPicture u -> Point2 u  -> CtxPicture u-p `atPoint` (P2 x y) = move (V2 x y) p--- -- | Center the picture at the supplied point. ---centeredAt :: (Fractional u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u-centeredAt d (P2 x y) = mapCtxPicture fn d+cxpCenteredAt :: (Fractional u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u+cxpCenteredAt d (P2 x y) = mapCtxPicture fn d   where     fn p = let bb = boundary p                dx = x - (boundaryWidth  bb * 0.5)@@ -375,29 +423,31 @@            in p `picMoveBy` vec dx dy  --- | Concatenate the list of drawings. ------ No pictures are moved. ----zconcat :: (Real u, Floating u, FromPtSize u) => [CtxPicture u] -> CtxPicture u-zconcat []     = empty_drawing-zconcat (d:ds) = foldl' over d ds ------ | Concatenate the list pictures @xs@ horizontally.+-- | 'cxpRow' : @ ctx_picture1 * [ctx_picture] -> CtxPicture @ -- -hcat :: (Real u, Floating u, FromPtSize u) => [CtxPicture u] -> CtxPicture u-hcat []     = empty_drawing-hcat (d:ds) = foldl' nextToH d ds+-- Make a row of pictures concatenating them horizontally.+-- +-- Note - this function is in /destructor form/. As Wumpus cannot+-- make a Picture from an empty list of Pictures, +-- /destructor form/ decomposes the list into the @head@ and the +-- @rest@ in the function signature, rather than take a possibly+-- empty list and have to throw an error.+-- +cxpRow :: (Real u, Floating u, FromPtSize u) +       => CtxPicture u -> [CtxPicture u] -> CtxPicture u+cxpRow = foldl' cxpRight  --- | Concatenate the list of pictures @xs@ vertically.+-- | 'cxpColumn' : @ ctx_picture1 * [ctx_picture] -> CtxPicture @+-- +-- Make a column of pictures concatenating them vertically.+-- +-- Note - this function is in /destructor form/. ---vcat :: (Real u, Floating u, FromPtSize u) => [CtxPicture u] -> CtxPicture u-vcat []     = empty_drawing-vcat (d:ds) = foldl' nextToV d ds+cxpColumn :: (Real u, Floating u, FromPtSize u) +          => CtxPicture u -> [CtxPicture u] -> CtxPicture u+cxpColumn = foldl' cxpDown   @@ -407,13 +457,13 @@   --- | > hspace n a b+-- | > cxpRightSep n a b -- -- Horizontal composition - move @b@, placing it to the right  -- of @a@ with a horizontal gap of @n@ separating the pictures. ---hspace :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u-hspace n = megaCombR boundaryRightEdge boundaryLeftEdge moveFun+cxpRightSep :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u+cxpRightSep n = megaCombR boundaryRightEdge boundaryLeftEdge moveFun   where     moveFun a b pic = pic `picMoveBy` hvec (n + a - b) @@ -421,39 +471,40 @@   --- | > vspace n a b+-- | > cxpDownSep n a b -- -- Vertical composition - move @b@, placing it below @a@ with a -- vertical gap of @n@ separating the pictures. ---vspace :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u-vspace n = megaCombR boundaryBottomEdge boundaryTopEdge moveFun+cxpDownSep :: (Num u, Ord u) +           => u -> CtxPicture u -> CtxPicture u -> CtxPicture u+cxpDownSep n = megaCombR boundaryBottomEdge boundaryTopEdge moveFun   where      moveFun a b pic = pic `picMoveBy`  vvec (a - b - n)   --- | > hsep n xs+-- | > picRowSep n x xs -- -- Concatenate the list of pictures @xs@ horizontally with  -- @hspace@ starting at @x@. The pictures are interspersed with  -- spaces of @n@ units. ---hsep :: (Real u, Floating u, FromPtSize u) => u -> [CtxPicture u] -> CtxPicture u-hsep _ []     = empty_drawing-hsep n (d:ds) = foldl' (hspace n) d ds+cxpRowSep :: (Real u, Floating u, FromPtSize u) +          => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u+cxpRowSep n = foldl' (cxpRightSep n)   --- | > vsep n xs+-- | > vsepPic n xs -- -- Concatenate the list of pictures @xs@ vertically with  -- @vspace@ starting at @x@. The pictures are interspersed with  -- spaces of @n@ units. ---vsep :: (Real u, Floating u, FromPtSize u) => u -> [CtxPicture u] -> CtxPicture u-vsep _ []     = empty_drawing-vsep n (d:ds) = foldl' (vspace n) d ds+cxpColumnSep :: (Real u, Floating u, FromPtSize u) +             => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u+cxpColumnSep n = foldl' (cxpDownSep n)   --------------------------------------------------------------------------------@@ -463,29 +514,32 @@ alignMove p1 p2 pic = pic `picMoveBy` (p1 .-. p2)  +-- Note - these don\'t conform to the naming convention, but using +-- /Right/ in the names would be confusing with alignment. --- | > alignH align a b++-- | > cxpAlignH align a b --  -- Horizontal composition - move @b@, placing it to the right  -- of @a@ and align it with the top, center or bottom of @a@. -- -alignH :: (Fractional u, Ord u) -       =>  HAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u-alignH HTop     = megaCombR boundaryNE    boundaryNW     alignMove-alignH HCenter  = megaCombR boundaryE    boundaryW     alignMove-alignH HBottom  = megaCombR boundarySE boundarySW  alignMove+cxpAlignH :: (Fractional u, Ord u) +          =>  HAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u+cxpAlignH HTop     = megaCombR boundaryNE boundaryNW  alignMove+cxpAlignH HCenter  = megaCombR boundaryE  boundaryW   alignMove+cxpAlignH HBottom  = megaCombR boundarySE boundarySW  alignMove  --- | > alignV align a b+-- | > cxpAlignV align a b --  -- Vertical composition - move @b@, placing it below @a@  -- and align it with the left, center or right of @a@. -- -alignV :: (Fractional u, Ord u) +cxpAlignV :: (Fractional u, Ord u)         => VAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u-alignV VLeft    = megaCombR boundarySW  boundaryNW   alignMove-alignV VCenter  = megaCombR boundaryS   boundaryN    alignMove-alignV VRight   = megaCombR boundarySE boundaryNE  alignMove+cxpAlignV VLeft    = megaCombR boundarySW boundaryNW alignMove+cxpAlignV VCenter  = megaCombR boundaryS  boundaryN  alignMove+cxpAlignV VRight   = megaCombR boundarySE boundaryNE  alignMove   @@ -495,69 +549,67 @@   --- | > alignHSep align sep a b+-- | > cxpAlignSepH align sep a b -- --- Spacing version of alignH - move @b@ to the right of @a@ +-- Spacing version of 'cxpAlignH' - move @b@ to the right of @a@  -- separated by @sep@ units, align @b@ according to @align@. -- -alignHSep :: (Fractional u, Ord u) -          => HAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u-alignHSep HTop    dx = megaCombR boundaryNE boundaryNW (alignMove2 (hvec dx))-alignHSep HCenter dx = megaCombR boundaryE  boundaryW  (alignMove2 (hvec dx))-alignHSep HBottom dx = megaCombR boundarySE boundarySW (alignMove2 (hvec dx))+cxpAlignSepH :: (Fractional u, Ord u) +               => HAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u+cxpAlignSepH align dx = go align+  where+    go HTop    = megaCombR boundaryNE boundaryNW (alignMove2 (hvec dx))+    go HCenter = megaCombR boundaryE  boundaryW  (alignMove2 (hvec dx))+    go HBottom = megaCombR boundarySE boundarySW (alignMove2 (hvec dx))  --- | > alignVSep align sep a b+-- | > cxpAlignSepV align sep a b --  -- Spacing version of alignV - move @b@ below @a@  -- separated by @sep@ units, align @b@ according to @align@. -- -alignVSep :: (Fractional u, Ord u) -          => VAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u-alignVSep VLeft   dy = megaCombR boundarySW boundaryNW (alignMove2 $ vvec (-dy)) -alignVSep VCenter dy = megaCombR boundaryS  boundaryN  (alignMove2 $ vvec (-dy)) -alignVSep VRight  dy = megaCombR boundarySE boundaryNE (alignMove2 $ vvec (-dy))+cxpAlignSepV :: (Fractional u, Ord u) +               => VAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u+cxpAlignSepV align dy = go align+  where+    go VLeft   = megaCombR boundarySW boundaryNW (alignMove2 $ vvec (-dy)) +    go VCenter = megaCombR boundaryS  boundaryN  (alignMove2 $ vvec (-dy)) +    go VRight  = megaCombR boundarySE boundaryNE (alignMove2 $ vvec (-dy))  --- | Variant of 'hcat' that aligns the pictures as well as+-- | Variant of 'cxpRow' that aligns the pictures as well as -- concatenating them. ---hcatA :: (Real u, Floating u, FromPtSize u) -      => HAlign -> [CtxPicture u] -> CtxPicture u-hcatA _  []     = empty_drawing-hcatA ha (d:ds) = foldl' (alignH ha) d ds+cxpAlignRow :: (Real u, Floating u, FromPtSize u) +            => HAlign -> CtxPicture u-> [CtxPicture u] -> CtxPicture u+cxpAlignRow ha = foldl' (cxpAlignH ha)   --- | Variant of 'vcat' that aligns the pictures as well as+-- | Variant of 'cxpColumn' that aligns the pictures as well as -- concatenating them. ---vcatA :: (Real u, Floating u, FromPtSize u) -      => VAlign -> [CtxPicture u] -> CtxPicture u-vcatA _  []     = empty_drawing-vcatA va (d:ds) = foldl' (alignV va) d ds+cxpAlignColumn :: (Real u, Floating u, FromPtSize u) +               => VAlign -> CtxPicture u -> [CtxPicture u] -> CtxPicture u+cxpAlignColumn va = foldl' (cxpAlignV va)  --- | Variant of @hsep@ that aligns the pictures as well as+-- | Variant of 'cxpRow' that aligns the pictures as well as -- concatenating and spacing them. ---hsepA :: (Real u, Floating u, FromPtSize u) -      => HAlign -> u -> [CtxPicture u] -> CtxPicture u-hsepA _  _ []     = empty_drawing-hsepA ha n (d:ds) = foldl' op d ds-  where -    a `op` b = alignHSep ha n a b +cxpAlignRowSep :: (Real u, Floating u, FromPtSize u) +                 => HAlign -> u -> CtxPicture u -> [CtxPicture u] +                 -> CtxPicture u+cxpAlignRowSep ha n = foldl' (cxpAlignSepH ha n)  --- | Variant of @vsep@ that aligns the pictures as well as+-- | Variant of 'cxpColumn' that aligns the pictures as well as -- concatenating and spacing them. ---vsepA :: (Real u, Floating u, FromPtSize u) -      => VAlign -> u -> [CtxPicture u] -> CtxPicture u-vsepA _  _ []     = empty_drawing-vsepA va n (d:ds) = foldl' op d ds-  where -    a `op` b = alignVSep va n a b +cxpAlignColumnSep :: (Real u, Floating u, FromPtSize u) +                    => VAlign -> u -> CtxPicture u -> [CtxPicture u] +                    -> CtxPicture u+cxpAlignColumnSep va n = foldl' (cxpAlignSepV va n)    
+ src/Wumpus/Basic/Kernel/Objects/Displacement.hs view
@@ -0,0 +1,277 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Basic.Kernel.Objects.Displacement+-- Copyright   :  (c) Stephen Tetley 2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  highly unstable+-- Portability :  GHC +--+-- Displacing points - often start points. +--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Displacement+  (+++  -- * Moving points and angles+    PointDisplace+  , ThetaDisplace+  , ThetaPointDisplace+++  , moveStart+  , moveStartTheta+  , moveStartThetaPoint+  , moveStartThetaAngle++  , displace+  , displaceVec+  , displaceH+  , displaceV++  , northwards+  , southwards +  , eastwards+  , westwards  ++  , northeastwards+  , northwestwards+  , southeastwards+  , southwestwards+++  , displaceParallel+  , displacePerpendicular+  , displaceOrtho++  , thetaNorthwards+  , thetaSouthwards +  , thetaEastwards+  , thetaWestwards  ++  , thetaNortheastwards+  , thetaNorthwestwards+  , thetaSoutheastwards+  , thetaSouthwestwards++  ) where+++import Wumpus.Basic.Kernel.Base.ContextFun++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space++++--------------------------------------------------------------------------------+-- Displacing points++-- | 'PointDisplace' is a type representing functions +-- @from Point to Point@.+--+-- It is especially useful for building composite graphics where +-- one part of the graphic is drawn from a different start point +-- to the other part.+--+type PointDisplace u = Point2 u -> Point2 u+++-- | 'ThetaDisplace' is a type representing functions +-- @from Radian to Radian@.+--+-- It is especially useful for building composite graphics where +-- one part of the graphic is drawn from a different start point +-- to the other part.+--+type ThetaDisplace = Radian -> Radian+++-- | 'ThetaPointDisplace' is a type representing functions +-- @from Radian * Point to Point@.+--+-- It is useful for building arrowheads which are constructed +-- with an implicit angle representing the direction of the line +-- at the arrow tip.+--+type ThetaPointDisplace u = Radian -> PointDisplace u++++-- | Move the start-point of a 'LocCF' with the supplied +-- displacement function.+--+moveStart :: PointDisplace u -> LocCF u a -> LocCF u a+moveStart f ma = promoteR1 $ \pt -> apply1R1 ma (f pt)++++-- | Move the start-point of a 'LocThetaCF' with the supplied +-- displacement function.+--+moveStartTheta :: ThetaPointDisplace u -> LocThetaCF u a -> LocThetaCF u a+moveStartTheta f ma = promoteR2 $ \pt theta -> let p2 = f theta pt +                                               in apply2R2 ma p2 theta+++-- | Move the start-point of a 'LocThetaCF' with the supplied +-- displacement function.+--+moveStartThetaPoint :: PointDisplace u -> LocThetaCF u a -> LocThetaCF u a+moveStartThetaPoint f ma = promoteR2 $ \pt theta -> apply2R2 ma (f pt) theta+++-- | Change the inclination of a 'LocThetaCF' with the supplied +-- displacement function.+--+moveStartThetaAngle :: ThetaDisplace -> LocThetaCF u a -> LocThetaCF u a+moveStartThetaAngle f ma = promoteR2 $ \pt theta -> apply2R2 ma pt (f theta)++++--------------------------------------------------------------------------------+-- PointDisplace functions++-- | 'displace' : @ x -> y -> PointDisplace @+--+-- Build a combinator to move @Points@ by the supplied @x@ and +-- @y@ distances.+--+displace :: Num u => u -> u -> PointDisplace u+displace dx dy (P2 x y) = P2 (x+dx) (y+dy)+++-- | 'displaceV' : @ (V2 x y) -> PointDisplace @+-- +-- Version of 'displace' where the displacement is supplied as+-- a vector rather than two parameters.+-- +displaceVec :: Num u => Vec2 u -> PointDisplace u+displaceVec (V2 dx dy) (P2 x y) = P2 (x+dx) (y+dy)+++-- | 'displaceH' : @ x -> PointDisplace @+-- +-- Build a combinator to move @Points@ by horizontally the +-- supplied @x@ distance.+--+displaceH :: Num u => u -> PointDisplace u+displaceH dx (P2 x y) = P2 (x+dx) y++-- | 'displaceV' : @ y -> PointDisplace @+-- +-- Build a combinator to move @Points@ vertically by the supplied +-- @y@ distance.+--+displaceV :: Num u => u -> PointDisplace u+displaceV dy (P2 x y) = P2 x (y+dy)+++-- Cardinal displacement ++++northwards :: Num u => u -> PointDisplace u+northwards = displaceV+++southwards :: Num u => u -> PointDisplace u+southwards =  displaceV . negate++eastwards :: Num u => u -> PointDisplace u+eastwards = displaceH++westwards :: Num u => u -> PointDisplace u+westwards = displaceH . negate++northeastwards :: Floating u => u -> PointDisplace u+northeastwards = displaceVec . avec (0.25 * pi)++northwestwards ::  Floating u => u -> PointDisplace u+northwestwards = displaceVec . avec (0.75 * pi)++southeastwards ::  Floating u => u -> PointDisplace u+southeastwards = displaceVec . avec (1.75 * pi)++southwestwards ::  Floating u => u -> PointDisplace u+southwestwards = displaceVec . avec (1.25 * pi)+++--------------------------------------------------------------------------------+-- ThetaPointDisplace functions+++-- | 'displaceParallel' : @ dist -> ThetaPointDisplace @+-- +-- Build a combinator to move @Points@ in parallel to the +-- direction of the implicit angle by the supplied distance +-- @dist@. +--+displaceParallel :: Floating u => u -> ThetaPointDisplace u+displaceParallel d = \theta pt -> pt .+^ avec (circularModulo theta) d+++-- | 'displaceParallel' : @ dist -> ThetaPointDisplace @+-- +-- Build a combinator to move @Points@ perpendicular to the +-- inclnation of the implicit angle by the supplied distance +-- @dist@. +--+displacePerpendicular :: Floating u => u -> ThetaPointDisplace u+displacePerpendicular d = +    \theta pt -> pt .+^ avec (circularModulo $ theta + (0.5*pi)) d++++-- | 'displaceOrtho' : @ vec -> ThetaPointDisplace @+-- +-- This is a combination of @displaceParallel@ and +-- @displacePerpendicular@, with the x component of the vector+-- displaced in parallel and the y component displaced+-- perpendicular. +-- +displaceOrtho :: Floating u => Vec2 u -> ThetaPointDisplace u+displaceOrtho (V2 x y) = \theta -> +    displaceParallel x theta . displacePerpendicular y theta+++thetaNorthwards :: Floating u => u -> ThetaPointDisplace u+thetaNorthwards = displacePerpendicular+++thetaSouthwards :: Floating u => u -> ThetaPointDisplace u+thetaSouthwards = displacePerpendicular . negate+++thetaEastwards :: Floating u => u -> ThetaPointDisplace u+thetaEastwards = displaceParallel+++thetaWestwards :: Floating u => u -> ThetaPointDisplace u+thetaWestwards = displaceParallel . negate++thetaNortheastwards :: Floating u => u -> ThetaPointDisplace u+thetaNortheastwards d = +    \theta pt -> pt .+^ avec (circularModulo $ theta + (0.25*pi)) d+++thetaNorthwestwards :: Floating u => u -> ThetaPointDisplace u+thetaNorthwestwards d = +    \theta pt -> pt .+^ avec (circularModulo $ theta + (0.75*pi)) d+++thetaSoutheastwards :: Floating u => u -> ThetaPointDisplace u+thetaSoutheastwards d = +    \theta pt -> pt .+^ avec (circularModulo $ theta + (1.75*pi)) d+++thetaSouthwestwards :: Floating u => u -> ThetaPointDisplace u+thetaSouthwestwards d = +    \theta pt -> pt .+^ avec (circularModulo $ theta + (1.25*pi)) d+
+ src/Wumpus/Basic/Kernel/Objects/DrawingPrimitives.hs view
@@ -0,0 +1,651 @@+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE TypeSynonymInstances       #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Basic.Kernel.Objects.DrawingPrimitives+-- Copyright   :  (c) Stephen Tetley 2010-2011+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  highly unstable+-- Portability :  GHC +--+-- Graphic type - this is largely equivalent to Primitive in+-- Wumpus-Core, but drawing attributes are implicitly supplied +-- by the DrawingContext.+--+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.DrawingPrimitives+  (++  -- * Paths+    locPath+  , emptyLocPath++  , openStroke+  , closedStroke+  , filledPath+  , borderedPath++  -- * Text+  , textline+  , rtextline+  , escapedline+  , rescapedline++  , hkernline+  , vkernline++  -- * Lines+  , straightLine+  , straightLineGraphic+  , curveGraphic++  -- * Circles+  , strokedCircle+  , filledCircle+  , borderedCircle++  -- * Ellipses+  , strokedEllipse+  , rstrokedEllipse+  , filledEllipse+  , rfilledEllipse++  , borderedEllipse+  , rborderedEllipse++  -- * Rectangles+  , strokedRectangle+  , filledRectangle+  , borderedRectangle++  -- * Disks  +  , strokedDisk+  , filledDisk+  , borderedDisk++  , strokedEllipseDisk+  , filledEllipseDisk+  , borderedEllipseDisk++  ) where++import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Base.QueryDC+import Wumpus.Basic.Kernel.Base.WrappedPrimitive+import Wumpus.Basic.Kernel.Objects.Graphic++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space++import Control.Applicative++++-- Helper+--+graphicAns :: Primitive u -> (UNil u, PrimGraphic u)+graphicAns p = (uNil, primGraphic p)+++--------------------------------------------------------------------------------+-- Paths++-- | 'locPath' : @ [next_vector] -> (Point2 ~> PrimPath) @+--+-- Create a path 'LocCF' - i.e. a functional type +-- /from Point to PrimPath/.+-- +-- This is the analogue to 'vectorPath' in @Wumpus-Core@, but the +-- result is produced /within/ the 'DrawingContext'.+--+locPath :: Num u => [Vec2 u] -> LocCF u (PrimPath u)+locPath vs = promoteR1 $ \pt  -> pure $ vectorPath pt vs+++-- | 'emptyLocPath' : @ (Point ~> PrimPath) @+--+-- Create an empty path 'LocCF' - i.e. a functional type +-- /from Point to PrimPath/.+--+-- This is the analogue to 'emptyPath' in @Wumpus-Core@, but the+-- result is produced /within/ the 'DrawingContext'.+--+emptyLocPath :: Num u => LocCF u (PrimPath u)+emptyLocPath = locPath []+++++--+-- Drawing paths (stroke, fill, bordered)...+--++-- | 'openStroke' : @ path -> Graphic @+--+-- This is the analogue to 'ostroke' in @Wumpus-core@, but the +-- drawing properties (colour, line width, etc.) are taken from +-- the implicit 'DrawingContext'.+--+openStroke :: Num u => PrimPath u -> Graphic u+openStroke pp = +    withStrokeAttr $ \rgb attr -> graphicAns $ ostroke rgb attr pp+++-- | 'closedStroke' : @ path -> Graphic @+--+-- This is the analogue to 'cstroke' in @Wumpus-core@, but the +-- drawing properties (colour, line width, etc.) are taken from +-- the implicit 'DrawingContext'.+--+closedStroke :: Num u => PrimPath u -> Graphic u+closedStroke pp = +    withStrokeAttr $ \rgb attr -> graphicAns $ cstroke rgb attr pp+++-- | 'filledPath' : @ path -> Graphic @+-- +-- This is the analogue to 'fill' in @Wumpus-core@, but the +-- fill colour is taken from the implicit 'DrawingContext'.+--+--+filledPath :: Num u => PrimPath u -> Graphic u+filledPath pp = withFillAttr $ \rgb -> graphicAns $ fill rgb pp+                 ++-- | 'borderedPath' : @ path -> Graphic @+--+-- This is the analogue to 'fillStroke' in @Wumpus-core@, but the +-- drawing properties (fill colour, border colour, line width, +-- etc.) are taken from the implicit 'DrawingContext'.+--+--+borderedPath :: Num u => PrimPath u -> Graphic u+borderedPath pp =+    withBorderedAttr $ \frgb attr srgb -> +      graphicAns $ fillStroke frgb attr srgb pp++++--------------------------------------------------------------------------------+-- Text++-- | 'textline' : @ string -> LocGraphic @+-- +-- Create a text 'LocGraphic' - i.e. a functional type +-- /from Point to Graphic/.+--+-- The implicit point of the LocGraphic is the baseline left.+--+-- This is the analogue to 'textlabel' in @Wumpus-core@, but the+-- text properties (font family, font size, colour) are taken from+-- the implicit 'DrawingContext'.+--+textline :: Num u => String -> LocGraphic u+textline ss = +    promoteR1 $ \pt -> +      withTextAttr $ \rgb attr -> graphicAns (textlabel rgb attr ss pt)+++++-- | 'rtextline' : @ string -> LocThetaGraphic @+-- +-- Create a text 'LocThetaGraphic' - i.e. a functional type +-- /from Point and Angle to Graphic/.+--+-- The implicit point of the LocGraphic is the baseline left, the+-- implicit angle is rotation factor of the text.+--+-- Note - rotated text often does not render well in PostScript or+-- SVG. Rotated text should be used sparingly.+-- +-- This is the analogue to 'rtextlabel' in @Wumpus-core@.+--+rtextline :: Num u => String -> LocThetaGraphic u+rtextline ss = +    promoteR2 $ \pt theta -> +      withTextAttr $ \rgb attr -> graphicAns (rtextlabel rgb attr ss theta pt)++++-- | 'escapedline' : @ escaped_text -> LocGraphic @+-- +-- Create a text 'LocGraphic' - i.e. a functional type +-- /from Point to Graphic/.+--+-- The implicit point of the LocGraphic is the baseline left.+--+-- This is the analogue to 'escapedlabel' in @Wumpus-core@, but +-- the text properties (font family, font size, colour) are taken +-- from the implicit 'DrawingContext'.+--+escapedline :: Num u => EscapedText -> LocGraphic u+escapedline ss = +    promoteR1 $ \pt -> +      withTextAttr $ \rgb attr -> graphicAns (escapedlabel rgb attr ss pt)++++-- | 'rescapedline' : @ escaped_text -> LocThetaGraphic @+-- +-- Create a text 'LocThetaGraphic' - i.e. a functional type +-- /from Point and Angle to Graphic/.+--+-- The implicit point of the LocGraphic is the baseline left, the+-- implicit angle is rotation factor of the text.+--+-- Note - rotated text often does not render well in PostScript or+-- SVG. Rotated text should be used sparingly.+-- +-- This is the analogue to 'rescapedlabel' in @Wumpus-core@, but+-- the text properties (font family, font size, colour) are taken +-- from the implicit 'DrawingContext'.+--+rescapedline :: Num u => EscapedText -> LocThetaGraphic u+rescapedline ss = +    promoteR2 $ \pt theta -> +      withTextAttr $ \rgb attr -> graphicAns (rescapedlabel rgb attr ss theta pt)+++++-- | 'hkernline' : @ [kern_char] -> LocGraphic @+-- +-- Create a horizontally kerned text 'LocGraphic' - i.e. a +-- functional type /from Point to Graphic/.+--+-- The implicit point of the LocGraphic is the baseline left.+--+-- This is the analogue to 'hkernlabel' in @Wumpus-core@, but +-- the text properties (font family, font size, colour) are taken +-- from the implicit 'DrawingContext'.+--+hkernline :: Num u => [KerningChar u] -> LocGraphic u+hkernline xs = +    promoteR1 $ \pt -> +      withTextAttr $ \rgb attr -> graphicAns (hkernlabel rgb attr xs pt)+++-- | 'vkernline' : @ [kern_char] -> LocGraphic @+-- +-- Create a vertically kerned text 'LocGraphic' - i.e. a +-- functional type /from Point to Graphic/.+--+-- The implicit point of the LocGraphic is the baseline left.+--+-- This is the analogue to 'vkernlabel' in @Wumpus-core@, but +-- the text properties (font family, font size, colour) are taken +-- from the implicit 'DrawingContext'.+--+vkernline :: Num u => [KerningChar u] -> LocGraphic u+vkernline xs = +    promoteR1 $ \pt -> +      withTextAttr $ \rgb attr -> graphicAns (vkernlabel rgb attr xs pt)+++++--------------------------------------------------------------------------------+-- Lines++-- | 'straightLine' : @ vec_to -> LocGraphic @ +--+-- Create a stright line 'LocGraphic' - i.e. a functional type +-- /from Point to Graphic/.+--+-- The implicit point of the LocGraphic is the start point, the +-- end point is calculated by displacing the start point with the +-- supplied vector.+--+-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +straightLine :: Fractional u => Vec2 u -> LocGraphic u+straightLine v = mf >>= (lift0R1 . openStroke)+  where+    mf = promoteR1 $ \pt -> pure $ primPath pt [lineTo $ pt .+^ v]++          +-- | 'straightLineGraphic' : @ start_point * end_point -> LocGraphic @ +-- +-- Create a straight line 'Graphic', the start and end point +-- are supplied explicitly.+-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +straightLineGraphic :: Fractional u => Point2 u -> Point2 u -> Graphic u+straightLineGraphic p1 p2 = openStroke $ primPath p1 [lineTo p2]++++-- | 'curveGraphic' : @ start_point * control_point1 * +--        control_point2 * end_point -> Graphic @ +-- +-- Create a Bezier curve 'Graphic', all control points are +-- supplied explicitly.+-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +curveGraphic :: Fractional u +             => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u+curveGraphic sp cp1 cp2 ep = openStroke $ primPath sp [curveTo cp1 cp2 ep]+++--------------------------------------------------------------------------------+-- Circles++-- | 'strokedCircle' : @ radius -> LocGraphic @+--+-- Create a stroked circle 'LocGraphic' - the implicit point is +-- center. The circle is drawn with four Bezier curves. +-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +strokedCircle :: Floating u => u -> LocGraphic u+strokedCircle r = promoteR1 (closedStroke . curvedPath . bezierCircle r)++++-- | 'filledCircle' : @ radius -> LocGraphic @+--+-- Create a filled circle 'LocGraphic' - the implicit point is +-- center. The circle is drawn with four Bezier curves. +-- +-- The fill colour is taken from the implicit 'DrawingContext'.+-- +filledCircle :: Floating u => u -> LocGraphic u+filledCircle r =  promoteR1 (filledPath . curvedPath . bezierCircle r)++++-- | 'borderedCircle' : @ radius -> LocGraphic @+--+-- Create a bordered circle 'LocGraphic' - the implicit point is +-- center. The circle is drawn with four Bezier curves. +-- +-- The background fill colour and the outline stroke properties +-- are taken from the implicit 'DrawingContext'.+-- +borderedCircle :: Floating u => u -> LocGraphic u+borderedCircle r = promoteR1 (borderedPath . curvedPath . bezierCircle r)+++--------------------------------------------------------------------------------+-- Ellipses++++-- | 'strokedEllipse' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a stroked ellipse 'LocGraphic' - the implicit point is +-- center. The ellipse is drawn with four Bezier curves. +-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +strokedEllipse :: Floating u => u -> u -> LocGraphic u+strokedEllipse rx ry =+    promoteR1 (closedStroke . curvedPath . bezierEllipse rx ry)++++-- | 'rstrokedEllipse' : @ x_radius * y_radius -> LocThetaGraphic @+--+-- Create a stroked ellipse 'LocThetaGraphic' - the implicit point+-- is center and the angle is rotation about the center. The +-- ellipse is drawn with four Bezier curves. +-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +rstrokedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u+rstrokedEllipse hw hh = +    promoteR2 $ \ pt theta -> +      closedStroke $ curvedPath $ rbezierEllipse hw hh theta pt +++-- | 'filledEllipse' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a filled ellipse 'LocGraphic' - the implicit point is +-- center. The ellipse is drawn with four Bezier curves. +-- +-- The fill colour is taken from the implicit 'DrawingContext'.+-- +filledEllipse :: Floating u => u -> u -> LocGraphic u+filledEllipse hw hh = +    promoteR1 (filledPath . curvedPath . bezierEllipse hw hh)+++-- | 'rfilledEllipse' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a filled ellipse 'LocThetaGraphic' - the implicit point+-- is center and the angle is rotation about the center. The +-- ellipse is drawn with four Bezier curves.  +-- +-- The fill colour is taken from the implicit 'DrawingContext'.+-- +rfilledEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u+rfilledEllipse hw hh = +    promoteR2 $ \ pt theta -> +      filledPath $ curvedPath $ rbezierEllipse hw hh theta pt ++++-- | 'borderedEllipse' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a bordered ellipse 'LocGraphic' - the implicit point is +-- center. The ellipse is drawn with four Bezier curves. +-- +-- The background fill colour and the outline stroke properties +-- are taken from the implicit 'DrawingContext'.+-- +borderedEllipse :: Floating u => u -> u -> LocGraphic u+borderedEllipse hw hh =+    promoteR1 (borderedPath . curvedPath . bezierEllipse hw hh)++++-- | 'rborderedEllipse' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a bordered ellipse 'LocThetaGraphic' - the implicit point+-- is center and the angle is rotation about the center. The +-- ellipse is drawn with four Bezier curves.  +-- +-- The background fill colour and the outline stroke properties +-- are taken from the implicit 'DrawingContext'.+-- +rborderedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u+rborderedEllipse hw hh = +    promoteR2 $ \ pt theta -> +      borderedPath $ curvedPath $ rbezierEllipse hw hh theta pt ++++-- Note - clipping needs a picture as well as a path, so there is+-- no analogous @clippedPath@ function.++--------------------------------------------------------------------------------+-- Rectangles++++-- | Supplied point is /bottom-left/.+--+rectanglePath :: Num u => u -> u -> Point2 u -> PrimPath u+rectanglePath w h bl = primPath bl [ lineTo br, lineTo tr, lineTo tl ]+  where+    br = bl .+^ hvec w+    tr = br .+^ vvec h+    tl = bl .+^ vvec h+++-- | 'strokedRectangle' : @ width * height -> LocGraphic @+--+-- Create a stroked rectangle 'LocGraphic' - the implicit point is +-- bottom-left. +-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +strokedRectangle :: Fractional u => u -> u -> LocGraphic u+strokedRectangle w h = promoteR1 (closedStroke . rectanglePath w h)+++-- | 'filledRectangle' : @ width * height -> LocGraphic @+--+-- Create a filled rectangle 'LocGraphic' - the implicit point is +-- the bottom-left. +-- +-- The fill colour is taken from the implicit 'DrawingContext'.+-- +filledRectangle :: Fractional u => u -> u -> LocGraphic u+filledRectangle w h = promoteR1 (filledPath . rectanglePath w h)+++-- | 'borderedRectangle' : @ width * height -> LocGraphic @+--+-- Create a bordered rectangle 'LocGraphic' - the implicit point is +-- bottom-left. +-- +-- The background fill colour and the outline stroke properties +-- are taken from the implicit 'DrawingContext'.+-- +borderedRectangle :: Fractional u => u -> u -> LocGraphic u+borderedRectangle w h = promoteR1 (borderedPath . rectanglePath w h)+++---------------------------------------------------------------------------+++-- | 'strokedDisk' : @ radius -> LocGraphic @+--+-- Create a stroked circle 'LocGraphic' - the implicit point is +-- the center. +-- +-- This is a efficient representation of circles using +-- PostScript\'s @arc@ or SVG\'s @circle@ in the generated +-- output. However, stroked-circles do not draw well after +-- non-uniform scaling - the pen width is scaled as well as +-- the shape.+--+-- For stroked circles that can be adequately scaled, use +-- 'strokedCircle' instead.+--+-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +strokedDisk :: Num u => u -> LocGraphic u+strokedDisk r = strokedEllipseDisk r r+++-- | 'filledDisk' : @ radius -> LocGraphic @+--+-- Create a filled circle 'LocGraphic' - the implicit point is +-- the center. +-- +-- This is a efficient representation of circles using +-- PostScript\'s @arc@ or SVG\'s @circle@ in the generated +-- output. As the circle is filled rather than drawn with a +-- \"pen\" a @filledDisk@ can be scaled. +--+-- The fill colour is taken from the implicit 'DrawingContext'.+-- +filledDisk :: Num u => u -> LocGraphic u+filledDisk r = filledEllipseDisk r r+++-- | 'borderedDisk' : @ radius -> LocGraphic @+--+-- Create a bordered circle 'LocGraphic' - the implicit point is +-- the center. +-- +-- This is a efficient representation of circles using +-- PostScript\'s @arc@ or SVG\'s @circle@ in the generated +-- output. However, bordereded circles do not draw well after +-- non-uniform scaling - the pen width of the outline is scaled as +-- well as the shape.+--+-- For bordered circles that can be adequately scaled, use +-- 'borderedCircle' instead.+--+-- The background fill colour and the outline stroke properties +-- are taken from the implicit 'DrawingContext'.+-- +borderedDisk :: Num u => u -> LocGraphic u+borderedDisk r = borderedEllipseDisk r r+++-- | 'strokedEllipseDisk' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a stroked ellipse 'LocGraphic' - the implicit point is +-- the center. +-- +-- This is a efficient representation of circles using +-- PostScript\'s @arc@ or SVG\'s @ellipse@ in the generated +-- output. However, stroked ellipses do not draw well after +-- non-uniform scaling - the pen width is scaled as well as +-- the shape.+--+-- For stroked ellipses that can be adequately scaled, use +-- 'strokedEllipse' instead.+--+-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +strokedEllipseDisk :: Num u => u -> u -> LocGraphic u+strokedEllipseDisk rx ry =+    promoteR1 $ \ pt -> +      withStrokeAttr $ \rgb attr -> +        graphicAns (strokeEllipse rgb attr rx ry pt)+++-- | 'filledEllipseDisk' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a filled ellipse 'LocGraphic' - the implicit point is +-- the center. +-- +-- This is a efficient representation of ellipses using +-- PostScript\'s @arc@ or SVG\'s @ellipse@ in the generated +-- output. As the ellipse is filled rather than drawn with a +-- \"pen\" a @filledEllipseDisk@ can be scaled. +--+-- The fill colour is taken from the implicit 'DrawingContext'.+-- +filledEllipseDisk :: Num u => u -> u -> LocGraphic u+filledEllipseDisk rx ry = +    promoteR1 $ \pt ->  +      withFillAttr $ \rgb -> graphicAns (fillEllipse rgb rx ry pt)+++-- | 'borderedEllipseDisk' : @ x_radius * y_radius -> LocGraphic @+--+-- Create a bordered ellipse 'LocGraphic' - the implicit point is +-- the center. +-- +-- This is a efficient representation of ellipses using +-- PostScript\'s @arc@ or SVG\'s @ellipse@ in the generated +-- output. However, bordereded ellipses do not draw well after +-- non-uniform scaling - the pen width of the outline is scaled as +-- well as the shape.+--+-- For bordered ellipses that can be adequately scaled, use +-- 'borderedEllipse' instead.+--+-- The background fill colour and the outline stroke properties +-- are taken from the implicit 'DrawingContext'.+-- +borderedEllipseDisk :: Num u => u -> u -> LocGraphic u+borderedEllipseDisk rx ry = +    promoteR1 $ \pt -> +      withBorderedAttr $ \frgb attr srgb -> +        graphicAns (fillStrokeEllipse frgb attr srgb rx ry pt)
src/Wumpus/Basic/Kernel/Objects/Graphic.hs view
@@ -5,7 +5,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Basic.Kernel.Objects.Graphic--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  stephen.tetley@gmail.com@@ -37,66 +37,33 @@   , DLocThetaGraphic    -- * Functions+  , safeconcat+  , ignoreAns+  , replaceAns+  , mapAns+   , intoImage   , intoLocImage   , intoLocThetaImage -  , moveStartPoint-  , moveStartPointTheta--  , locPath-  , emptyLocPath   , emptyLocGraphic---  , openStroke-  , closedStroke-  , filledPath-  , borderedPath--  , textline-  , rtextline-  , escapedline-  , rescapedline--  , hkernline-  , vkernline--  , strokedEllipse-  , rstrokedEllipse-  , filledEllipse-  , rfilledEllipse--  , borderedEllipse-  , rborderedEllipse--  , straightLine-  , straightLineBetween-  , curveBetween--  , strokedRectangle-  , filledRectangle-  , borderedRectangle+  , emptyLocThetaGraphic  -  , strokedCircle-  , filledCircle-  , borderedCircle+  , decorate+  , sdecorate+  , adecorate   -  , strokedDisk-  , filledDisk-  , borderedDisk+  , hyperlink    ) where -import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.BaseDefs-import Wumpus.Basic.Kernel.Base.QueryDC+import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.WrappedPrimitive import Wumpus.Basic.Kernel.Objects.BaseObjects  import Wumpus.Core                              -- package: wumpus-core -import Data.AffineSpace                         -- package: vector-space  import Control.Applicative @@ -143,336 +110,173 @@ -- Functions  --- | Build an Image...----intoImage :: CF a -> Graphic u -> Image u a-intoImage = liftA2 (\a (_,b) -> (a,b))----- | Build a LocImage...----intoLocImage :: LocCF u a -> LocGraphic u -> LocImage u a-intoLocImage = liftA2 (\a (_,b) -> (a,b))---- | Build a LocThetaImage...----intoLocThetaImage :: LocThetaCF u a -> LocThetaGraphic u -> LocThetaImage u a-intoLocThetaImage = liftA2 (\a (_,b) -> (a,b))----- | Move the start-point of a LocImage with the supplied --- displacement function.----moveStartPoint :: PointDisplace u -> LocCF u a -> LocCF u a-moveStartPoint f ma = promoteR1 $ \pt -> apply1R1 ma (f pt)----- | Move the start-point of a LocImage with the supplied --- displacement function.----moveStartPointTheta :: PointDisplace u -> LocThetaCF u a -> LocThetaCF u a-moveStartPointTheta f ma = promoteR2 $ \pt theta -> apply2R2 ma (f pt) theta--------------------------------------------------------------------------------------graphicBody :: Primitive u -> (UNil u, PrimGraphic u)-graphicBody p = (uNil, primGraphic p)----- | This is the analogue to 'vectorPath' in @Wumpus-core@.----locPath :: Num u => [Vec2 u] -> LocCF u (PrimPath u)-locPath vs = promoteR1 $ \pt  -> pure $ vectorPath pt vs----- | This is the analogue to 'emptyPath' in @Wumpus-core@.+-- | 'safeconcat' : @ alternative * [image] -> Image@+-- +-- 'safeconcat' produces a composite 'Image' from a list of +-- @Image@\'s. If the list is empty the alternative @Image@ is +-- used. ---emptyLocPath :: Num u => LocCF u (PrimPath u)-emptyLocPath = locPath []---- | Build an empty LocGraphic - this is a path with a start--- point but no path segments. +-- This contrasts to 'oconcat' - when used for @Image@\'s, +-- @oconcat@ has the same type signature as @safeconcat@ but +-- @oconcat@ considers its arguments to be an already destructured +-- list: -- --- The 'emptyLocGraphic' It is treated as a /null primitive/ by --- @Wumpus-Core@ and is not drawn, although it does generate a --- minimum bounding box at the implicit start point.+-- > oconcat (head::Image) (rest::[Image]) -- -emptyLocGraphic :: Num u => LocGraphic u-emptyLocGraphic = emptyLocPath >>= (lift0R1 . openStroke)----- | 'openStroke' : @ path -> Graphic @------ This is the analogue to 'ostroke' in @Wumpus-core@, but the --- drawing properties (colour, line width, etc.) are taken from --- the implicit 'DrawingContext'.----openStroke :: Num u => PrimPath u -> Graphic u-openStroke pp = -    withStrokeAttr $ \rgb attr -> graphicBody $ ostroke rgb attr pp+safeconcat :: OPlus a => Image u a -> [Image u a] -> Image u a+safeconcat _   (x:xs) = oconcat x xs+safeconcat alt []     = alt  --- | 'closedStroke' : @ path -> Graphic @+-- | Ignore the answer produced by an 'Image', a 'LocImage' etc. ----- This is the analogue to 'cstroke' in @Wumpus-core@, but the --- drawing properties (colour, line width, etc.) are taken from --- the implicit 'DrawingContext'.+-- Use this function to turn an 'Image' into a 'Graphic', a +-- 'LocImage into a 'LocGraphic'. ---closedStroke :: Num u => PrimPath u -> Graphic u-closedStroke pp = -    withStrokeAttr $ \rgb attr -> graphicBody $ cstroke rgb attr pp+ignoreAns :: Functor f => f (a,b) -> f (UNil u, b)+ignoreAns = fmap (replaceL uNil)  --- | 'filledPath' : @ path -> Graphic @--- --- This is the analogue to 'fill' in @Wumpus-core@, but the --- fill colour is taken from the implicit 'DrawingContext'.-------filledPath :: Num u => PrimPath u -> Graphic u-filledPath pp = withFillAttr $ \rgb -> graphicBody $ fill rgb pp-                 ---- | 'borderedPath' : @ path -> Graphic @------ This is the analogue to 'fillStroke' in @Wumpus-core@, but the --- drawing properties (fill colour, border colour, line width, --- etc.) are taken from the implicit 'DrawingContext'.---+-- | Replace the answer produced by an 'Image', a 'LocImage' etc. ---borderedPath :: Num u => PrimPath u -> Graphic u-borderedPath pp =-    withBorderedAttr $ \frgb attr srgb -> -      graphicBody $ fillStroke frgb attr srgb pp--+replaceAns :: Functor f => z -> f (a,b) -> f (z, b)+replaceAns = fmap . replaceL  --- | This is the analogue to 'textlabel' in @Wumpus-core@.+-- | Apply the supplied function to the answer produced by an +-- 'Image', a 'LocImage' etc. ---textline :: Num u => String -> LocGraphic u-textline ss = -    promoteR1 $ \pt -> -      withTextAttr $ \rgb attr -> graphicBody (textlabel rgb attr ss pt)--+mapAns :: Functor f => (a -> z) -> f (a,b) -> f (z,b)+mapAns f = fmap (\(a,b) -> (f a ,b))  --- | This is the analogue to 'rtextlabel' in @Wumpus-core@.+-- | 'intoImage' : @ context_function * graphic -> Image @ ---rtextline :: Num u => String -> LocThetaGraphic u-rtextline ss = -    promoteR2 $ \pt theta -> -      withTextAttr $ \rgb attr -> graphicBody (rtextlabel rgb attr ss theta pt)------ | This is the analogue to 'escapedlabel' in @Wumpus-core@.+-- Build an 'Image' from a context function ('CF') that generates +-- the answer and a 'Graphic' that draws the 'Image'. ---escapedline :: Num u => EscapedText -> LocGraphic u-escapedline ss = -    promoteR1 $ \pt -> -      withTextAttr $ \rgb attr -> graphicBody (escapedlabel rgb attr ss pt)-+intoImage :: CF a -> Graphic u -> Image u a+intoImage = liftA2 (\a (_,b) -> (a,b))  --- | This is the analogue to 'rescapedlabel' in @Wumpus-core@.+-- | 'intoLocImage' : @ loc_context_function * loc_graphic -> LocImage @ ---rescapedline :: Num u => EscapedText -> LocThetaGraphic u-rescapedline ss = -    promoteR2 $ \pt theta -> -      withTextAttr $ \rgb attr -> graphicBody (rescapedlabel rgb attr ss theta pt)------- | This is the analogue to 'hkernlabel' in @Wumpus-core@.+-- /Loc/ version of 'intoImage'. +-- +-- The 'LocImage' is built as a function from an implicit start +-- point to the answer. ---hkernline :: Num u => [KerningChar u] -> LocGraphic u-hkernline xs = -    promoteR1 $ \pt -> -      withTextAttr $ \rgb attr -> graphicBody (hkernlabel rgb attr xs pt)-+intoLocImage :: LocCF u a -> LocGraphic u -> LocImage u a+intoLocImage = liftA2 (\a (_,b) -> (a,b)) --- | This is the analogue to 'vkernlabel' in @Wumpus-core@.+-- | 'intoLocThetaImage' : @ loc_theta_cf * loc_theta_graphic -> LocThetaImage @ ---vkernline :: Num u => [KerningChar u] -> LocGraphic u-vkernline xs = -    promoteR1 $ \pt -> -      withTextAttr $ \rgb attr -> graphicBody (vkernlabel rgb attr xs pt)--------------------------------------------------------------------------------------------- | This is the analogue to 'strokeEllipse' in @Wumpus-core@.+-- /LocTheta/ version of 'intoImage'. +-- +-- The 'LocThetaImage' is built as a function from an implicit +-- start point and angle of inclination to the answer. ---strokedEllipse :: Num u => u -> u -> LocGraphic u-strokedEllipse hw hh =-    promoteR1 $ \pt -> -      withStrokeAttr $ \rgb attr -> graphicBody (strokeEllipse rgb attr hw hh pt)+intoLocThetaImage :: LocThetaCF u a -> LocThetaGraphic u -> LocThetaImage u a+intoLocThetaImage = liftA2 (\a (_,b) -> (a,b))   --- | This is the analogue to 'rstrokeEllispe' in @Wumpus-core@.----rstrokedEllipse :: Num u => u -> u -> LocThetaGraphic u-rstrokedEllipse hw hh = -    promoteR2 $ \ pt theta -> -      withStrokeAttr $ \rgb attr -> -        graphicBody (rstrokeEllipse rgb attr hw hh theta pt)----- | This is the analogue to 'fillEllispe' in @Wumpus-core@.----filledEllipse :: Num u => u -> u -> LocGraphic u-filledEllipse hw hh = -    promoteR1 $ \pt ->  -      withFillAttr $ \rgb -> graphicBody (fillEllipse rgb hw hh pt)----- | This is the analogue to 'rfillEllispe' in @Wumpus-core@.+-- | 'emptyLocGraphic' : @ LocGraphic @ ---rfilledEllipse :: Num u => u -> u -> LocThetaGraphic u-rfilledEllipse hw hh = -    promoteR2 $ \pt theta ->-      withFillAttr $ \rgb -> graphicBody (rfillEllipse rgb hw hh theta pt)+-- Build an empty 'LocGraphic' (i.e. a function +-- /from Point to Graphic/). This is a path with a start point +-- but no path segments. +-- +-- The 'emptyLocGraphic' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, although it does generate a +-- minimum bounding box at the implicit start point.+-- +emptyLocGraphic :: Num u => LocGraphic u+emptyLocGraphic = promoteR1 $ \pt -> +                    return $ (uNil, primGraphic $ zostroke $ emptyPath pt)   --- | This is the analogue to 'fillStrokeEllispe' in @Wumpus-core@.----borderedEllipse :: Num u => u -> u -> LocGraphic u-borderedEllipse hw hh =-    promoteR1 $ \pt -> -      withBorderedAttr $ \frgb attr srgb -> -        graphicBody (fillStrokeEllipse frgb attr srgb hw hh pt)---- | This is the analogue to 'rfillStrokeEllispe' in @Wumpus-core@.+-- | 'emptyLocThetaGraphic' : @ LocThetaGraphic @ ---rborderedEllipse :: Num u => u -> u -> LocThetaGraphic u-rborderedEllipse hw hh = -    promoteR2 $ \pt theta -> -      withBorderedAttr $ \frgb attr srgb -> -        graphicBody (rfillStrokeEllipse frgb attr srgb hw hh theta pt)------ Note - clipping needs a picture as well as a path, so there is--- no analogous @clippedPath@ function.--------------------------------------------------------------------------------------- | Draw a straight line formed from displacing the implicit --- start point with the supplied vector.+-- Build an empty 'LocThetaGraphic' (i.e. a function +-- /from Point and Inclination to Graphic/).  -- -straightLine :: Fractional u => Vec2 u -> LocGraphic u-straightLine v = mf >>= (lift0R1 . openStroke)-  where-    mf = promoteR1 $ \pt -> pure $ primPath pt [lineTo $ pt .+^ v]--          --- | Draw a straight line - start and end point are supplied --- explicitly.+-- The 'emptyLocThetaGraphic' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, although it does generate a +-- minimum bounding box at the implicit start point. -- -straightLineBetween :: Fractional u => Point2 u -> Point2 u -> Graphic u-straightLineBetween p1 p2 = openStroke $ primPath p1 [lineTo p2]+emptyLocThetaGraphic :: Num u => LocThetaGraphic u+emptyLocThetaGraphic = lift1R2 emptyLocGraphic   --- | Draw a Bezier curve - all points are supplied explicitly.--- -curveBetween :: Fractional u -             => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u-curveBetween sp cp1 cp2 ep = openStroke $ primPath sp [curveTo cp1 cp2 ep] ---- This is a permuted version of the cardinal-prime combinator...--- --- > (r2 -> a) -> (a -> r1 -> ans) -> (r1 -> r2 -> ans)+-- | Decorate an Image by superimposing a Graphic. ----drawWith :: (Point2 u -> PrimPath u) -> (PrimPath u -> Graphic u) -> LocGraphic u -drawWith g mf = promoteR1 $ \pt -> mf (g pt)----- | Supplied point is /bottom-left/.+-- Note - this function has a very general type signature and+-- supports various graphic types: ---rectanglePath :: Num u => u -> u -> Point2 u -> PrimPath u-rectanglePath w h bl = primPath bl [ lineTo br, lineTo tr, lineTo tl ]-  where-    br = bl .+^ hvec w-    tr = br .+^ vvec h-    tl = bl .+^ vvec h---- | Supplied point is /bottom left/.+-- > decorate :: Image u a -> Graphic u -> Image u a+-- > decorate :: LocImage u a -> LocGraphic u -> LocImage u a+-- > decorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a ---strokedRectangle :: Fractional u => u -> u -> LocGraphic u-strokedRectangle w h = rectanglePath w h `drawWith` closedStroke+decorate :: Monad m +         => m (ImageAns u a) -> m (ImageAns u zz) -> m (ImageAns u a) +decorate img gf = +    img >>= \(a,g1) -> gf >>= \(_,g2) -> return (a, g1 `oplus` g2)  --- | Supplied point is /bottom left/.----filledRectangle :: Fractional u => u -> u -> LocGraphic u-filledRectangle w h = rectanglePath w h `drawWith` filledPath --- | Supplied point is /bottom left/.+-- | /Anterior decorate/ - decorate an Image by superimposing it +-- on a Graphic. ---borderedRectangle :: Fractional u => u -> u -> LocGraphic u-borderedRectangle w h = rectanglePath w h `drawWith` borderedPath----- | Supplied point is center. Circle is drawn with Bezier --- curves. +-- Note - here the Graphic has access to the result produced by the +-- the Image unlike 'decorate'. ---strokedCircle :: Floating u => Int -> u -> LocGraphic u-strokedCircle n r = (curvedPath . bezierCircle n r) `drawWith` closedStroke ------ | Supplied point is center. Circle is drawn with Bezier --- curves. +-- Again, this function has a very general type signature and+-- supports various graphic types: ---filledCircle :: Floating u => Int -> u -> LocGraphic u-filledCircle n r =  (curvedPath . bezierCircle n r) `drawWith` filledPath------ | Supplied point is center. Circle is drawn with Bezier --- curves. +-- > adecorate :: Image u a -> Graphic u -> Image u a+-- > adecorate :: LocImage u a -> LocGraphic u -> LocImage u a+-- > adecorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a ---borderedCircle :: Floating u => Int -> u -> LocGraphic u-borderedCircle n r = (curvedPath . bezierCircle n r) `drawWith` borderedPath +adecorate :: Monad m +          => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)+adecorate img f = +    img >>= \(a,g1) -> f a >>= \(_,g0) -> return (a, g0 `oplus` g1)  --- | 'disk' is drawn with Wumpus-Core\'s @ellipse@ primitive.+-- | /Superior decorate/ - decorate an image by superimposing a +-- graphic on top of it. ----- This is a efficient representation of circles using --- PostScript\'s @arc@ or SVG\'s @circle@ in the generated --- output. However, stroked-circles do not draw well after --- non-uniform scaling - the line width is scaled as well as --- the shape.+-- Note, here the Graphic has access to the result produced by the +-- the Image unlike 'decorate'. ----- For stroked circles that can be adequately scaled, use --- 'strokedCircle' instead.+-- Again, this function has a very general type signature and+-- supports various graphic types: ---strokedDisk :: Num u => u -> LocGraphic u-strokedDisk radius = strokedEllipse radius radius---- | Filled disk...+-- > sdecorate :: Image u a -> Graphic u -> Image u a+-- > sdecorate :: LocImage u a -> LocGraphic u -> LocImage u a+-- > sdecorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a ---filledDisk :: Num u => u -> LocGraphic u-filledDisk radius = filledEllipse radius radius+sdecorate :: Monad m +          => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)+sdecorate img f = +    img >>= \(a,g1) -> f a >>= \(_,g2) -> return (a, g1 `oplus` g2) --- | bordered disk...++-- | Hyperlink a graphic object.+-- +-- This function has a very general type signature and supports +-- various graphic types: ---borderedDisk :: Num u => u -> LocGraphic u-borderedDisk radius = borderedEllipse radius radius+-- > hyperlink :: XLink -> Graphic u -> Graphic u+-- > hyperlink :: XLink -> Image u a -> Image u a+-- > hyperlink :: XLink -> LocImage u a -> LocImage u a+-- > hyperlink :: XLink -> LocThetaImage u a -> LocThetaImage u a+--+hyperlink :: Functor m => XLink -> m (ImageAns u a) -> m (ImageAns u a)+hyperlink hypl = +    fmap (\(a,prim) -> (a, metamorphPrim (xlink hypl) prim))+
+ src/Wumpus/Basic/Kernel/Objects/PosImage.hs view
@@ -0,0 +1,237 @@+{-# LANGUAGE TypeFamilies               #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Basic.Kernel.Objects.PosImage+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  highly unstable+-- Portability :  GHC +--+-- Extended Graphic object - a rectangular /positionable/ Image.+-- +-- This graphic object has a more flexible API for positioning +-- than other graphic objects. Rather than a LocGraphic which +-- supports a single method of positioning at some start-point,+-- a @PosGraphic@ can be drawn at its center or locations on its +-- outer rectangle.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.PosImage+  (++    RectPosition(..)+  , ObjectPos(..)++  -- * Positionable image++  , PosImage+  , DPosImage ++  , PosGraphic+  , DPosGraphic++  , makePosImage++  , startPos+  , atStartPos++  , objectPosBounds++  ) where+++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Objects.BaseObjects+import Wumpus.Basic.Kernel.Objects.Displacement++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space++-- | Datatype enumerating positions within a rectangle that can be+-- derived for a 'PosGraphic'.  +--+data RectPosition = CENTER | NN | SS | EE | WW | NE | NW | SE | SW +  deriving (Enum,Eq,Ord,Show)+++-- | Utility datatype representing orientation within a +-- rectangular /frame/. ObjectPos is useful for graphics such as +-- text where the start point is not necessarily at the center +-- (or bottom left).+--+-- > x_minor is the horizontal distance from the left to the start point+-- >+-- > x_major is the horizontal distance from the start point to the right+-- >+-- > y_minor is the vertical distance from the bottom to the start point+-- >+-- > y_major is the vertical distance from the start point to the top+--+-- Values should be not be negative!+--+-- +data ObjectPos u = ObjectPos +      { op_x_minor      :: !u+      , op_x_major      :: !u+      , op_y_minor      :: !u+      , op_y_major      :: !u+      }+  deriving (Eq,Ord,Show)++++type instance DUnit (ObjectPos u)   = u++++-- | A positionable Image.+--+type PosImage u a = CF2  (Point2 u) RectPosition (ImageAns u a)+    +-- | Version of PosImage specialized to Double for the unit type.+--+type DPosImage a = PosImage Double a++++-- | A positionable Graphic.+--+type PosGraphic u = PosImage u (UNil u) +    +-- | Version of PosGraphic specialized to Double for the unit type.+--+type DPosGraphic = PosGraphic Double+++++++--------------------------------------------------------------------------------+++instance (Fractional u, Ord u) => OPlus (ObjectPos u) where+  oplus = concatObjectPos+++-- | Concatenation here essentially turns both ObjectPos objects+-- into /center-form/ then finds the maximum rectangle.+--+concatObjectPos :: (Fractional u, Ord u) +                => ObjectPos u -> ObjectPos u -> ObjectPos u+concatObjectPos op0 op1 = ObjectPos hw hw hh hh+  where+    (hw0,hh0) = halfDists op0+    (hw1,hh1) = halfDists op1+    hw        = max hw0 hw1+    hh        = max hh0 hh1++++--------------------------------------------------------------------------------+++-- | Find the half-width and half-height of an ObjectPos.+-- +-- Essentially this is /center-form/ of an ObjectPos, but +-- in /center-form/ there is duplication: +--+-- > xminor == xmajor+-- > yminor == ymajor+-- +-- So instead, the result type is just a pair.+--+halfDists :: Fractional u => ObjectPos u -> (u,u)+halfDists (ObjectPos xmin xmaj ymin ymaj) = +    (0.5 * (xmin+xmaj), 0.5 * (ymin+ymaj))+++-- | 'makePosImage' : @ object_pos * loc_graphic -> PosGraphic @ +--+-- Create a 'PosImage' from an 'ObjectPos' describing how it+-- is orientated within a border rectangle and a 'LocImage' that +-- draws it.+--+makePosImage :: Fractional u +             => ObjectPos u -> LocImage u a -> PosImage u a+makePosImage opos gf = promoteR2 $ \start rpos -> +    let v1 = startVector rpos opos in gf `at` displaceVec v1 start++++infixr 1 `startPos`++-- | 'startPos' : @ pos_image * rect_pos -> LocImage @+--+-- /Downcast/ a 'PosImage' to a 'LocImage' by supplying it +-- with a 'RectPosition' (start position).+--  +startPos :: Floating u +         => PosImage u a -> RectPosition -> LocImage u a+startPos = apply1R2+ +-- | 'atStartPos' : @ pos_image * start_point * rect_pos -> LocImage @+--+-- /Downcast/ a 'PosGraphic' to an 'Image' by supplying it +-- with an initial point and a 'RectPosition' (start position).+--  +atStartPos ::  Floating u +           => PosImage u a -> Point2 u -> RectPosition -> Image u a+atStartPos = apply2R2++-- | The vector from some Rectangle position to the start point.+--+startVector :: Fractional u => RectPosition -> ObjectPos u -> Vec2 u+startVector rpos (ObjectPos xminor xmajor yminor ymajor) = go rpos+  where+    w         = xminor + xmajor+    h         = yminor + ymajor+    hw        = 0.5 * w+    hh        = 0.5 * h+    +    -- CENTER, NN, SS, EE, WW all go to bottomleft then add back +    -- the minors.++    go CENTER = V2 ((-hw) + xminor) ((-hh) + yminor)+    go NN     = V2 ((-hw) + xminor) ((-h)  + yminor)+    go SS     = V2 ((-hw) + xminor)  yminor+    go EE     = V2 ((-w)  + xminor) ((-hh) + yminor)+    go WW     = V2 xminor           ((-hh) + yminor)+    go NE     = V2 (-xmajor)        (-ymajor)+    go SE     = V2 (-xmajor)          yminor+    go SW     = V2 xminor           yminor+    go NW     = V2 xminor           (-ymajor)++++-- | Calculate the bounding box formed by locating the 'ObjectPos'+-- at the supplied point.+-- +objectPosBounds :: Fractional u +                => Point2 u -> RectPosition -> ObjectPos u -> BoundingBox u+objectPosBounds (P2 x y) pos (ObjectPos xmin xmaj ymin ymaj) = go pos+  where+    w         = xmin + xmaj+    h         = ymin + ymaj+    hw        = 0.5 * w+    hh        = 0.5 * h+    bbox      = \bl -> BBox bl (bl .+^ vec w h)++    go CENTER = bbox $ P2 (x-hw) (y-hh)+    go NN     = bbox $ P2 (x-hw) (y-h)+    go SS     = bbox $ P2 (x-hw)  y+    go EE     = bbox $ P2 (x-w)  (y-hh)+    go WW     = bbox $ P2  x     (y-hh)+    go NE     = bbox $ P2 (x-w)  (y-h)+    go SE     = bbox $ P2 (x-w)   y+    go SW     = bbox $ P2 x       y+    go NW     = bbox $ P2 x      (y-h)++
src/Wumpus/Basic/System/FontLoader/Afm.hs view
@@ -76,6 +76,7 @@ afm_mono_defaults_4_1 =      MonospaceDefaults { default_letter_bbox  = bbox                       , default_cap_height   = 562+                      , default_descender    = (-157)                       , default_char_width   = V2 600 0                       }   where
src/Wumpus/Basic/System/FontLoader/Base/AfmParserBase.hs view
@@ -71,6 +71,7 @@               { afm_encoding        = getEncodingScheme info               , afm_letter_bbox     = getFontBBox       info               , afm_cap_height      = getCapHeight      info+              , afm_descender       = getDescender      info               , afm_glyph_metrics   = cms               } @@ -101,6 +102,9 @@  getCapHeight           :: GlobalInfo -> Maybe AfmUnit getCapHeight           = runQuery "CapHeight" number++getDescender           :: GlobalInfo -> Maybe AfmUnit+getDescender           = runQuery "Descender" number   charBBox :: CharParser AfmBoundingBox
src/Wumpus/Basic/System/FontLoader/Base/Datatypes.hs view
@@ -46,8 +46,8 @@  import Wumpus.Core                              -- package: wumpus-core -import qualified Data.IntMap   as IntMap-import qualified Data.Map as Map+import qualified Data.IntMap   as IM+import qualified Data.Map      as M   @@ -87,7 +87,7 @@ type AfmBoundingBox     = BoundingBox AfmUnit  type AfmKey         = String-type GlobalInfo     = Map.Map AfmKey String+type GlobalInfo     = M.Map AfmKey String   @@ -106,6 +106,7 @@       { afm_encoding        :: Maybe String       , afm_letter_bbox     :: Maybe AfmBoundingBox       , afm_cap_height      :: Maybe AfmUnit+      , afm_descender       :: Maybe AfmUnit       , afm_glyph_metrics   :: [AfmGlyphMetrics]       }   deriving (Show) @@ -132,6 +133,7 @@ data MonospaceDefaults cu = MonospaceDefaults        { default_letter_bbox  :: BoundingBox cu       , default_cap_height   :: cu+      , default_descender    :: cu       , default_char_width   :: Vec2 cu       }   deriving (Eq,Show)@@ -150,8 +152,9 @@ data FontProps cu = FontProps        { fp_bounding_box        :: BoundingBox cu         , fp_default_adv_vec     :: Vec2 cu-       , fp_adv_vecs            :: IntMap.IntMap (Vec2 cu)+       , fp_adv_vecs            :: IM.IntMap (Vec2 cu)        , fp_cap_height          :: cu+       , fp_descender           :: cu        }  @@ -159,13 +162,14 @@ -- scaling function and FontProps read from a file. -- buildMetricsOps :: (cu -> PtSize) -> FontProps cu -> MetricsOps-buildMetricsOps fn (FontProps (BBox ll ur) (V2 vx vy) -                              vec_table    cap_height) = +buildMetricsOps fn font@(FontProps { fp_bounding_box = BBox ll ur+                                   , fp_default_adv_vec = V2 vx vy }) =      MetricsOps       { get_bounding_box  = \sz -> BBox (scalePt sz ll) (scalePt sz ur)       , get_cw_table      = \sz i -> -            maybe (defaultAV sz) (scaleVec sz) $ IntMap.lookup i vec_table -      , get_cap_height    = \sz -> upscale sz (fn cap_height)+            maybe (defaultAV sz) (scaleVec sz) $ IM.lookup i (fp_adv_vecs font)+      , get_cap_height    = \sz -> upscale sz (fn $ fp_cap_height font)+      , get_descender     = \sz -> upscale sz (fn $ fp_descender font)       }   where     upscale sz d            = fromPtSize $ sz * d 
src/Wumpus/Basic/System/FontLoader/Base/FontLoadMonad.hs view
@@ -164,13 +164,15 @@                   -> AfmFile                    -> FontLoadIO (FontProps AfmUnit) buildAfmFontProps defaults afm = do -    cap_height <- extractCapHeight defaults afm-    bbox       <- extractFontBBox  defaults afm +    cap_height  <- extractCapHeight defaults afm+    desc_depth  <- extractDescender defaults afm+    bbox        <- extractFontBBox  defaults afm      return $ FontProps                 { fp_bounding_box    = bbox                , fp_default_adv_vec = default_char_width defaults                , fp_adv_vecs        = char_widths                , fp_cap_height      = cap_height+               , fp_descender       = desc_depth                }     where     char_widths = foldr fn IntMap.empty $ afm_glyph_metrics afm@@ -185,6 +187,14 @@   where     errk = logLoadMsg "WARNING - Could not extract CapHeight" >>             return (default_cap_height defaults)++++extractDescender :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO AfmUnit+extractDescender defaults afm = maybe errk return $ afm_descender afm+  where+    errk = logLoadMsg "WARNING - Could not extract Descender" >> +           return (default_descender defaults)   extractFontBBox :: MonospaceDefaults AfmUnit -> AfmFile 
src/Wumpus/Basic/System/FontLoader/GhostScript.hs view
@@ -80,6 +80,7 @@ ghostscript_mono_defaults_8_54 =      MonospaceDefaults { default_letter_bbox  = bbox                       , default_cap_height   = 563+                      , default_descender    = (-186)                       , default_char_width   = V2 600 0                       }   where
src/Wumpus/Basic/VersionNumber.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Basic.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,15,0)+-- > (0,16,0) -- wumpus_basic_version :: (Int,Int,Int)-wumpus_basic_version = (0,15,0)+wumpus_basic_version = (0,16,0)
wumpus-basic.cabal view
@@ -1,5 +1,5 @@ name:             wumpus-basic-version:          0.15.0+version:          0.16.0 license:          BSD3 license-file:     LICENSE copyright:        Stephen Tetley <stephen.tetley@gmail.com>@@ -30,6 +30,32 @@   .   Changelog:   .+  v0.15.0 to v0.16.0:+  .+  * Moved the Geometry modules from Wumpus-Drawing into +    Wumpus-Basic.+  .+  * Re-worked the @CtxPicture@ API, although the current naming +    scheme is not satisfactory.+  .+  * Added extra Anchor classes.+  .+  * Added @PosImage@ object - this is a rectangle-framed object +    that can be drawn from any of its corners or its center. +  .+  * Added @Displacement@ module. This defines the @PointDisplace@+    type and provides a library of @PointDisplace@ functions.+    Note - some of the new functions have taken names previously +    used for anchor projection functions (@northwards@, +    @southwards@, etc.), anchor projections are now build with the +    function @projectAnchor@.+  .+  * Added the property @descender@ to the font metrics.+  .+  * Split drawing primitives from type in @Objects.Graphic@, +    drawing primitives are now in the module +    @Objects.DrawingPrimitives@.+  .   v0.14.0 to v0.15.0:   .    * Split previous @Wumpus-Basic@ package into two packages:@@ -59,7 +85,9 @@ extra-source-files:   CHANGES,   LICENSE,-  demo/FontDeltaPic.hs+  demo/FontDeltaPic.hs,+  demo/SimpleAdvGraphic.hs,+  demo/SimplePosImage.hs  library   hs-source-dirs:     src@@ -68,10 +96,14 @@                       directory       >= 1.0     && <  2.0,                        filepath        >= 1.1     && <  2.0,                       vector-space    >= 0.6     && <  1.0,-                      wumpus-core     >= 0.42.0  && <  0.43.0+                      wumpus-core     >= 0.43.0  && <  0.44.0       exposed-modules:+    Wumpus.Basic.Geometry.Base,+    Wumpus.Basic.Geometry.Intersection,+    Wumpus.Basic.Geometry.Paths,+    Wumpus.Basic.Geometry.Quadrant,     Wumpus.Basic.Kernel,     Wumpus.Basic.Kernel.Base.Anchors,     Wumpus.Basic.Kernel.Base.BaseDefs,@@ -87,7 +119,10 @@     Wumpus.Basic.Kernel.Objects.Bounded,     Wumpus.Basic.Kernel.Objects.Connector,     Wumpus.Basic.Kernel.Objects.CtxPicture,+    Wumpus.Basic.Kernel.Objects.Displacement,+    Wumpus.Basic.Kernel.Objects.DrawingPrimitives,     Wumpus.Basic.Kernel.Objects.Graphic,+    Wumpus.Basic.Kernel.Objects.PosImage,     Wumpus.Basic.Kernel.Objects.TraceDrawing,     Wumpus.Basic.System.FontLoader.Afm,     Wumpus.Basic.System.FontLoader.GhostScript,