wumpus-drawing 0.3.0 → 0.4.0
raw patch · 61 files changed
+3124/−3099 lines, 61 filesdep ~wumpus-basicdep ~wumpus-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: wumpus-basic, wumpus-core
API changes (from Hackage documentation)
- Wumpus.Drawing.Connectors.Base: makeArrowTip :: Query u -> Query u -> LocThetaGraphic En -> ArrowTip u
- Wumpus.Drawing.Connectors.Base: promoteConn :: (Real u, Floating u, InterpretUnit u) => (Point2 u -> Point2 u -> CF a) -> CF (Point2 u -> Point2 u -> a)
- Wumpus.Drawing.Connectors.Loop: loop :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorQuery u (AbsPath u)
- Wumpus.Drawing.Connectors.Loop: loopPoints :: (Real u, Floating u) => u -> Point2 u -> Radian -> [Point2 u]
- Wumpus.Drawing.Dots.Marks: markAsterisk :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markChar :: (Real u, Floating u, InterpretUnit u) => Char -> LocGraphic u
- Wumpus.Drawing.Dots.Marks: markCircle :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markCross :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markDisk :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markFOCross :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markHLine :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markOCross :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markOPlus :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markPentagon :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markPlus :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markSquare :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markStar :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markText :: (Real u, Floating u, InterpretUnit u) => String -> LocGraphic u
- Wumpus.Drawing.Dots.Marks: markTriangle :: (Floating u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markVLine :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Dots.Marks: markX :: (Fractional u, InterpretUnit u) => LocGraphic u
- Wumpus.Drawing.Extras.Turtle.TurtleClass: class Monad m => TurtleM m
- Wumpus.Drawing.Extras.Turtle.TurtleClass: getLoc :: TurtleM m => m (Int, Int)
- Wumpus.Drawing.Extras.Turtle.TurtleClass: getOrigin :: TurtleM m => m (Int, Int)
- Wumpus.Drawing.Extras.Turtle.TurtleClass: moveDown :: TurtleM m => m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: moveLeft :: TurtleM m => m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: moveRight :: TurtleM m => m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: moveUp :: TurtleM m => m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: nextLine :: TurtleM m => m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: resetLoc :: TurtleM m => m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: setLoc :: TurtleM m => (Int, Int) -> m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: setOrigin :: TurtleM m => (Int, Int) -> m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: setsLoc :: TurtleM m => (Coord -> (a, Coord)) -> m a
- Wumpus.Drawing.Extras.Turtle.TurtleClass: setsLoc_ :: TurtleM m => (Coord -> Coord) -> m ()
- Wumpus.Drawing.Extras.Turtle.TurtleClass: type Coord = (Int, Int)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: data TurtleT u m a
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance (u ~ MonUnit (m ()), Monad m, TraceM m) => TraceM (TurtleT u m)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance DrawingCtxM m => DrawingCtxM (TurtleT u m)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => Applicative (TurtleT u m)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => Functor (TurtleT u m)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => Monad (TurtleT u m)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: instance Monad m => TurtleM (TurtleT u m)
- Wumpus.Drawing.Extras.Turtle.TurtleMonad: runTurtleT :: (Monad m, Num u) => (Int, Int) -> TurtleT u m a -> m a
- Wumpus.Drawing.Paths.Base.AbsBuilder: abscurve :: (Floating u, Ord u, Tolerance u) => Point2 u -> Point2 u -> Point2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: absline :: Floating u => Point2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: absmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Point2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: aline :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: amove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: ctrlcurve :: (Floating u, Ord u, Tolerance u) => Radian -> Radian -> Point2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: cycle :: (Floating u, InterpretUnit u) => AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: data AbsBuild u a
- Wumpus.Drawing.Paths.Base.AbsBuilder: evalAbsBuild :: (Floating u, InterpretUnit u) => Point2 u -> AbsBuild u a -> AbsPath u
- Wumpus.Drawing.Paths.Base.AbsBuilder: execAbsBuild :: (Floating u, InterpretUnit u) => Point2 u -> AbsBuild u a -> Graphic u
- Wumpus.Drawing.Paths.Base.AbsBuilder: hline :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: hmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: insert :: Num u => LocGraphic u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: instance Applicative (AbsBuild u)
- Wumpus.Drawing.Paths.Base.AbsBuilder: instance Functor (AbsBuild u)
- Wumpus.Drawing.Paths.Base.AbsBuilder: instance Monad (AbsBuild u)
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_down :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_down_left :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_down_right :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_east :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_left :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_north :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_northeast :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_northwest :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_right :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_south :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_southeast :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_southwest :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_up :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_up_left :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_up_right :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: line_west :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_down :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_down_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_down_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_east :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_north :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_northeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_northwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_south :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_southeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_southwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_up :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_up_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_up_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: move_west :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: pen_colour :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => RGBi -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: pen_width :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Double -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: relcurve :: (Floating u, Ord u, Tolerance u) => Vec2 u -> Vec2 u -> Vec2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: relline :: Floating u => Vec2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: rellineParallel :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: rellinePerpendicular :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: relmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Vec2 u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: relmoveParallel :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: relmovePerpendicular :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: runAbsBuild :: (Floating u, InterpretUnit u) => Point2 u -> AbsBuild u a -> (AbsPath u, Graphic u)
- Wumpus.Drawing.Paths.Base.AbsBuilder: setIncline :: Radian -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: tip :: AbsBuild u (Point2 u)
- Wumpus.Drawing.Paths.Base.AbsBuilder: vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Vamp u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: vline :: Floating u => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.AbsBuilder: vmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => u -> AbsBuild u ()
- Wumpus.Drawing.Paths.Base.BuildCommon: PATH_CLOSED :: PathEnd
- Wumpus.Drawing.Paths.Base.BuildCommon: PATH_OPEN :: PathEnd
- Wumpus.Drawing.Paths.Base.BuildCommon: Vamp :: Vec2 u -> Vec2 u -> DrawingContextF -> RelPath u -> PathEnd -> Vamp u
- Wumpus.Drawing.Paths.Base.BuildCommon: addInsert :: a -> BuildLog a -> BuildLog a
- Wumpus.Drawing.Paths.Base.BuildCommon: addPen :: a -> BuildLog a -> BuildLog a
- Wumpus.Drawing.Paths.Base.BuildCommon: data BuildLog a
- Wumpus.Drawing.Paths.Base.BuildCommon: data PathEnd
- Wumpus.Drawing.Paths.Base.BuildCommon: data Vamp u
- Wumpus.Drawing.Paths.Base.BuildCommon: extractTrace :: OPlus a => a -> BuildLog a -> (a, a)
- Wumpus.Drawing.Paths.Base.BuildCommon: insert1 :: a -> BuildLog a
- Wumpus.Drawing.Paths.Base.BuildCommon: instance Eq PathEnd
- Wumpus.Drawing.Paths.Base.BuildCommon: instance Monoid (BuildLog a)
- Wumpus.Drawing.Paths.Base.BuildCommon: instance Show PathEnd
- Wumpus.Drawing.Paths.Base.BuildCommon: pen1 :: a -> BuildLog a
- Wumpus.Drawing.Paths.Base.BuildCommon: vamp_dc_update :: Vamp u -> DrawingContextF
- Wumpus.Drawing.Paths.Base.BuildCommon: vamp_deco_path :: Vamp u -> RelPath u
- Wumpus.Drawing.Paths.Base.BuildCommon: vamp_move_span :: Vamp u -> Vec2 u
- Wumpus.Drawing.Paths.Base.BuildCommon: vamp_move_start :: Vamp u -> Vec2 u
- Wumpus.Drawing.Paths.Base.BuildCommon: vamp_path_end :: Vamp u -> PathEnd
- Wumpus.Drawing.Paths.Base.RelBuilder: aline :: Floating u => Radian -> u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: amove :: (Floating u, InterpretUnit u) => Radian -> u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: curve :: Floating u => Vec2 u -> Vec2 u -> Vec2 u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: cycle :: (Floating u, InterpretUnit u) => RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: data RelBuild u a
- Wumpus.Drawing.Paths.Base.RelBuilder: evalRelBuild :: (Floating u, InterpretUnit u) => RelBuild u a -> RelPath u
- Wumpus.Drawing.Paths.Base.RelBuilder: execPivot :: (Floating u, InterpretUnit u) => RelBuild u a -> LocGraphic u
- Wumpus.Drawing.Paths.Base.RelBuilder: execRelBuild :: (Floating u, InterpretUnit u) => RelBuild u a -> LocGraphic u
- Wumpus.Drawing.Paths.Base.RelBuilder: hline :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: hmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: insert :: Num u => LocGraphic u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: instance Applicative (RelBuild u)
- Wumpus.Drawing.Paths.Base.RelBuilder: instance Functor (RelBuild u)
- Wumpus.Drawing.Paths.Base.RelBuilder: instance Monad (RelBuild u)
- Wumpus.Drawing.Paths.Base.RelBuilder: line :: Floating u => Vec2 u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_down :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_down_left :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_down_right :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_east :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_left :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_north :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_northeast :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_northwest :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_right :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_south :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_southeast :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_southwest :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_up :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_up_left :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_up_right :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: line_west :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move :: (Floating u, InterpretUnit u) => Vec2 u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_down :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_down_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_down_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_east :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_north :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_northeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_northwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_south :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_southeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_southwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_up :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_up_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_up_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: move_west :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: pen_colour :: (Floating u, InterpretUnit u) => RGBi -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: pen_width :: (Floating u, InterpretUnit u) => Double -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: pivot :: RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: runRelBuild :: (Floating u, InterpretUnit u) => RelBuild u a -> (RelPath u, LocGraphic u)
- Wumpus.Drawing.Paths.Base.RelBuilder: setIncline :: Radian -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: tip :: RelBuild u (Vec2 u)
- Wumpus.Drawing.Paths.Base.RelBuilder: vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) => Vamp u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: vline :: Floating u => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelBuilder: vmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()
- Wumpus.Drawing.Paths.Base.RelPath: instance Monoid (RelPath u)
- Wumpus.Drawing.Paths.Base.RelPath: strokeRelPath :: InterpretUnit u => RelPath u -> LocGraphic u
- Wumpus.Drawing.Paths.Vamps: PATH_CLOSED :: PathEnd
- Wumpus.Drawing.Paths.Vamps: PATH_OPEN :: PathEnd
- Wumpus.Drawing.Paths.Vamps: Vamp :: Vec2 u -> Vec2 u -> DrawingContextF -> RelPath u -> PathEnd -> Vamp u
- Wumpus.Drawing.Paths.Vamps: circleVamp :: (Fractional u, Floating u) => Vec2 u -> Vamp u
- Wumpus.Drawing.Paths.Vamps: data PathEnd
- Wumpus.Drawing.Paths.Vamps: data Vamp u
- Wumpus.Drawing.Paths.Vamps: vamp_dc_update :: Vamp u -> DrawingContextF
- Wumpus.Drawing.Paths.Vamps: vamp_deco_path :: Vamp u -> RelPath u
- Wumpus.Drawing.Paths.Vamps: vamp_move_span :: Vamp u -> Vec2 u
- Wumpus.Drawing.Paths.Vamps: vamp_move_start :: Vamp u -> Vec2 u
- Wumpus.Drawing.Paths.Vamps: vamp_path_end :: Vamp u -> PathEnd
- Wumpus.Drawing.Shapes.Parallelogram: instance Functor SyntheticProps
- Wumpus.Drawing.Shapes.Semicircle: instance Functor SyntheticProps
- Wumpus.Drawing.Shapes.Semiellipse: instance Functor SyntheticProps
- Wumpus.Drawing.Shapes.Trapezium: ztrapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Trapezium u
- Wumpus.Drawing.Shapes.Triangle: instance Functor SyntheticProps
+ Wumpus.Drawing.Basis.DrawingPrimitives: arc :: (Floating u, InterpretUnit u) => u -> Radian -> LocThetaGraphic u
+ Wumpus.Drawing.Basis.DrawingPrimitives: blRectangle :: InterpretUnit u => DrawStyle -> u -> u -> LocGraphic u
+ Wumpus.Drawing.Basis.DrawingPrimitives: ctrRectangle :: (Fractional u, InterpretUnit u) => DrawStyle -> u -> u -> LocGraphic u
+ Wumpus.Drawing.Basis.DrawingPrimitives: hline :: InterpretUnit u => u -> LocGraphic u
+ Wumpus.Drawing.Basis.DrawingPrimitives: pivotLine :: (Floating u, InterpretUnit u) => u -> u -> Radian -> LocGraphic u
+ Wumpus.Drawing.Basis.DrawingPrimitives: vline :: InterpretUnit u => u -> LocGraphic u
+ Wumpus.Drawing.Basis.DrawingPrimitives: wedge :: (Floating u, InterpretUnit u) => DrawStyle -> u -> Radian -> LocThetaGraphic u
+ Wumpus.Drawing.Basis.LocTrace: branch :: LocForkTraceM m => m a -> m a
+ Wumpus.Drawing.Basis.LocTrace: class LocTraceM m => LocForkTraceM m :: (* -> *)
+ Wumpus.Drawing.Basis.LocTrace: class Monad m => LocTraceM m :: (* -> *)
+ Wumpus.Drawing.Basis.LocTrace: data LocTrace u a
+ Wumpus.Drawing.Basis.LocTrace: data LocTraceT u m a
+ Wumpus.Drawing.Basis.LocTrace: evalLocTrace :: Num u => LocTrace u a -> a
+ Wumpus.Drawing.Basis.LocTrace: evalLocTraceT :: (Monad m, Num u) => LocTraceT u m a -> m a
+ Wumpus.Drawing.Basis.LocTrace: execLocTrace :: Num u => LocTrace u a -> LocGraphic u
+ Wumpus.Drawing.Basis.LocTrace: execLocTraceT :: (Monad m, Num u) => LocTraceT u m a -> m (LocGraphic u)
+ Wumpus.Drawing.Basis.LocTrace: hmoveBy :: (LocTraceM m, Num u, u ~ (MonUnit (m ()))) => u -> m ()
+ Wumpus.Drawing.Basis.LocTrace: insertl :: (LocTraceM m, (MonUnit (m ())) ~ u) => LocGraphic u -> m ()
+ Wumpus.Drawing.Basis.LocTrace: insertl_ :: (LocTraceM m, (MonUnit (m ())) ~ u) => LocImage u a -> m ()
+ Wumpus.Drawing.Basis.LocTrace: instance (LocTraceM m, Num u) => LocForkTraceM (LocTraceT u m)
+ Wumpus.Drawing.Basis.LocTrace: instance (Monad m, Num u) => LocTraceM (LocTraceT u m)
+ Wumpus.Drawing.Basis.LocTrace: instance Applicative (LocTrace u)
+ Wumpus.Drawing.Basis.LocTrace: instance Functor (LocTrace u)
+ Wumpus.Drawing.Basis.LocTrace: instance Monad (LocTrace u)
+ Wumpus.Drawing.Basis.LocTrace: instance Monad m => Applicative (LocTraceT u m)
+ Wumpus.Drawing.Basis.LocTrace: instance Monad m => Functor (LocTraceT u m)
+ Wumpus.Drawing.Basis.LocTrace: instance Monad m => Monad (LocTraceT u m)
+ Wumpus.Drawing.Basis.LocTrace: instance Num u => LocForkTraceM (LocTrace u)
+ Wumpus.Drawing.Basis.LocTrace: instance Num u => LocTraceM (LocTrace u)
+ Wumpus.Drawing.Basis.LocTrace: liftLocTraceT :: Monad m => m a -> LocTraceT u m a
+ Wumpus.Drawing.Basis.LocTrace: location :: (LocTraceM m, (MonUnit (m ())) ~ u) => m (Vec2 u)
+ Wumpus.Drawing.Basis.LocTrace: moveBy :: (LocTraceM m, (MonUnit (m ())) ~ u) => Vec2 u -> m ()
+ Wumpus.Drawing.Basis.LocTrace: reset :: LocForkTraceM m => m ()
+ Wumpus.Drawing.Basis.LocTrace: runLocTrace :: Num u => LocTrace u a -> (a, Vec2 u, LocGraphic u)
+ Wumpus.Drawing.Basis.LocTrace: runLocTraceT :: (Monad m, Num u) => LocTraceT u m a -> m (a, Vec2 u, LocGraphic u)
+ Wumpus.Drawing.Basis.LocTrace: vmoveBy :: (LocTraceM m, Num u, u ~ (MonUnit (m ()))) => u -> m ()
+ Wumpus.Drawing.Basis.RefTrace: binaryLink :: (ans -> Point2 u) -> (ans -> Point2 u) -> ConnectorGraphic u -> Ref -> Ref -> LinkRef u ans
+ Wumpus.Drawing.Basis.RefTrace: class Monad m => LocTraceM m :: (* -> *)
+ Wumpus.Drawing.Basis.RefTrace: class Monad m => RefTraceM m :: (* -> *) where { type family MonRef m :: *; }
+ Wumpus.Drawing.Basis.RefTrace: data Ref
+ Wumpus.Drawing.Basis.RefTrace: data RefTrace u z a
+ Wumpus.Drawing.Basis.RefTrace: data RefTraceT u z m a
+ Wumpus.Drawing.Basis.RefTrace: insertRef :: (RefTraceM m, (MonRef m) ~ a, (MonUnit (m ())) ~ u) => LocImage u a -> m Ref
+ Wumpus.Drawing.Basis.RefTrace: insertl :: (LocTraceM m, (MonUnit (m ())) ~ u) => LocGraphic u -> m ()
+ Wumpus.Drawing.Basis.RefTrace: insertl_ :: (LocTraceM m, (MonUnit (m ())) ~ u) => LocImage u a -> m ()
+ Wumpus.Drawing.Basis.RefTrace: instance (Monad m, Num u) => LocTraceM (RefTraceT u z m)
+ Wumpus.Drawing.Basis.RefTrace: instance Applicative (RefTrace u z)
+ Wumpus.Drawing.Basis.RefTrace: instance Functor (RefTrace u z)
+ Wumpus.Drawing.Basis.RefTrace: instance Monad (RefTrace u z)
+ Wumpus.Drawing.Basis.RefTrace: instance Monad m => Applicative (RefTraceT u z m)
+ Wumpus.Drawing.Basis.RefTrace: instance Monad m => Functor (RefTraceT u z m)
+ Wumpus.Drawing.Basis.RefTrace: instance Monad m => Monad (RefTraceT u z m)
+ Wumpus.Drawing.Basis.RefTrace: instance Num u => LocTraceM (RefTrace u z)
+ Wumpus.Drawing.Basis.RefTrace: instance Num u => RefTraceM (RefTrace u z)
+ Wumpus.Drawing.Basis.RefTrace: linkRef :: (RefTraceM m, (MonRef m) ~ a, (MonUnit (m ())) ~ u) => LinkRef u a -> m ()
+ Wumpus.Drawing.Basis.RefTrace: location :: (LocTraceM m, (MonUnit (m ())) ~ u) => m (Vec2 u)
+ Wumpus.Drawing.Basis.RefTrace: moveBy :: (LocTraceM m, (MonUnit (m ())) ~ u) => Vec2 u -> m ()
+ Wumpus.Drawing.Basis.RefTrace: multiwayLink :: (ans -> Point2 u) -> ([Point2 u] -> Graphic u) -> [Ref] -> LinkRef u ans
+ Wumpus.Drawing.Basis.RefTrace: runRefTrace :: Num u => RefTrace u ans a -> LocImage u a
+ Wumpus.Drawing.Basis.RefTrace: runRefTraceT :: (Monad m, Num u) => RefTraceT u ans m a -> m (LocImage u a)
+ Wumpus.Drawing.Basis.RefTrace: unaryLink :: (ans -> Point2 u) -> LocGraphic u -> Ref -> LinkRef u ans
+ Wumpus.Drawing.Basis.TraceGraphic: class Monad m => TraceGraphicM m
+ Wumpus.Drawing.Basis.TraceGraphic: data TraceGraphic u a
+ Wumpus.Drawing.Basis.TraceGraphic: data TraceGraphicT u m a
+ Wumpus.Drawing.Basis.TraceGraphic: instance Applicative (TraceGraphic u)
+ Wumpus.Drawing.Basis.TraceGraphic: instance DrawingCtxM (TraceGraphic u)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Functor (TraceGraphic u)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Monad (TraceGraphic u)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Monad m => Applicative (TraceGraphicT u m)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Monad m => DrawingCtxM (TraceGraphicT u m)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Monad m => Functor (TraceGraphicT u m)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Monad m => Monad (TraceGraphicT u m)
+ Wumpus.Drawing.Basis.TraceGraphic: instance Monad m => TraceGraphicM (TraceGraphicT u m)
+ Wumpus.Drawing.Basis.TraceGraphic: instance TraceGraphicM (TraceGraphic u)
+ Wumpus.Drawing.Basis.TraceGraphic: liftTraceGraphicT :: Monad m => m a -> TraceGraphicT u m a
+ Wumpus.Drawing.Basis.TraceGraphic: runTraceGraphic :: TraceGraphic u a -> Image u a
+ Wumpus.Drawing.Basis.TraceGraphic: runTraceGraphicT :: Monad m => DrawingContext -> TraceGraphicT u m a -> m (a, HPrim u)
+ Wumpus.Drawing.Basis.TraceGraphic: tellImage :: (TraceGraphicM m, (MonUnit (m ())) ~ u) => Image u a -> m a
+ Wumpus.Drawing.Basis.TraceGraphic: tellImage_ :: (TraceGraphicM m, (MonUnit (m ())) ~ u) => Image u a -> m ()
+ Wumpus.Drawing.Connectors.Base: ArrowTip :: (Double -> En) -> En -> LocThetaGraphic En -> ArrowTip
+ Wumpus.Drawing.Connectors.Base: buildConn :: (Real u, Floating u, InterpretUnit u) => (Point2 u -> Point2 u -> Image u a) -> ConnectorImage u a
+ Wumpus.Drawing.Connectors.Base: retract_distance :: ArrowTip -> Double -> En
+ Wumpus.Drawing.Connectors.Base: rightArrowPath :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> AbsPath u -> Image u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: tip_deco :: ArrowTip -> LocThetaGraphic En
+ Wumpus.Drawing.Connectors.Base: tip_half_len :: ArrowTip -> En
+ Wumpus.Drawing.Dots.AnchorDots: dotNone :: InterpretUnit u => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: largeCirc :: (Floating u, Real u, InterpretUnit u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: largeDisk :: (Floating u, Real u, InterpretUnit u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: smallCirc :: (Floating u, Real u, InterpretUnit u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: smallDisk :: (Floating u, Real u, InterpretUnit u) => DotLocImage u
+ Wumpus.Drawing.Dots.SimpleDots: data MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: dotAsterisk :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotChar :: (Real u, Floating u, InterpretUnit u) => Char -> LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotCircle :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotCross :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotDisk :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotFOCross :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotHLine :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotNone :: InterpretUnit u => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotOCross :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotOPlus :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotPentagon :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotPlus :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotSquare :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotStar :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotText :: (Real u, Floating u, InterpretUnit u) => String -> LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotTriangle :: (Floating u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotVLine :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: dotX :: (Fractional u, InterpretUnit u) => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: instance Eq MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance Floating MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance Fractional MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance InterpretUnit MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance Num MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance Ord MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance Real MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance RealFloat MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance RealFrac MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: instance Show MarkSize
+ Wumpus.Drawing.Dots.SimpleDots: largeCirc :: InterpretUnit u => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: largeDisk :: InterpretUnit u => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: smallCirc :: InterpretUnit u => LocGraphic u
+ Wumpus.Drawing.Dots.SimpleDots: smallDisk :: InterpretUnit u => LocGraphic u
+ Wumpus.Drawing.Extras.Clip: locClip :: InterpretUnit u => RelPath u -> LocGraphic u -> LocGraphic u
+ Wumpus.Drawing.Extras.Grids: dotted_major_grid :: GridContextF
+ Wumpus.Drawing.Extras.Loop: loop :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> Point2 u -> Radian -> Query u (AbsPath u)
+ Wumpus.Drawing.Extras.Loop: loopPoints :: (Real u, Floating u) => u -> Point2 u -> Radian -> [Point2 u]
+ Wumpus.Drawing.Paths.Base.AbsPath: closedAbsPath :: InterpretUnit u => DrawStyle -> AbsPath u -> Image u (AbsPath u)
+ Wumpus.Drawing.Paths.Base.AbsPath: openAbsPath :: InterpretUnit u => AbsPath u -> Image u (AbsPath u)
+ Wumpus.Drawing.Paths.Base.AbsPath: optimizeLines :: (Real u, Floating u, Ord u, Tolerance u) => AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base.PathBuilder: SUBPATH_CLOSED :: DrawStyle -> PathTerm
+ Wumpus.Drawing.Paths.Base.PathBuilder: SUBPATH_OPEN :: PathTerm
+ Wumpus.Drawing.Paths.Base.PathBuilder: aline :: (PathOpM m, Floating u, u ~ (MonUnit (m ()))) => Radian -> u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: class Monad m => LocTraceM m :: (* -> *)
+ Wumpus.Drawing.Paths.Base.PathBuilder: class Monad m => PathOpM m
+ Wumpus.Drawing.Paths.Base.PathBuilder: curve :: (PathOpM m, u ~ (MonUnit (m ()))) => Vec2 u -> Vec2 u -> Vec2 u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: cycleSubPath :: PathOpM m => DrawStyle -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: data PathSpec u a
+ Wumpus.Drawing.Paths.Base.PathBuilder: data PathSpecT u m a
+ Wumpus.Drawing.Paths.Base.PathBuilder: data PathTerm
+ Wumpus.Drawing.Paths.Base.PathBuilder: data Vamp u
+ Wumpus.Drawing.Paths.Base.PathBuilder: evalPathSpec :: (Floating u, InterpretUnit u) => PathSpec u a -> RelPath u
+ Wumpus.Drawing.Paths.Base.PathBuilder: evalPathSpecT :: (Monad m, Floating u, InterpretUnit u) => PathSpecT u m a -> m (RelPath u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: execPathSpec :: (Floating u, InterpretUnit u) => PathSpec u a -> LocGraphic u
+ Wumpus.Drawing.Paths.Base.PathBuilder: execPathSpecT :: (Monad m, Floating u, InterpretUnit u) => PathSpecT u m a -> m (LocGraphic u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: execPivot :: (Floating u, InterpretUnit u) => PathSpec u a -> PathSpec u a -> LocGraphic u
+ Wumpus.Drawing.Paths.Base.PathBuilder: execPivotT :: (Floating u, InterpretUnit u, Monad m) => PathSpecT u m a -> PathSpecT u m a -> m (LocGraphic u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: hline :: (PathOpM m, Num u, u ~ (MonUnit (m ()))) => u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: insertl :: (LocTraceM m, (MonUnit (m ())) ~ u) => LocGraphic u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: insertl_ :: (LocTraceM m, (MonUnit (m ())) ~ u) => LocImage u a -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance (Floating u, InterpretUnit u) => LocTraceM (PathSpec u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance (Floating u, Ord u, Tolerance u, InterpretUnit u) => PathOpM (PathSpec u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance (Monad m, Floating u, InterpretUnit u) => LocTraceM (PathSpecT u m)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance (Monad m, Floating u, Ord u, Tolerance u, InterpretUnit u) => PathOpM (PathSpecT u m)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Applicative (PathSpec u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Eq PathTerm
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Functor (PathSpec u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Monad (PathSpec u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Monad m => Applicative (PathSpecT u m)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Monad m => Functor (PathSpecT u m)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Monad m => Monad (PathSpecT u m)
+ Wumpus.Drawing.Paths.Base.PathBuilder: instance Show PathTerm
+ Wumpus.Drawing.Paths.Base.PathBuilder: line :: (PathOpM m, u ~ (MonUnit (m ()))) => Vec2 u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: lines :: (PathOpM m, u ~ (MonUnit (m ()))) => [Vec2 u] -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: location :: (LocTraceM m, (MonUnit (m ())) ~ u) => m (Vec2 u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: makeVamp :: Vec2 u -> RelPath u -> PathTerm -> Vamp u
+ Wumpus.Drawing.Paths.Base.PathBuilder: moveBy :: (LocTraceM m, (MonUnit (m ())) ~ u) => Vec2 u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: pen_colour :: PathOpM m => RGBi -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: pen_width :: PathOpM m => Double -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: runPathSpec :: (Floating u, InterpretUnit u) => PathSpec u a -> (a, RelPath u, Vec2 u, LocGraphic u, LocGraphic u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: runPathSpecT :: (Monad m, Floating u, InterpretUnit u) => PathSpecT u m a -> m (a, RelPath u, Vec2 u, LocGraphic u, LocGraphic u)
+ Wumpus.Drawing.Paths.Base.PathBuilder: updatePen :: PathOpM m => DrawingContextF -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: vamp :: (PathOpM m, u ~ (MonUnit (m ()))) => Vamp u -> m ()
+ Wumpus.Drawing.Paths.Base.PathBuilder: vline :: (PathOpM m, Num u, u ~ (MonUnit (m ()))) => u -> m ()
+ Wumpus.Drawing.Paths.Base.RelPath: closedRelPath :: InterpretUnit u => DrawStyle -> RelPath u -> LocImage u (RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: instance Num u => Monoid (RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: length :: RelPath u -> u
+ Wumpus.Drawing.Paths.Base.RelPath: openRelPath :: InterpretUnit u => RelPath u -> LocImage u (RelPath u)
+ Wumpus.Drawing.Paths.Vamps: squareWE :: (Fractional u, Floating u) => u -> Vamp u
+ Wumpus.Drawing.Text.Base.Label: above_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query u (Anchor u)
+ Wumpus.Drawing.Text.Base.Label: above_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query u (Anchor u)
+ Wumpus.Drawing.Text.Base.Label: below_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query u (Anchor u)
+ Wumpus.Drawing.Text.Base.Label: below_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query u (Anchor u)
+ Wumpus.Drawing.Text.Base.Label: centerRelative :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => (Int, Int) -> a -> Query u (Anchor u)
+ Wumpus.Drawing.Text.Base.Label: left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query u (Anchor u)
+ Wumpus.Drawing.Text.Base.Label: right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query u (Anchor u)
- Wumpus.Drawing.Connectors.Arrowheads: barb45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: barb45 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: barb60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: barb60 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: barb90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: barb90 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: bracket :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: bracket :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: curveTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: curveTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: diamondTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: diamondTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: diamondWideTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: diamondWideTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: diskTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: diskTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: odiamondTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: odiamondTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: odiamondWideTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: odiamondWideTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: odiskTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: odiskTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: orevtri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: orevtri45 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: orevtri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: orevtri60 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: orevtri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: orevtri90 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: osquareTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: osquareTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: otri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: otri45 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: otri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: otri60 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: otri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: otri90 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: perp :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: perp :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revbarb45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revbarb45 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revbarb60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revbarb60 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revbarb90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revbarb90 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revcurveTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revcurveTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revtri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revtri45 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revtri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revtri60 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: revtri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: revtri90 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: squareTip :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: squareTip :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: tri45 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: tri45 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: tri60 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: tri60 :: ArrowTip
- Wumpus.Drawing.Connectors.Arrowheads: tri90 :: InterpretUnit u => ArrowTip u
+ Wumpus.Drawing.Connectors.Arrowheads: tri90 :: ArrowTip
- Wumpus.Drawing.Connectors.Base: data ArrowTip u
+ Wumpus.Drawing.Connectors.Base: data ArrowTip
- Wumpus.Drawing.Connectors.Base: leftArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: leftArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> Connector u -> ArrowConnector u
- Wumpus.Drawing.Connectors.Base: leftRightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: leftRightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> ArrowTip -> Connector u -> ArrowConnector u
- Wumpus.Drawing.Connectors.Base: rightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: rightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> Connector u -> ArrowConnector u
- Wumpus.Drawing.Connectors.Base: uniformArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip u -> Connector u -> ArrowConnector u
+ Wumpus.Drawing.Connectors.Base: uniformArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> Connector u -> ArrowConnector u
- Wumpus.Drawing.Extras.Axes: orthontAxes :: (Real u, Floating u, InterpretUnit u) => (Double, Double) -> Graphic u
+ Wumpus.Drawing.Extras.Axes: orthontAxes :: (Real u, Floating u, InterpretUnit u) => (Int, Int) -> (Int, Int) -> LocGraphic u
- Wumpus.Drawing.Extras.Grids: grid :: (Fractional u, InterpretUnit u) => GridContextF -> (Int, Int) -> (Int, Int) -> Graphic u
+ Wumpus.Drawing.Extras.Grids: grid :: (Fractional u, InterpretUnit u) => GridContextF -> Int -> Int -> LocGraphic u
- Wumpus.Drawing.Paths.Base.AbsPath: toPrimPath :: InterpretUnit u => AbsPath u -> Query PrimPath
+ Wumpus.Drawing.Paths.Base.AbsPath: toPrimPath :: InterpretUnit u => AbsPath u -> Query u PrimPath
- Wumpus.Drawing.Paths.Base.RelPath: append :: RelPath u -> RelPath u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: append :: Num u => RelPath u -> RelPath u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: consCurveTo :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: consCurveTo :: (Floating u, Ord u, Tolerance u) => Vec2 u -> Vec2 u -> Vec2 u -> RelPath u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: consLineTo :: Vec2 u -> RelPath u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: consLineTo :: Floating u => Vec2 u -> RelPath u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: curve1 :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: curve1 :: Floating u => Vec2 u -> Vec2 u -> Vec2 u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: curvedPath :: [Vec2 u] -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: curvedPath :: Floating u => [Vec2 u] -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: empty :: RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: empty :: Num u => RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: fromPathAlgCurves :: Num u => PathAlg u -> (Vec2 u, RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: fromPathAlgCurves :: Floating u => PathAlg u -> (Vec2 u, RelPath u)
- Wumpus.Drawing.Paths.Base.RelPath: fromPathAlgVertices :: Num u => PathAlg u -> (Vec2 u, RelPath u)
+ Wumpus.Drawing.Paths.Base.RelPath: fromPathAlgVertices :: Floating u => PathAlg u -> (Vec2 u, RelPath u)
- Wumpus.Drawing.Paths.Base.RelPath: line1 :: Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: line1 :: Floating u => Vec2 u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: snocCurveTo :: RelPath u -> Vec2 u -> Vec2 u -> Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: snocCurveTo :: (Floating u, Ord u, Tolerance u) => RelPath u -> Vec2 u -> Vec2 u -> Vec2 u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: snocLineTo :: RelPath u -> Vec2 u -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: snocLineTo :: Floating u => RelPath u -> Vec2 u -> RelPath u
- Wumpus.Drawing.Paths.Base.RelPath: toPrimPath :: InterpretUnit u => Point2 u -> RelPath u -> Query PrimPath
+ Wumpus.Drawing.Paths.Base.RelPath: toPrimPath :: InterpretUnit u => Point2 u -> RelPath u -> Query u PrimPath
- Wumpus.Drawing.Paths.Base.RelPath: vertexPath :: [Vec2 u] -> RelPath u
+ Wumpus.Drawing.Paths.Base.RelPath: vertexPath :: Floating u => [Vec2 u] -> RelPath u
- Wumpus.Drawing.Shapes.Base: roundCornerShapePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> [Point2 u] -> Query (AbsPath u)
+ Wumpus.Drawing.Shapes.Base: roundCornerShapePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> [Point2 u] -> Query u (AbsPath u)
- Wumpus.Drawing.Shapes.Trapezium: trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Radian -> Shape Trapezium u
+ Wumpus.Drawing.Shapes.Trapezium: trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> u -> Shape Trapezium u
- Wumpus.Drawing.Text.Base.Common: advtext :: InterpretUnit u => EscapedText -> AdvGraphic u
+ Wumpus.Drawing.Text.Base.Common: advtext :: InterpretUnit u => EscapedText -> LocImage u (Vec2 u)
- Wumpus.Drawing.Text.Base.Common: posTextWithMargins :: (Fractional u, InterpretUnit u) => PosObject u -> BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.Common: posTextWithMargins :: (Fractional u, InterpretUnit u) => PosObject u -> (RectAddress -> LocImage u (BoundingBox u))
- Wumpus.Drawing.Text.Base.DocTextZero: render :: (Real u, Floating u, InterpretUnit u) => FontFamily -> Doc u -> BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.DocTextZero: render :: (Real u, Floating u, InterpretUnit u) => FontFamily -> Doc u -> (RectAddress -> LocImage u (BoundingBox u))
- Wumpus.Drawing.Text.Base.DocTextZero: type TextFrame u = BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.DocTextZero: type TextFrame u = RectAddress -> LocImage u (BoundingBox u)
- Wumpus.Drawing.Text.Base.Label: locImageLabel :: Floating u => (a -> Anchor u) -> RectAddress -> BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: locImageLabel :: Floating u => (a -> Anchor u) -> RectAddress -> (RectAddress -> LocImage u (BoundingBox u)) -> LocImage u a -> LocImage u a
- Wumpus.Drawing.Text.Base.PosChar: type LocRectChar u = BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.PosChar: type LocRectChar u = RectAddress -> LocImage u (BoundingBox u)
- Wumpus.Drawing.Text.Base.RotTextZero: type LocRectTextLine u = BoundedLocRectGraphic u
+ Wumpus.Drawing.Text.Base.RotTextZero: type LocRectTextLine u = RectAddress -> LocImage u (BoundingBox u)
- Wumpus.Drawing.Text.Base.RotTextZero: type LocTextLine u = BoundedLocGraphic u
+ Wumpus.Drawing.Text.Base.RotTextZero: type LocTextLine u = LocImage u (BoundingBox u)
Files
- CHANGES +26/−0
- demo/Arrowheads.hs +9/−9
- demo/Automata.hs +14/−6
- demo/ClipPic.hs +52/−52
- demo/ColourCharts.hs +6/−4
- demo/Connectors.hs +6/−6
- demo/DotPic.hs +48/−49
- demo/FeatureModel.hs +2/−2
- demo/FontPic.hs +5/−5
- demo/LeftRightText.hs +12/−23
- demo/PetriNet.hs +9/−9
- demo/SampleShapes.hs +16/−14
- demo/SingleChar.hs +3/−3
- demo/SingleLine.hs +3/−2
- demo/Symbols.hs +2/−2
- demo/TableChains.hs +0/−26
- src/Wumpus/Drawing/Basis/DrawingPrimitives.hs +136/−0
- src/Wumpus/Drawing/Basis/LocTrace.hs +252/−0
- src/Wumpus/Drawing/Basis/RefTrace.hs +297/−0
- src/Wumpus/Drawing/Basis/TraceGraphic.hs +168/−0
- src/Wumpus/Drawing/Connectors.hs +0/−2
- src/Wumpus/Drawing/Connectors/Arrowheads.hs +155/−104
- src/Wumpus/Drawing/Connectors/Base.hs +118/−72
- src/Wumpus/Drawing/Connectors/BoxConnectors.hs +6/−6
- src/Wumpus/Drawing/Connectors/ConnectorPaths.hs +28/−28
- src/Wumpus/Drawing/Connectors/Loop.hs +0/−86
- src/Wumpus/Drawing/Dots/AnchorDots.hs +111/−60
- src/Wumpus/Drawing/Dots/Marks.hs +0/−242
- src/Wumpus/Drawing/Dots/SimpleDots.hs +267/−0
- src/Wumpus/Drawing/Extras/Axes.hs +12/−13
- src/Wumpus/Drawing/Extras/Clip.hs +41/−0
- src/Wumpus/Drawing/Extras/Grids.hs +71/−90
- src/Wumpus/Drawing/Extras/Loop.hs +95/−0
- src/Wumpus/Drawing/Extras/Turtle/TurtleClass.hs +0/−91
- src/Wumpus/Drawing/Extras/Turtle/TurtleMonad.hs +0/−132
- src/Wumpus/Drawing/Paths/Absolute.hs +3/−3
- src/Wumpus/Drawing/Paths/Base/AbsBuilder.hs +0/−561
- src/Wumpus/Drawing/Paths/Base/AbsPath.hs +41/−2
- src/Wumpus/Drawing/Paths/Base/BuildCommon.hs +0/−129
- src/Wumpus/Drawing/Paths/Base/PathBuilder.hs +576/−0
- src/Wumpus/Drawing/Paths/Base/RelBuilder.hs +0/−520
- src/Wumpus/Drawing/Paths/Base/RelPath.hs +126/−46
- src/Wumpus/Drawing/Paths/Relative.hs +2/−2
- src/Wumpus/Drawing/Paths/Vamps.hs +10/−20
- src/Wumpus/Drawing/Shapes/Base.hs +24/−29
- src/Wumpus/Drawing/Shapes/Circle.hs +2/−2
- src/Wumpus/Drawing/Shapes/Diamond.hs +4/−4
- src/Wumpus/Drawing/Shapes/Ellipse.hs +2/−2
- src/Wumpus/Drawing/Shapes/Parallelogram.hs +47/−92
- src/Wumpus/Drawing/Shapes/Rectangle.hs +4/−6
- src/Wumpus/Drawing/Shapes/Semicircle.hs +47/−35
- src/Wumpus/Drawing/Shapes/Semiellipse.hs +27/−29
- src/Wumpus/Drawing/Shapes/Trapezium.hs +34/−114
- src/Wumpus/Drawing/Shapes/Triangle.hs +33/−40
- src/Wumpus/Drawing/Text/Base/Common.hs +5/−5
- src/Wumpus/Drawing/Text/Base/DocTextZero.hs +29/−25
- src/Wumpus/Drawing/Text/Base/Label.hs +90/−6
- src/Wumpus/Drawing/Text/Base/PosChar.hs +3/−3
- src/Wumpus/Drawing/Text/Base/RotTextZero.hs +22/−236
- src/Wumpus/Drawing/VersionNumber.hs +2/−2
- wumpus-drawing.cabal +21/−48
CHANGES view
@@ -1,4 +1,30 @@ ++0.2.0 to 0.3.0:++ * Moved Turtle and Grids into the @Wumpus.Drawing.Extras@+ name-space. Modules here are considered sketches.++ * Re-implemented arrowheads and connectors.++ * Re-implemented monadic path construction. This is now + essentially \"turtle drawing\" with a path trace.++ * Removed chains - a simplified implementation is now + provided by Wumpus-Basic.++ * Re-implemented and expanded Text. ++0.1.0 to 0.2.0:++ * Added new Shapes.++ * Move Geometry modules to Wumpus-Basic.++ * Re-implemented Chains.++ * Re-implemented LR-Text. Added CatText.+ 0.1.0: * Initial release - this is a split from @Wumpus-Basic@ making
demo/Arrowheads.hs view
@@ -13,7 +13,7 @@ import Wumpus.Core -- package: wumpus-core -+import Data.Monoid import System.Directory main :: IO ()@@ -38,7 +38,7 @@ arrow_drawing = drawTracing $ localize dotted_line $ tableGraphic arrtable -arrtable :: [(String, ArrowTip Double)]+arrtable :: [(String, ArrowTip)] arrtable = [ ("tri90", tri90) , ("tri60", tri60)@@ -74,7 +74,7 @@ -tableGraphic :: [(String, ArrowTip Double)] -> TraceDrawing Double ()+tableGraphic :: [(String, ArrowTip)] -> TraceDrawing Double () tableGraphic tips = drawl start $ chain_ chn_alg (map makeArrowDrawing tips) where@@ -87,12 +87,12 @@ -makeArrowDrawing :: (String, ArrowTip Double) -> LocGraphic Double-makeArrowDrawing (name, utip) = aconn `oplus` lbl+makeArrowDrawing :: (String, ArrowTip) -> LocGraphic Double+makeArrowDrawing (name, utip) = aconn `mappend` lbl where- aconn = promoteR1 $ \pt -> fmap ignoreAns $ - connect (uniformArrow utip connline) pt (displaceH 60 pt)+ aconn = ignoreAns $ promoteLoc $ \pt ->+ connect pt (displace (hvec 60) pt) (uniformArrow utip connline) - lbl = promoteR1 $ \pt -> fmap ignoreAns $ - atStartAddr (textline name) (displaceH 66 pt) WW+ lbl = ignoreAns $ promoteLoc $ \pt -> + textline name WW `at` (displace (hvec 66) pt)
demo/Automata.hs view
@@ -4,6 +4,7 @@ module Automata where import Wumpus.Drawing.Connectors+import Wumpus.Drawing.Extras.Loop import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes import Wumpus.Drawing.Text.DirectionZero@@ -57,11 +58,12 @@ return () -+-- Monadic at - this is a hack that needs a rethink...+-- infixr 1 `mat` -mat :: LocImage u a -> Query (Point2 u) -> Image u a-mat img mq = mq >>= \pt -> img `at` pt+mat :: LocImage u a -> Query u (Point2 u) -> Image u a+mat img mq = zapQuery mq >>= \pt -> img `at` pt state :: String -> DLocImage DCircle state ss = @@ -84,12 +86,12 @@ => a -> b -> Image u (AbsPath u) straightconn a b = let (p0,p1) = radialConnectorPoints a b- in connect (rightArrow tri45 connline) p0 p1+ in connect p0 p1 (rightArrow tri45 connline) astraightconn :: ( Real u, Floating u, InterpretUnit u) => Anchor u -> Anchor u -> Image u (AbsPath u)-astraightconn p0 p1 = connect (rightArrow tri45 connline) p0 p1+astraightconn p0 p1 = connect p0 p1 (rightArrow tri45 connline) -- Note - there is a problem with @rightArrow@ as @loop@@@ -97,7 +99,13 @@ -- arrloop :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Anchor u -> Anchor u -> Image u (AbsPath u)-arrloop p0 p1 = connect (rightArrow barb45 loop) p0 p1+arrloop ctr p1 = + zapQuery (loop zradius ctr zincl) >>= \absp -> + rightArrowPath tri45 absp + where+ v1 = pvec ctr p1+ zradius = vlength v1+ zincl = vdirection v1
demo/ClipPic.hs view
@@ -13,7 +13,8 @@ module ClipPic where import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Paths.Absolute+import Wumpus.Drawing.Extras.Clip+import Wumpus.Drawing.Paths.Relative import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic@@ -22,13 +23,14 @@ import Data.AffineSpace -- package: vector-space +import Data.Monoid import System.Directory main :: IO () main = do createDirectoryIfMissing True "./out/"- let pic1 = runCtxPictureU std_ctx $ top_pic `vconcat` clip_pic+ let pic1 = runCtxPictureU std_ctx clip_pic writeEPS "./out/clip_pic.eps" pic1 writeSVG "./out/clip_pic.svg" pic1 @@ -37,74 +39,72 @@ std_ctx = standardContext 14 -top_pic :: CtxPicture-top_pic = drawTracing $ localize (fill_colour medium_slate_blue) $ do- draw $ toPrimPath path01 >>= filledPath- draw $ localize (fill_colour powder_blue) $ toPrimPath path02 >>= filledPath- draw $ toPrimPath path03 >>= filledPath- draw $ toPrimPath path04 >>= filledPath- clip_pic :: CtxPicture-clip_pic = drawTracing $ do- mapM_ draw $ [ clip1, clip2, clip3, clip4 ]+clip_pic = drawTracing $ localize (fill_colour medium_slate_blue) $ do+ drawl (P2 0 320) $ closedRelPath FILL path01+ drawl (P2 112 320) $ localize (fill_colour powder_blue) $ closedRelPath FILL path02+ drawl (P2 384 416) $ closedRelPath FILL path03+ drawl (P2 328 512) $ closedRelPath FILL path04+ drawl (P2 0 0) $ clip1+ drawl (P2 112 0) $ clip2+ drawl (P2 384 96) $ clip3+ drawl (P2 328 192) $ clip4 -background :: RGBi -> Graphic Double-background rgb = - fmap ignoreAns $ localize (text_colour rgb) $ ihh `at` P2 0 288+background :: RGBi -> LocGraphic Double+background rgb = promoteLoc $ \_ -> + ignoreAns $ localize (text_colour rgb) $ ihh `at` P2 0 288 where ihh = chain (tableDown 18 (86,16)) (replicate 112 iheartHaskell) --- Wumpus-Basic needs a clip function, but is this the most --- satisfactory definition?----clipGraphic :: PrimPath -> Graphic u -> Graphic u -clipGraphic cp = fmap (clipObject cp) -clip1 :: Graphic Double-clip1 = toPrimPath path01 >>= \pp -> clipGraphic pp (background black)+clip1 :: LocGraphic Double+clip1 = locClip path01 $ background black -clip2 :: Graphic Double-clip2 = toPrimPath path02 >>= \pp -> clipGraphic pp (background medium_violet_red)+clip2 :: LocGraphic Double+clip2 = locClip path02 $ background medium_violet_red -clip3 :: Graphic Double-clip3 = toPrimPath path03 >>= \pp -> clipGraphic pp (background black)+clip3 :: LocGraphic Double+clip3 = locClip path03 $ background black -clip4 :: Graphic Double-clip4 = toPrimPath path04 >>= \pp -> clipGraphic pp (background black)+clip4 :: LocGraphic Double+clip4 = locClip path04 $ background black iheartHaskell :: LocGraphic Double-iheartHaskell = promoteR1 $ \pt -> - let body = plainTextLine "I Haskell" `at` pt+iheartHaskell = promoteLoc $ \pt -> + let body = dcTextlabel "I Haskell" `at` pt heart = localize (set_font symbol) $ - plainTextLine "&heart;" `at` (pt .+^ hvec 7)- in body `oplus` heart+ dcTextlabel "&heart;" `at` (pt .+^ hvec 7)+ in body `mappend` heart -path01 :: AbsPath Double-path01 = evalAbsBuild zeroPt $ hline 80 - >> relline (vec 112 160) - >> relline (vec (-112) 160)- >> hline (-80)- >> relline (vec 112 (-160))- >> relline (vec (-112) (-160))+-- zeroPt+path01 :: RelPath Double+path01 = evalPathSpec $ hline 80 + >> line (vec 112 160) + >> line (vec (-112) 160)+ >> hline (-80)+ >> line (vec 112 (-160))+ >> line (vec (-112) (-160)) --path02 :: AbsPath Double-path02 = evalAbsBuild (P2 112 0) $ hline 80 - >> relline (vec 72 112)- >> relline (vec 72 (-112))- >> hline 80- >> relline (vec (-224) 320)- >> hline (-80)- >> relline (vec 112 (-160))- >> relline (vec (-112) (-160))+-- (P2 112 0)+path02 :: RelPath Double+path02 = evalPathSpec $ hline 80 + >> line (vec 72 112)+ >> line (vec 72 (-112))+ >> hline 80+ >> line (vec (-224) 320)+ >> hline (-80)+ >> line (vec 112 (-160))+ >> line (vec (-112) (-160)) -path03 :: AbsPath Double-path03 = evalAbsBuild (P2 384 96) $ hline 96 >> vline 56 >> hline (-136) +-- (P2 384 96) +path03 :: RelPath Double+path03 = evalPathSpec $ hline 96 >> vline 56 >> hline (-136) -path04 :: AbsPath Double-path04 = evalAbsBuild (P2 328 192) $ hline 152 >> vline 56 >> hline (-192) +-- (P2 328 192)+path04 :: RelPath Double+path04 = evalPathSpec $ hline 152 >> vline 56 >> hline (-192)
demo/ColourCharts.hs view
@@ -4,11 +4,13 @@ import ColourChartUtils +import Wumpus.Drawing.Basis.DrawingPrimitives import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core +import Data.Monoid import System.Directory @@ -44,14 +46,14 @@ tableGraphic row_count xs = draw $ (chain_ chn gs) `at` pt where chn = tableDown row_count (152,11)- pt = displaceV (fromIntegral $ 11 * row_count) zeroPt + pt = displace (vvec $ fromIntegral $ 11 * row_count) zeroPt gs = map (uncurry colourSample) xs colourSample :: String -> RGBi -> LocGraphic Double colourSample name rgb = localize (fill_colour rgb) $ - promoteR1 $ \pt -> - oplus (borderedRectangle 15 10 `at` pt)- (plainTextLine name `at` displace 20 2 pt)+ promoteLoc $ \pt -> + mappend (blRectangle FILL_STROKE 15 10 `at` pt)+ (dcTextlabel name `at` displace (vec 20 2) pt)
demo/Connectors.hs view
@@ -13,7 +13,7 @@ import Wumpus.Core -- package: wumpus-core -+import Data.Monoid import System.Directory @@ -76,13 +76,13 @@ makeConnDrawing :: (String, Connector Double) -> DLocGraphic makeConnDrawing (ss,conn) = - promoteR1 $ \p0 -> fn p0 (displace 60 40 p0) + promoteLoc $ \p0 -> fn p0 (displace (vec 60 40) p0) where- fn p0 p1 = disk p0 `oplus` disk p1 `oplus` dcon p0 p1 `oplus` lbl p1+ fn p0 p1 = mconcat [disk p0, disk p1, dcon p0 p1, lbl p1] - disk pt = localize (fill_colour red) $ filledDisk 2 `at` pt- dcon p0 p1 = fmap ignoreAns $ connect (uniformArrow curveTip conn) p0 p1+ disk pt = localize (fill_colour red) $ dcDisk FILL 2 `at` pt+ dcon p0 p1 = ignoreAns $ connect p0 p1 (uniformArrow curveTip conn) - lbl pt = fmap ignoreAns $ atStartAddr (textline ss) (displaceH 10 pt) WW+ lbl pt = ignoreAns $ textline ss WW `at` (displace (hvec 10) pt)
demo/DotPic.hs view
@@ -4,6 +4,8 @@ import Wumpus.Drawing.Colour.SVGColours import Wumpus.Drawing.Dots.AnchorDots+import Wumpus.Drawing.Paths.Relative+import Wumpus.Drawing.Text.DirectionZero import Wumpus.Drawing.Text.StandardFontDefs import Wumpus.Basic.Kernel -- package: wumpus-basic@@ -11,8 +13,7 @@ import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace -- package: vector-space-+import Data.Monoid import System.Directory main :: IO ()@@ -30,68 +31,66 @@ makeCtx :: FontLoadResult -> DrawingContext-makeCtx = fill_colour peru . set_font helvetica . metricsContext 24+makeCtx = fill_colour peru . set_font helvetica . metricsContext 14 dot_pic :: CtxPicture-dot_pic = drawTracing $ tableGraphic $ - [ dotHLine- , dotVLine- , dotX- , dotPlus- , dotCross- , dotDiamond- , dotDisk- , dotSquare- , dotCircle- , dotPentagon- , dotStar- , dotAsterisk- , dotOPlus- , dotOCross- , dotFOCross- , dotFDiamond- , dotText "%" - , dotTriangle+dot_pic = drawTracing $ tableGraphic dottable+++dottable :: [(String, DotLocImage Double)]+dottable = + [ ("smallDisk", smallDisk)+ , ("largeDisk", largeDisk)+ , ("smallCirc", smallCirc)+ , ("largeCirc", largeCirc)+ , ("dotNone", dotNone)+ , ("dotHLine", dotHLine)+ , ("dotVLine", dotVLine)+ , ("dotX", dotX)+ , ("dotPlus", dotPlus)+ , ("dotCross", dotCross)+ , ("dotDiamond", dotDiamond)+ , ("dotDisk", dotDisk)+ , ("dotSquare", dotSquare)+ , ("dotCircle", dotCircle)+ , ("dotPentagon", dotPentagon)+ , ("dotStar", dotStar)+ , ("dotAsterisk", dotAsterisk)+ , ("dotOPlus", dotOPlus)+ , ("dotOCross", dotOCross)+ , ("dotFOCross", dotFOCross)+ , ("dotFDiamond", dotFDiamond)+ , ("dotText" , dotText "%")+ , ("dotTriangle", dotTriangle) ] -tableGraphic :: [DotLocImage Double] -> TraceDrawing Double ()++tableGraphic :: [(String, DotLocImage Double)] -> TraceDrawing Double () tableGraphic imgs = draw $ chain_ chn_alg (map makeDotDrawing imgs) `at` pt where- row_count = length imgs- chn_alg = tableDown row_count (1,36)- pt = displaceV (fromIntegral $ 36 * row_count) zeroPt + row_count = 18+ chn_alg = tableDown row_count (180,36)+ pt = displace (vvec $ fromIntegral $ 36 * row_count) zeroPt --- This is a bit convoluted - maybe there should be chain-run --- functions for TraceDrawings as well as LocGraphics? -makeDotDrawing :: (Real u, Floating u, InterpretUnit u) - => DotLocImage u -> LocGraphic u-makeDotDrawing dotF = - promoteR1 $ \pt -> - let all_points = map (pt .+^) displacements- in oconcat (dashline all_points)- (map (\p1 -> fmap ignoreAns $ dotF `at` p1) all_points)+makeDotDrawing :: (String, DotLocImage Double) -> DLocGraphic +makeDotDrawing (name,df) = + drawing `mappend` moveStart (vec 86 14) lbl where- dashline = \ps -> localize attrUpd $ vertexPP ps >>= openStroke-- attrUpd :: DrawingContext -> DrawingContext- attrUpd = packed_dotted . stroke_colour cadet_blue--displacements :: Num u => [Vec2 u]-displacements = [V2 0 0, V2 64 20, V2 128 0, V2 192 20]-+ drawing = execPathSpec $ + updatePen path_style >> + insertl dot >> mapM (\v -> line v >> insertl dot) steps --- Should these produce a DashPattern or a StrokeAttr?+ lbl = ignoreAns $ promoteLoc $ \pt -> + textline name WW `at` pt -evenDashes :: Int -> DashPattern -evenDashes n = Dash 0 [(n,n)]+ steps = [V2 25 15, V2 25 (-15), V2 25 15]+ dot = ignoreAns df+ path_style = packed_dotted . stroke_colour cadet_blue -dashOffset :: Int -> DashPattern -> DashPattern-dashOffset _ Solid = Solid-dashOffset n (Dash _ xs) = Dash n xs
demo/FeatureModel.hs view
@@ -87,12 +87,12 @@ connWith :: ( Real u, Floating u, InterpretUnit u ) - => ArrowTip u -> Box u -> Box u -> TraceDrawing u (AbsPath u)+ => ArrowTip -> Box u -> Box u -> TraceDrawing u (AbsPath u) connWith arrh b0 b1 = do lw <- getLineWidth let p0 = south b0 let p1 = projectAnchor north (realToFrac lw) b1- drawi $ connect (rightArrow arrh connline) p0 p1+ drawi $ connect p0 p1 (rightArrow arrh connline) infixr 4 `cmandatory`, `coptional`, `cmandatory_`, `coptional_`
demo/FontPic.hs view
@@ -42,7 +42,7 @@ makeLabel :: RGBi -> FontDef -> Int -> DLocGraphic-makeLabel rgb ft sz = localize upd (plainTextLine $ fontMsg ft sz)+makeLabel rgb ft sz = localize upd (dcTextlabel $ fontMsg ft sz) where upd = text_colour rgb . font_attr ft sz @@ -59,14 +59,14 @@ pointChain :: (Int -> DLocGraphic) -> DLocImage DPoint2 pointChain fn = chain chn_alg $ map fn point_sizes where- chn_alg = linear $ iterationScheme start step+ chn_alg = linearChain $ iterationScheme start step start = \pt -> (pt,point_sizes) - step (pt,[]) = ((displaceV 50 pt, []), pt)- step (pt,(y:ys)) = ((displaceV (fromIntegral $ 2 + y) pt, ys), pt)+ step (pt,[]) = ((displace (vvec 50) pt, []), pt)+ step (pt,(y:ys)) = ((displace (vvec $ fromIntegral $ 2 + y) pt, ys), pt) fontGraphic :: RGBi -> FontDef -> DLocGraphic -fontGraphic rgb ft = locGraphic_ $ pointChain mkGF+fontGraphic rgb ft = ignoreAns $ pointChain mkGF where mkGF sz = makeLabel rgb ft sz
demo/LeftRightText.hs view
@@ -1,23 +1,12 @@ {-# OPTIONS -Wall #-} --- Note - @main@ is more convoluted than would normally be --- expected as it supports both sources of glyph metrics - the --- GhostScript distribution or the Core 14 metrics from Adobe.--- --- \"Real\" applications would be expected to choose one source. ------ I-am-not-a-lawyer, but it does look as though the Adobe font--- metrics are redistributable, the GhostScript metrics are --- seemingly redistributable under the same terms as the larger--- GhostScript distribution.--- module LeftRightText where import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Dots.Marks+import Wumpus.Drawing.Dots.SimpleDots import Wumpus.Drawing.Text.DirectionZero import Wumpus.Drawing.Text.StandardFontDefs @@ -84,47 +73,47 @@ fn = illustrateBoundedLocGraphic redPlus :: (Fractional u, InterpretUnit u) => LocGraphic u-redPlus = localize (stroke_colour red) markPlus+redPlus = localize (stroke_colour red) dotPlus -- single line -- ne_oneline :: BoundedLocGraphic Double-ne_oneline = textline "north east" `startAddr` NE+ne_oneline = textline "north east" NE -- single line -- se_oneline :: BoundedLocGraphic Double-se_oneline = textline "south east" `startAddr` SE+se_oneline = textline "south east" SE -- single line -- ss_oneline :: BoundedLocGraphic Double-ss_oneline = textline "south" `startAddr` SS+ss_oneline = textline "south" SS -- single line -- sw_oneline :: BoundedLocGraphic Double-sw_oneline = textline "south west" `startAddr` SW+sw_oneline = textline "south west" SW -- single line rot -- ssr_single :: BoundedLocGraphic Double-ssr_single = rtextline (0.25*pi) "south rot45" `startAddr` SS+ssr_single = rtextline (0.25*pi) "south rot45" SS -- single line rot -- swr_single :: BoundedLocGraphic Double-swr_single = rtextline (0.25*pi) "south west rot45" `startAddr` SW+swr_single = rtextline (0.25*pi) "south west rot45" SW -- single line rot -- ner_single :: BoundedLocGraphic Double-ner_single = rtextline (0.25*pi) "north east rot45" `startAddr` NE+ner_single = rtextline (0.25*pi) "north east rot45" NE cc_oneline :: BoundedLocGraphic Double@@ -136,14 +125,14 @@ left_text :: BoundedLocGraphic Double-left_text = multiAlignLeft dummy_text `startAddr` CENTER+left_text = multiAlignLeft dummy_text CENTER right_text :: BoundedLocGraphic Double-right_text = multiAlignRight dummy_text `startAddr` CENTER+right_text = multiAlignRight dummy_text CENTER center_text :: BoundedLocGraphic Double-center_text = multiAlignCenter dummy_text `startAddr` CENTER+center_text = multiAlignCenter dummy_text CENTER dummy_text :: String dummy_text = unlines $ [ "The quick brown"
demo/PetriNet.hs view
@@ -100,39 +100,39 @@ straightconn :: ConnectorGraphic Double-straightconn = connectorGraphic_ $ rightArrow tri45 connline+straightconn = ignoreAns $ rightArrow tri45 connline connectorC :: ConnectorGraphic Double connectorC = - connectorGraphic_ $ localize (uniform_arm_len (30::Double)) - $ rightArrow tri45 connbbar+ ignoreAns $ localize (uniform_arm_len (30::Double)) + $ rightArrow tri45 connbbar connectorC' :: ConnectorGraphic Double connectorC' = - connectorGraphic_ $ localize (uniform_arm_len (30::Double)) + ignoreAns $ localize (uniform_arm_len (30::Double)) $ rightArrow tri45 connabar connectorD :: ConnectorGraphic Double-connectorD = connectorGraphic_ $ rightArrow tri45 connarc+connectorD = ignoreAns $ rightArrow tri45 connarc connectorD' :: ConnectorGraphic Double connectorD' = - connectorGraphic_ $ localize (conn_arc_angle $ negate $ pi / 12) + ignoreAns $ localize (conn_arc_angle $ negate $ pi / 12) $ rightArrow tri45 connarc lblParensParens :: DLocGraphic lblParensParens = - locGraphic_ $ localize (set_font helvetica) $ ccTextline "(),()"+ ignoreAns $ localize (set_font helvetica) $ ccTextline "(),()" lblParensParensParens :: DLocGraphic lblParensParensParens = - locGraphic_ $ localize (set_font helvetica) $ ccTextline "(),(),()"+ ignoreAns $ localize (set_font helvetica) $ ccTextline "(),(),()" lblBold :: String -> DLocGraphic lblBold ss = - locGraphic_ $ localize (set_font helvetica_bold) $ ccTextline ss+ ignoreAns $ localize (set_font helvetica_bold) $ ccTextline ss
demo/SampleShapes.hs view
@@ -7,7 +7,7 @@ import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Dots.Marks+import Wumpus.Drawing.Dots.SimpleDots import Wumpus.Drawing.Shapes import Wumpus.Drawing.Text.DirectionZero import Wumpus.Drawing.Text.StandardFontDefs@@ -18,6 +18,7 @@ import Wumpus.Core -- package: wumpus-core import Control.Monad+import Data.Monoid import System.Directory main :: IO ()@@ -67,7 +68,7 @@ , shapePic (apexAnchor >=> bottomCorners) $ semiellipse 100 150) , ( "trapezium" , shapePic (bottomCorners >=> topCorners >=> midPoints 4) $ - ztrapezium 300 150)+ trapezium 300 200 150) , ( "triangle" , shapePic (apexAnchor >=> bottomCorners >=> midPoints 3) $ triangle 300 150 )@@ -154,7 +155,8 @@ return () where shape = strokedShape $ setDecoration textF sh- textF = lift1R2 $ locGraphic_ (startAddr (multiAlignCenter name) CENTER)+ textF = promoteLocTheta $ \pt _ -> + ignoreAns (multiAlignCenter name CENTER) `at` pt deg10 = d2r (10::Double) deg110 = d2r (110::Double)@@ -171,19 +173,19 @@ label :: (Real u, Floating u, InterpretUnit u) => Cardinal -> String -> LocGraphic u-label cpos ss = markX `oplus` msg+label cpos ss = dotX `mappend` msg where (rpos,fn) = go cpos- msg = locGraphic_ $ moveStart (fn 10) $ - startAddr (multiAlignCenter ss) rpos+ msg = ignoreAns $ moveStart (fn 10) $ + multiAlignCenter ss rpos - go NORTH = (SS, disp_north)- go NORTH_EAST = (SW, disp_northeast)- go EAST = (WW, disp_east) - go SOUTH_EAST = (NW, disp_southeast)- go SOUTH = (NN, disp_south)- go SOUTH_WEST = (NE, disp_southwest)- go WEST = (EE, disp_west)- go NORTH_WEST = (SE, disp_northwest)+ go NORTH = (SS, go_north)+ go NORTH_EAST = (SW, go_north_east)+ go EAST = (WW, go_east) + go SOUTH_EAST = (NW, go_south_east)+ go SOUTH = (NN, go_south)+ go SOUTH_WEST = (NE, go_south_west)+ go WEST = (EE, go_west)+ go NORTH_WEST = (SE, go_north_west)
demo/SingleChar.hs view
@@ -5,7 +5,7 @@ import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Dots.Marks+import Wumpus.Drawing.Dots.SimpleDots import Wumpus.Drawing.Text.DirectionZero import Wumpus.Drawing.Text.StandardFontDefs @@ -62,9 +62,9 @@ draw $ redPlus `at` P2 200 0 where- fn addr obj = illustrateBoundedLocGraphic (runPosObjectR2 obj `startAddr` addr)+ fn addr obj = illustrateBoundedLocGraphic $ (runPosObject addr obj) redPlus :: (Fractional u, InterpretUnit u) => LocGraphic u-redPlus = localize (stroke_colour red) markPlus+redPlus = localize (stroke_colour red) dotPlus
demo/SingleLine.hs view
@@ -12,6 +12,7 @@ import Wumpus.Core -- package: wumpus-core +import Data.Monoid import System.Directory @@ -52,9 +53,9 @@ testDraw :: RectAddress -> LocGraphic Double-testDraw rpos = filledDisk 2 `oplus` (locGraphic_ ans)+testDraw rpos = dcDisk FILL 2 `mappend` (ignoreAns ans) where- ans = textline "Qwerty" `startAddr` rpos+ ans = textline "Qwerty" rpos
demo/Symbols.hs view
@@ -36,8 +36,8 @@ where chn_alg = tableDown 30 (100,20) start = P2 0 (30*20)- sdraw (s,_) = plainTextLine s- ldraw (_,name) = moveStart (displaceH 16) (plainTextLine name)+ sdraw (s,_) = dcTextlabel s+ ldraw (_,name) = moveStart (hvec 16) (dcTextlabel name) all_letters :: [(String, String)]
− demo/TableChains.hs
@@ -1,26 +0,0 @@-{-# OPTIONS -Wall #-}--module TableChains where---import Wumpus.Drawing.Colour.SVGColours-import Wumpus.Drawing.Extras.Grids--import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Core -- package: wumpus-core--import System.Directory--main :: IO ()-main = do - createDirectoryIfMissing True "./out/"- let pic1 = runCtxPictureU std_ctx table_drawing- writeEPS "./out/table_chains01.eps" pic1- writeSVG "./out/table_chains01.svg" pic1--std_ctx :: DrawingContext-std_ctx = fill_colour peru $ standardContext 18--table_drawing :: CtxPicture-table_drawing = udrawTracing (0::Double) $ do - draw $ grid (grid_minor_colour cornflower_blue) (0,0) (4,2)
+ src/Wumpus/Drawing/Basis/DrawingPrimitives.hs view
@@ -0,0 +1,136 @@+{-# OPTIONS -Wall #-}+++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.DrawingPrimitives+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Alternative to the @DrawingPrimitives@ module in Wumpus-Basic.+-- +-- The drawing primitives here are either slightly higher level or+-- less general (more quirky).+--+-- This module is expected to be imported qualified - other modules+-- (e.g. shapes and paths) are likely to export conflicting names.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.DrawingPrimitives+ (+++ -- * Lines++ hline+ , vline+ , pivotLine++ -- * Rectangles+ , blRectangle+ , ctrRectangle+++ -- * Arc and wedge+ , arc+ , wedge++ )++ where++import Wumpus.Basic.Geometry -- package: wumpus-basic+import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+++--------------------------------------------------------------------------------+-- Lines++-- | Draw a vertical line.+-- +vline :: InterpretUnit u => u -> LocGraphic u +vline len = locStraightLine $ vvec len++-- | Draw a horizontal line.+-- +hline :: InterpretUnit u => u -> LocGraphic u +hline len = locStraightLine $ hvec len++++-- | @pivotLine@ : @ left_length * right_length * incline -> LocGraphic @+--+-- Draw a /pivot/ line. The start point is a pivot along the line, +-- not the end. The left and right distances are the extension of+-- the line from the pivot. +--+pivotLine :: (Floating u, InterpretUnit u) => u -> u -> Radian -> LocGraphic u+pivotLine lu ru ang = promoteLoc $ \pt -> + straightLine (pt .+^ avec (ang+pi) lu) (pt .+^ avec ang ru)+++--------------------------------------------------------------------------------+-- Rectangles++++-- | Draw a rectangle, start point is bottom left.+--+blRectangle :: InterpretUnit u => DrawStyle -> u -> u -> LocGraphic u+blRectangle = dcRectangle+++-- | Draw a rectangle, start point is bottom left.+--+ctrRectangle :: (Fractional u, InterpretUnit u) + => DrawStyle -> u -> u -> LocGraphic u+ctrRectangle sty w h = + moveStart (vec (-hw) (-hh)) $ dcRectangle sty w h+ where+ hw = 0.5 * w+ hh = 0.5 * h+++++--------------------------------------------------------------------------------+-- Wedge+++-- | arc : radius * apex_angle+-- +arc :: (Floating u, InterpretUnit u) => u -> Radian -> LocThetaGraphic u+arc radius ang = promoteLocTheta $ \pt inclin -> + let ps = bezierArcPoints ang radius inclin pt+ in zapQuery (curvePP ps) >>= dcOpenPath++-- | wedge : radius * apex_angle+-- +wedge :: (Floating u, InterpretUnit u) + => DrawStyle -> u -> Radian -> LocThetaGraphic u+wedge sty radius ang = promoteLocTheta $ \pt inclin -> + let ps = bezierArcPoints ang radius inclin pt+ in uconvertCtxF pt >>= \dpt -> + mapM uconvertCtxF ps >>= \dps -> + dcClosedPath sty (build dpt dps)+ where+ -- Note - this relies on an implicit straight line cycle back + -- to the start point.+ --+ build :: DPoint2 -> [DPoint2] -> PrimPath+ build pt [] = emptyPrimPath pt+ build pt (p1:ps) = let cs = curves ps+ in absPrimPath pt (absLineTo p1 : cs)+ + curves (a:b:c:ps) = absCurveTo a b c : curves ps+ curves _ = []+
+ src/Wumpus/Drawing/Basis/LocTrace.hs view
@@ -0,0 +1,252 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}+++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.LocTrace+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Writer monad with imperative /turtle/ style movement to build +-- LocGraphics.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.LocTrace+ (++ -- * LocTrace monads+ LocTrace+ , LocTraceT++ , runLocTrace+ , evalLocTrace+ , execLocTrace++ , runLocTraceT+ , evalLocTraceT+ , execLocTraceT++ , liftLocTraceT++ -- * LocTrace classes+ , LocTraceM(..)+ , LocForkTraceM(..)++ -- * Derived operations+ , hmoveBy+ , vmoveBy++ )++ where++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core++import Data.VectorSpace -- package: vector-space++import Control.Applicative+import Control.Monad+import Data.Monoid++-- | LocTrace is a writer state monad.+--+-- The writer accumulates a LocGraphic the state is a cumulative+-- displacement vector (called a cursor below).+--+newtype LocTrace u a = LocTrace { + getLocTrace :: Vec2 u -> (a, Vec2 u, LocGraphic u )}+++type instance DUnit (LocTrace u a) = u+++-- Do we need a transformer version +-- | LocTrace is a writer state monad.+--+-- The writer accumulates a LocGraphic the state is a cumulative+-- displacement vector.+--+newtype LocTraceT u m a = LocTraceT { + getLocTraceT :: Vec2 u -> m (a, Vec2 u, LocGraphic u )}+++type instance DUnit (LocTraceT u m a) = u+++type instance MonUnit (LocTrace u a) = u+type instance MonUnit (LocTraceT u m a) = u+++-- Functor++instance Functor (LocTrace u) where+ fmap f ma = LocTrace $ \v0 -> let (a,v1,o) = getLocTrace ma v0+ in (f a, v1, o)++instance Monad m => Functor (LocTraceT u m) where+ fmap f ma = LocTraceT $ \v0 -> getLocTraceT ma v0 >>= \(a,v1,o) -> + return (f a, v1, o)++-- Applicative++instance Applicative (LocTrace u) where+ pure a = LocTrace $ \v0 -> (a, v0, mempty)+ mf <*> ma = LocTrace $ \v0 -> + let (f,v1,o1) = getLocTrace mf v0+ (a,v2,o2) = getLocTrace ma v1+ in (f a, v2, o1 `mappend` o2)+++++instance Monad m => Applicative (LocTraceT u m) where+ pure a = LocTraceT $ \v0 -> return (a, v0, mempty)+ mf <*> ma = LocTraceT $ \v0 -> + getLocTraceT mf v0 >>= \(f,v1,o1) ->+ getLocTraceT ma v1 >>= \(a,v2,o2) ->+ return (f a, v2, o1 `mappend` o2)++++-- Monad++instance Monad (LocTrace u) where+ return a = LocTrace $ \v0 -> (a, v0, mempty)+ ma >>= k = LocTrace $ \v0 -> + let (a,v1,o1) = getLocTrace ma v0+ (b,v2,o2) = (getLocTrace . k) a v1+ in (b, v2, o1 `mappend` o2)++instance Monad m => Monad (LocTraceT u m) where+ return a = LocTraceT $ \v0 -> return (a, v0, mempty)+ ma >>= k = LocTraceT $ \v0 -> + getLocTraceT ma v0 >>= \(a,v1,o1) ->+ (getLocTraceT . k) a v1 >>= \(b,v2,o2) -> + return (b, v2, o1 `mappend` o2)++++runLocTrace :: Num u => LocTrace u a -> (a, Vec2 u, LocGraphic u)+runLocTrace mf = getLocTrace mf (V2 0 0)+++-- | Forget the generated LocImage, just return the /answer/.+--+evalLocTrace :: Num u => LocTrace u a -> a+evalLocTrace = post . runLocTrace+ where+ post (a,_,_) = a++-- | Forget the /answer/, just return the generated LocImage.+--+execLocTrace :: Num u => LocTrace u a -> LocGraphic u+execLocTrace = post . runLocTrace+ where+ post (_,_,o) = o++++runLocTraceT :: (Monad m, Num u) + => LocTraceT u m a -> m (a, Vec2 u, LocGraphic u)+runLocTraceT mf = getLocTraceT mf (V2 0 0)+++-- | Forget the generated LocImage, just return the /answer/.+--+evalLocTraceT :: (Monad m, Num u) => LocTraceT u m a -> m a+evalLocTraceT = liftM post . runLocTraceT+ where+ post (a,_,_) = a++-- | Forget the /answer/, just return the generated LocImage.+--+execLocTraceT :: (Monad m, Num u) => LocTraceT u m a -> m (LocGraphic u)+execLocTraceT = liftM post . runLocTraceT+ where+ post (_,_,o) = o++++liftLocTraceT :: Monad m => m a -> LocTraceT u m a +liftLocTraceT ma = LocTraceT $ \v0 -> + ma >>= \a -> return (a,v0,mempty)+++++-- | 'insertl' analogue to Writer monad @tell@.+--+class Monad m => LocTraceM (m :: * -> *) where+ insertl :: MonUnit (m ()) ~ u => LocGraphic u -> m ()+ insertl_ :: MonUnit (m ()) ~ u => LocImage u a -> m ()+ + moveBy :: MonUnit (m ()) ~ u => Vec2 u -> m ()+ location :: MonUnit (m ()) ~ u => m (Vec2 u)+++ insertl_ = insertl . ignoreAns ++++-- Note - @reset@ steals a too general name. +-- It needs changing...++-- | Add operations for branching (fork at the current point)+-- and resetting to the start point.+-- +-- Not all drawings that support tracing support branching. For+-- instance Paths can be built by tracing but they always need +-- a cumulative progression of /next point/ they cannot resrt to +-- the start point and go in a differnt direction.+-- +class LocTraceM m => LocForkTraceM (m :: * -> *) where+ reset :: m ()++ -- Branch is like @local@ in the Reader monad.+ branch :: m a -> m a+++++instance Num u => LocTraceM (LocTrace u) where+ insertl gf = LocTrace $ \v0 -> ((), v0, moveStart v0 gf)+ moveBy v = LocTrace $ \v0 -> ((), v0 ^+^ v, mempty)+ location = LocTrace $ \v0 -> (v0, v0, mempty)++instance Num u => LocForkTraceM (LocTrace u) where+ reset = LocTrace $ \_ -> ((), V2 0 0, mempty)+ branch ma = LocTrace $ \v0 -> let (a,_,o) = getLocTrace ma v0 in (a,v0,o)+ ++instance (Monad m, Num u) => LocTraceM (LocTraceT u m) where+ insertl gf = LocTraceT $ \v0 -> return ((), v0, moveStart v0 gf)+ moveBy v = LocTraceT $ \v0 -> return ((), v0 ^+^ v, mempty)+ location = LocTraceT $ \v0 -> return (v0, v0, mempty)++instance (LocTraceM m, Num u) => LocForkTraceM (LocTraceT u m) where+ reset = LocTraceT $ \_ -> return ((), V2 0 0, mempty)+ branch ma = LocTraceT $ \v0 -> getLocTraceT ma v0 >>= \(a,_,o) -> + return (a,v0,o)+++--------------------------------------------------------------------------------+-- Derived operations+++-- | Move the /cursor/ horizontally.+--+hmoveBy :: (LocTraceM m, Num u, u ~ MonUnit (m ())) => u -> m ()+hmoveBy dx = moveBy (hvec dx)++-- | Move the /cursor/ vertically.+--+vmoveBy :: (LocTraceM m, Num u, u ~ MonUnit (m ())) => u -> m ()+vmoveBy dx = moveBy (vvec dx)
+ src/Wumpus/Drawing/Basis/RefTrace.hs view
@@ -0,0 +1,297 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}+++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.RefTrace+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Writer monad with imperative /turtle/ style movement to build +-- LocGraphics and /references/ allowing connectors between +-- objects.+--+-- Note - references are not /feedback/. Subsequent nodes cannot+-- be place at anchors of previous nodes - anchors only allow+-- connectors to be drawn between located nodes.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.RefTrace+ (++ -- * Re-exports+ LocTraceM(..)++ , RefTrace+ , RefTraceT++ , Ref+ , RefTraceM(..)++ , runRefTrace+ , runRefTraceT++ , unaryLink+ , binaryLink+ , multiwayLink+ )++ where++import Wumpus.Drawing.Basis.LocTrace++import Wumpus.Basic.Kernel -- package: wumpus-basic+import qualified Wumpus.Basic.Utils.JoinList as JL++import Wumpus.Core -- package: wumpus-core++import Data.VectorSpace -- package: vector-space++import Control.Applicative+import Control.Monad+import qualified Data.IntMap as IntMap+import Data.Maybe+import Data.Monoid+++++newtype RefTrace u z a = RefTrace { + getRefTrace :: RefSt u z -> (a, RefSt u z) }+++type instance MonUnit (RefTrace u z a) = u++newtype RefTraceT u z m a = RefTraceT { + getRefTraceT :: RefSt u z -> m (a, RefSt u z) }+++type instance MonUnit (RefTraceT u z m a) = u+++newtype Ref = Ref { getRefUid :: Int }+++-- GRAPHIC or LOC_GRAPHIC? cf. connectors...+--+-- TODO - make this an newtype and only export an arity family of +-- constructors.+-- +-- Maybe we only support the arity2 (connector) and list (path) cases?+--+-- type Elaboration u ans = IntMap.IntMap ans -> Graphic u++data LinkRef u ans = + Unary { refU :: Ref + , ancrU :: ans -> Point2 u+ , drawU :: LocGraphic u + }+ | Binary { refB1 :: Ref + , refB2 :: Ref + , ancrB1 :: ans -> Point2 u+ , ancrB2 :: ans -> Point2 u+ , drawB :: ConnectorGraphic u+ }+ | Multiway { refLs :: [Ref]+ , ancrM :: ans -> Point2 u+ , drawM :: [Point2 u] -> Graphic u+ }++data RefSt u z = RefSt + { uid_count :: Int+ , current_tip :: Vec2 u+ , ref_acc :: LocImage u (IntMap.IntMap z)+ , ref_links :: JL.JoinList (LinkRef u z)+ }++++type instance DUnit (RefSt u z) = u++type RefStF u z = RefSt u z -> RefSt u z +++zeroRefSt :: Num u => RefSt u z+zeroRefSt = RefSt { uid_count = 0+ , current_tip = V2 0 0+ , ref_acc = mempty+ , ref_links = mempty + }+++++-- Functor++instance Functor (RefTrace u z) where+ fmap f ma = RefTrace $ \s0 -> let (a,s1) = getRefTrace ma s0 in (f a, s1)++instance Monad m => Functor (RefTraceT u z m) where+ fmap f ma = RefTraceT $ \s0 -> getRefTraceT ma s0 >>= \(a,s1) ->+ return (f a, s1)++++-- Applicative++instance Applicative (RefTrace u z) where+ pure a = RefTrace $ \s0 -> (a, s0)+ mf <*> ma = RefTrace $ \s0 -> + let (f,s1) = getRefTrace mf s0+ (a,s2) = getRefTrace ma s1+ in (f a, s2)++++instance Monad m => Applicative (RefTraceT u z m) where+ pure a = RefTraceT $ \s0 -> return (a, s0)+ mf <*> ma = RefTraceT $ \s0 -> getRefTraceT mf s0 >>= \(f,s1) -> + getRefTraceT ma s1 >>= \(a,s2) ->+ return (f a, s2)++++-- Monad++instance Monad (RefTrace u z) where+ return a = RefTrace $ \s0 -> (a, s0)+ ma >>= k = RefTrace $ \s0 -> + let (a,s1) = getRefTrace ma s0+ in (getRefTrace . k) a s1+++instance Monad m => Monad (RefTraceT u z m) where+ return a = RefTraceT $ \s0 -> return (a, s0)+ ma >>= k = RefTraceT $ \s0 -> getRefTraceT ma s0 >>= \(a,s1) ->+ (getRefTraceT . k) a s1+ ++++-- LocTraceM++instance Num u => LocTraceM (RefTrace u z) where+ insertl gf = RefTrace $ \s0 -> ((), insertSt gf s0)+ moveBy v = RefTrace $ \s0 -> ((), moveSt v s0)+ location = RefTrace $ \s0 -> (current_tip s0, s0)+++instance (Monad m, Num u) => LocTraceM (RefTraceT u z m) where+ insertl gf = RefTraceT $ \s0 -> return ((), insertSt gf s0)+ moveBy v = RefTraceT $ \s0 -> return ((), moveSt v s0)+ location = RefTraceT $ \s0 -> return (current_tip s0, s0)++++-- Run functions++runRefTrace :: Num u => RefTrace u ans a -> LocImage u a+runRefTrace mf = post $ getRefTrace mf zeroRefSt+ where+ post (a,st) = replaceAns a $ reconcileRefSt st+++runRefTraceT :: (Monad m, Num u) => RefTraceT u ans m a -> m (LocImage u a)+runRefTraceT mf = liftM post $ getRefTraceT mf zeroRefSt+ where+ post (a,st) = replaceAns a $ reconcileRefSt st++++-- Note we have to drop the vector++reconcileRefSt :: RefSt u z -> LocGraphic u+reconcileRefSt st = + step (ref_acc st) (JL.toList $ ref_links st)+ where+ step img xs = ignoreAns $ elaborate img (\a -> mconcat $ map (fn a) xs)+ + fn im (Unary r1 ar1 gf) = + maybe mempty (\pt -> promoteLoc $ \_ -> applyLoc gf pt) (projectRef r1 ar1 im)+ + fn im (Binary r1 r2 ar1 ar2 conn) = + case (projectRef r1 ar1 im, projectRef r2 ar2 im) of+ (Just p1, Just p2) -> promoteLoc $ \_ -> applyConn conn p1 p2+ _ -> mempty+++ fn im (Multiway rs ar1 gf) = + let ps = catMaybes $ map (\a -> projectRef a ar1 im) rs+ in promoteLoc $ \_ -> gf ps+ +++projectRef :: Ref -> (ans -> Point2 u) -> IntMap.IntMap ans -> Maybe (Point2 u)+projectRef r ancr im = ancr <$> IntMap.lookup (getRefUid r) im++-- Note - probably this supports Tree which is not a Trace monad...++class Monad m => RefTraceM (m :: * -> *) where+ type MonRef m :: *+ insertRef :: (MonRef m ~ a, MonUnit (m ()) ~ u) => LocImage u a -> m Ref+ linkRef :: (MonRef m ~ a, MonUnit (m ()) ~ u) => LinkRef u a -> m ()++instance Num u => RefTraceM (RefTrace u z) where+ type MonRef (RefTrace u z) = z+ insertRef img = RefTrace $ \s0 -> let (ix,s1) = incrementSt img s0+ in (Ref ix, s1)++ linkRef fn = RefTrace $ \s0 -> ((), snocLink fn s0) +++moveSt :: Num u => Vec2 u -> RefStF u z +moveSt v = (\s i -> s { current_tip = i ^+^ v }) + <*> current_tip++insertSt :: Num u => LocImage u z2 -> RefStF u ans+insertSt gf = (\s ac v1 -> let g1 = ignoreAns $ moveStart v1 gf+ in s { ref_acc = decorate ac g1 }) + <*> ref_acc <*> current_tip++snocLink :: LinkRef u ans -> RefStF u ans+snocLink fn = (\s i -> s { ref_links = JL.snoc i fn }) + <*> ref_links+++incrementSt :: Num u + => LocImage u ans -> RefSt u ans -> (Int, RefSt u ans)+incrementSt img s0 = (uid_count s0, upd s0)+ where+ upd = (\s ac v1 ix -> let img1 = moveStart v1 img+ in s { ref_acc = fn ix ac img1+ , uid_count = ix+1 }) + <*> ref_acc <*> current_tip <*> uid_count ++ fn ix ac gf = fmap (\(a,b) -> IntMap.insert ix b a) $ both ac gf++++unaryLink :: (ans -> Point2 u) -> LocGraphic u -> Ref -> LinkRef u ans+unaryLink f gf = \r1 -> Unary { refU = r1+ , ancrU = f+ , drawU = gf+ }++binaryLink :: (ans -> Point2 u) -> (ans -> Point2 u) + -> ConnectorGraphic u -> Ref -> Ref + -> LinkRef u ans+binaryLink f g conn = \r1 r2 -> Binary { refB1 = r1+ , refB2 = r2 + , ancrB1 = f+ , ancrB2 = g+ , drawB = conn+ }+++multiwayLink :: (ans -> Point2 u) -> ([Point2 u] -> Graphic u) -> [Ref] + -> LinkRef u ans+multiwayLink f gf = \rs -> Multiway { refLs = rs+ , ancrM = f+ , drawM = gf+ }
+ src/Wumpus/Drawing/Basis/TraceGraphic.hs view
@@ -0,0 +1,168 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.TraceGraphic+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : unstable+-- Portability : GHC+--+-- Build multi-part Graphics with an accumulator (i.e. a Writer +-- monad).+--+-- Note - the run functions for the transformer and the plain+-- monad are quite different. This is mandated by the need to +-- single-thread the DrawingContext through the transformer.+--+--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.TraceGraphic+ (+ TraceGraphic+ , TraceGraphicT++ , TraceGraphicM(..)++ , runTraceGraphic+ , runTraceGraphicT++ , liftTraceGraphicT++ ) where+++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Control.Applicative+import Data.Monoid++++newtype TraceGraphic u a = TraceGraphic { + getTraceGraphic :: DrawingContext -> (a, CatPrim) }+++newtype TraceGraphicT u m a = TraceGraphicT { + getTraceGraphicT :: DrawingContext -> m (a, CatPrim) }+++type instance MonUnit (TraceGraphic u a) = u+type instance MonUnit (TraceGraphicT u m a) = u+++-- Functor++instance Functor (TraceGraphic u) where+ fmap f ma = TraceGraphic $ \ctx -> let (a,w1) = getTraceGraphic ma ctx+ in (f a,w1)+++instance Monad m => Functor (TraceGraphicT u m) where+ fmap f ma = TraceGraphicT $ \ctx -> getTraceGraphicT ma ctx >>= \(a,w1) -> + return (f a,w1)+++-- Applicative++instance Applicative (TraceGraphic u) where+ pure a = TraceGraphic $ \_ -> (a, mempty)+ mf <*> ma = TraceGraphic $ \ctx -> + let (f,w1) = getTraceGraphic mf ctx+ (a,w2) = getTraceGraphic ma ctx+ in (f a,w1 `mappend` w2)+++instance Monad m => Applicative (TraceGraphicT u m) where+ pure a = TraceGraphicT $ \_ -> return (a, mempty)+ mf <*> ma = TraceGraphicT $ \ctx -> + getTraceGraphicT mf ctx >>= \(f,w1) ->+ getTraceGraphicT ma ctx >>= \(a,w2) -> + return (f a,w1 `mappend` w2)++++-- Monad++instance Monad (TraceGraphic u) where+ return a = TraceGraphic $ \_ -> (a, mempty)+ ma >>= k = TraceGraphic $ \ctx -> + let (a,w1) = getTraceGraphic ma ctx+ (b,w2) = (getTraceGraphic . k) a ctx+ in (b, w1 `mappend` w2)+ ++instance Monad m => Monad (TraceGraphicT u m) where+ return a = TraceGraphicT $ \_ -> return (a, mempty)+ ma >>= k = TraceGraphicT $ \ctx -> + getTraceGraphicT ma ctx >>= \(a,w1) -> + (getTraceGraphicT . k) a ctx >>= \(b,w2) -> + return (b, w1 `mappend` w2)+ +++-- DrawingCtxM++instance DrawingCtxM (TraceGraphic u) where+ askDC = TraceGraphic $ \ctx -> (ctx, mempty)+ asksDC f = TraceGraphic $ \ctx -> (f ctx, mempty)+ localize upd ma = TraceGraphic $ \ctx -> getTraceGraphic ma (upd ctx)++++instance Monad m => DrawingCtxM (TraceGraphicT u m) where+ askDC = TraceGraphicT $ \ctx -> return (ctx, mempty)+ asksDC f = TraceGraphicT $ \ctx -> return (f ctx, mempty)+ localize upd ma = TraceGraphicT $ \ctx -> getTraceGraphicT ma (upd ctx)++++-- TraceGraphicM++class Monad m => TraceGraphicM m where+ tellImage :: MonUnit (m ()) ~ u => Image u a -> m a+ tellImage_ :: MonUnit (m ()) ~ u => Image u a -> m ()++ tellImage_ ma = tellImage ma >> return ()+++instance TraceGraphicM (TraceGraphic u) where+ tellImage img = TraceGraphic $ \ctx -> + let (PrimW o a) = runImage ctx img in (a,o)++ tellImage_ img = TraceGraphic $ \ctx -> + let (PrimW o _) = runImage ctx img in ((),o)+++instance Monad m => TraceGraphicM (TraceGraphicT u m) where+ tellImage img = TraceGraphicT $ \ctx -> + let (PrimW o a) = runImage ctx img in return (a,o) ++ tellImage_ img = TraceGraphicT $ \ctx -> + let (PrimW o _) = runImage ctx img in return ((),o)+++runTraceGraphic :: TraceGraphic u a -> Image u a+runTraceGraphic mf = askDC >>= \ctx -> let (a,o) = getTraceGraphic mf ctx+ in replaceAns a $ primGraphic o+++-- | Note - this needs DrawingContext as an explicit parameter,+-- and hence it returns a pair of @(a, HPrim u)@ rather than an+-- Image.+--+-- It is expected this will be wrapped in to form a specific+-- TraceDrawing /draw/ function for the amalgamated monad.+-- +runTraceGraphicT :: Monad m + => DrawingContext -> TraceGraphicT u m a -> m (a, HPrim u)+runTraceGraphicT ctx mf = + getTraceGraphicT mf ctx >>= \(a,o) -> return (a, singleH o)+++liftTraceGraphicT :: Monad m => m a -> TraceGraphicT u m a +liftTraceGraphicT ma = TraceGraphicT $ \_ -> ma >>= \a -> return (a,mempty)+
src/Wumpus/Drawing/Connectors.hs view
@@ -20,7 +20,6 @@ , module Wumpus.Drawing.Connectors.Base , module Wumpus.Drawing.Connectors.BoxConnectors , module Wumpus.Drawing.Connectors.ConnectorPaths- , module Wumpus.Drawing.Connectors.Loop ) where @@ -28,4 +27,3 @@ import Wumpus.Drawing.Connectors.Base import Wumpus.Drawing.Connectors.BoxConnectors import Wumpus.Drawing.Connectors.ConnectorPaths-import Wumpus.Drawing.Connectors.Loop
src/Wumpus/Drawing/Connectors/Arrowheads.hs view
@@ -69,7 +69,6 @@ import Data.AffineSpace -- package: vector-space import Data.VectorSpace -import Control.Applicative @@ -85,20 +84,23 @@ filledTipPath :: PointGen -> LocThetaGraphic En filledTipPath fn = - localize fill_use_stroke_colour $ promoteR2 $ \pt theta ->- let vs = fn theta in vertexPP (map (pt .+^) vs) >>= filledPath+ localize fill_use_stroke_colour $ promoteLocTheta $ \pt theta ->+ let vs = fn theta + in zapQuery (vertexPP $ map (pt .+^) vs) >>= dcClosedPath FILL closedTipPath :: PointGen -> LocThetaGraphic En closedTipPath fn = - localize solid_stroke_tip $ promoteR2 $ \pt theta ->- let vs = fn theta in vertexPP (map (pt .+^) vs) >>= closedStroke+ localize solid_stroke_tip $ promoteLocTheta $ \pt theta ->+ let vs = fn theta + in zapQuery (vertexPP $ map (pt .+^) vs) >>= dcClosedPath STROKE openTipPath :: PointGen -> LocThetaGraphic En openTipPath fn = - localize solid_stroke_tip $ promoteR2 $ \pt theta ->- let vs = fn theta in vertexPP (map (pt .+^) vs) >>= openStroke+ localize solid_stroke_tip $ promoteLocTheta $ \pt theta ->+ let vs = fn theta + in zapQuery (vertexPP $ map (pt .+^) vs) >>= dcOpenPath @@ -145,9 +147,6 @@ -zeroVec :: Vec2 En-zeroVec = V2 0 0 - ang90 :: Radian ang90 = pi / 2 @@ -158,153 +157,165 @@ ang45 = pi / 4 -len_one :: InterpretUnit u => Query u-len_one = uconvertCtx1 (1::En) -len_two :: InterpretUnit u => Query u-len_two = uconvertCtx1 (2::En) -len_half :: InterpretUnit u => Query u-len_half = uconvertCtx1 (0.5::En)--len_zero :: InterpretUnit u => Query u-len_zero = pure 0--retract_one :: InterpretUnit u => Query u-retract_one = uconvertCtx1 (1::En)--retract_two :: InterpretUnit u => Query u-retract_two = uconvertCtx1 (2::En)----- retract_half :: InterpretUnit u => Query u--- retract_half = uconvertCtx1 (0.5::En)--retract_zero :: InterpretUnit u => Query u-retract_zero = pure 0----filledTri :: InterpretUnit u => Radian -> ArrowTip u+filledTri :: Radian -> ArrowTip filledTri ang = - makeArrowTip retract_one len_one (filledTipPath spec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = filledTipPath spec+ } where spec theta = let (v1,v2) = tripointsFromTip 1 ang theta in [zeroVec, v1, v2] --tri90 :: InterpretUnit u => ArrowTip u+-- | Filled triangle - apex is 90 deg.+--+tri90 :: ArrowTip tri90 = filledTri ang90 -tri60 :: InterpretUnit u => ArrowTip u+-- | Filled triangle - apex is 60 deg.+--+tri60 :: ArrowTip tri60 = filledTri ang60 -tri45 :: InterpretUnit u => ArrowTip u+-- | Filled triangle - apex is 45 deg.+--+tri45 :: ArrowTip tri45 = filledTri ang45 -strokedClosedTri :: InterpretUnit u => Radian -> ArrowTip u+strokedClosedTri :: Radian -> ArrowTip strokedClosedTri ang = - makeArrowTip retract_one len_one (closedTipPath spec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = closedTipPath spec+ } where spec theta = let (v1,v2) = tripointsFromTip 1 ang theta in [zeroVec, v1, v2] -otri90 :: InterpretUnit u => ArrowTip u+otri90 :: ArrowTip otri90 = strokedClosedTri ang90 -otri60 :: InterpretUnit u => ArrowTip u+otri60 :: ArrowTip otri60 = strokedClosedTri ang60 -otri45 :: InterpretUnit u => ArrowTip u+otri45 :: ArrowTip otri45 = strokedClosedTri ang45 -filledRevTri :: InterpretUnit u => Radian -> ArrowTip u+filledRevTri :: Radian -> ArrowTip filledRevTri ang = - makeArrowTip retract_one len_one (filledTipPath spec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = filledTipPath spec+ } where spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta in [v0, v1, v2] -revtri90 :: InterpretUnit u => ArrowTip u+revtri90 :: ArrowTip revtri90 = filledRevTri ang90 -revtri60 :: InterpretUnit u => ArrowTip u+revtri60 :: ArrowTip revtri60 = filledRevTri ang60 -revtri45 :: InterpretUnit u => ArrowTip u+revtri45 :: ArrowTip revtri45 = filledRevTri ang45 -strokedClosedRevTri :: InterpretUnit u => Radian -> ArrowTip u+strokedClosedRevTri :: Radian -> ArrowTip strokedClosedRevTri ang = - makeArrowTip retract_one len_one (closedTipPath spec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = closedTipPath spec+ } where spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta in [v0, v1, v2] -orevtri90 :: InterpretUnit u => ArrowTip u+orevtri90 :: ArrowTip orevtri90 = strokedClosedRevTri ang90 -orevtri60 :: InterpretUnit u => ArrowTip u+orevtri60 :: ArrowTip orevtri60 = strokedClosedRevTri ang60 -orevtri45 :: InterpretUnit u => ArrowTip u+orevtri45 :: ArrowTip orevtri45 = strokedClosedRevTri ang45 -strokedBarb :: InterpretUnit u => Radian -> ArrowTip u+strokedBarb :: Radian -> ArrowTip strokedBarb ang = - makeArrowTip retract_zero len_one (openTipPath spec)+ ArrowTip+ { retract_distance = const 0+ , tip_half_len = 0.5+ , tip_deco = openTipPath spec+ } where spec theta = let (v1,v2) = tripointsFromTip 1 ang theta in [v1,zeroVec,v2] -barb90 :: InterpretUnit u => ArrowTip u+barb90 :: ArrowTip barb90 = strokedBarb ang90 -barb60 :: InterpretUnit u => ArrowTip u+barb60 :: ArrowTip barb60 = strokedBarb ang60 -barb45 :: InterpretUnit u => ArrowTip u+barb45 :: ArrowTip barb45 = strokedBarb ang45 -strokedRevBarb :: InterpretUnit u => Radian -> ArrowTip u+strokedRevBarb :: Radian -> ArrowTip strokedRevBarb ang = - makeArrowTip retract_one len_one (openTipPath spec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = openTipPath spec+ } where spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta in [v1,v0,v2] -revbarb90 :: InterpretUnit u => ArrowTip u+revbarb90 :: ArrowTip revbarb90 = strokedRevBarb ang90 -revbarb60 :: InterpretUnit u => ArrowTip u+revbarb60 :: ArrowTip revbarb60 = strokedRevBarb ang60 -revbarb45 :: InterpretUnit u => ArrowTip u+revbarb45 :: ArrowTip revbarb45 = strokedRevBarb ang45 -perp :: InterpretUnit u => ArrowTip u+perp :: ArrowTip perp = - makeArrowTip retract_zero len_zero (openTipPath spec)+ ArrowTip+ { retract_distance = const 0+ , tip_half_len = 0+ , tip_deco = openTipPath spec+ } where spec theta = let oa = avec (theta + ang90) 0.5 ob = avec (theta - ang90) 0.5 in [oa, ob] -bracket :: InterpretUnit u => ArrowTip u+bracket :: ArrowTip bracket = - makeArrowTip retract_zero len_half (openTipPath spec)+ ArrowTip+ { retract_distance = const 0+ , tip_half_len = 0.5+ , tip_deco = openTipPath spec+ } where spec theta = let oa = avec (theta + ang90) 0.5 ob = avec (theta - ang90) 0.5@@ -313,26 +324,32 @@ -diskTip :: InterpretUnit u => ArrowTip u+diskTip :: ArrowTip diskTip = - makeArrowTip retract_one len_one - (promoteR2 $ \pt theta -> body theta `at` pt)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = promoteLocTheta $ \pt theta -> body theta `at` pt+ } where body :: Radian -> LocGraphic En body theta = let v1 = avec theta (-0.5) in localize fill_use_stroke_colour $ - moveStart (displaceVec v1) (filledDisk 0.5)+ moveStart v1 (dcDisk FILL 0.5) -odiskTip :: InterpretUnit u => ArrowTip u+odiskTip :: ArrowTip odiskTip = - makeArrowTip retract_one len_one - (promoteR2 $ \pt theta -> body theta `at` pt)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = promoteLocTheta $ \pt theta -> body theta `at` pt+ } where body :: Radian -> LocGraphic En body theta = let v1 = avec theta (-0.5) in localize solid_stroke_tip $ - moveStart (displaceVec v1) (strokedDisk 0.5)+ moveStart v1 (dcDisk STROKE 0.5) -- | squareSpec:@@ -352,13 +369,21 @@ ov = avec theta (-1) -squareTip :: InterpretUnit u => ArrowTip u+squareTip :: ArrowTip squareTip = - makeArrowTip retract_one len_one (filledTipPath squareSpec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = filledTipPath squareSpec+ } -osquareTip :: InterpretUnit u => ArrowTip u+osquareTip :: ArrowTip osquareTip = - makeArrowTip retract_one len_one (closedTipPath squareSpec)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = closedTipPath squareSpec+ } @@ -380,22 +405,38 @@ ob = ov ^+^ avec (theta - ang90) 0.5 -diamondTip :: InterpretUnit u => ArrowTip u+diamondTip :: ArrowTip diamondTip = - makeArrowTip retract_one len_one (filledTipPath $ diamondSpec 1)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = filledTipPath (diamondSpec 1)+ } -odiamondTip :: InterpretUnit u => ArrowTip u+odiamondTip :: ArrowTip odiamondTip = - makeArrowTip retract_one len_one (closedTipPath $ diamondSpec 1)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = closedTipPath (diamondSpec 1)+ } -diamondWideTip :: InterpretUnit u => ArrowTip u+diamondWideTip :: ArrowTip diamondWideTip = - makeArrowTip retract_two len_two (filledTipPath $ diamondSpec 2)+ ArrowTip+ { retract_distance = const 2+ , tip_half_len = 1.0+ , tip_deco = filledTipPath (diamondSpec 2)+ } -odiamondWideTip :: InterpretUnit u => ArrowTip u+odiamondWideTip :: ArrowTip odiamondWideTip = - makeArrowTip retract_two len_two (closedTipPath $ diamondSpec 2)+ ArrowTip+ { retract_distance = const 2+ , tip_half_len = 1.0+ , tip_deco = closedTipPath (diamondSpec 2)+ } curveTipPath :: Point2 En -> Radian -> AbsPath En@@ -410,12 +451,17 @@ (y,z) = trapezoidFromBasePoints 0.125 0.5 x pt -curveTip :: InterpretUnit u => ArrowTip u+curveTip :: ArrowTip curveTip = - makeArrowTip retract_zero len_one- (promoteR2 $ \pt theta -> - localize (join_bevel . solid_stroke_tip) $ - toPrimPath (curveTipPath pt theta) >>= openStroke)+ ArrowTip+ { retract_distance = const 0+ , tip_half_len = 0.5+ , tip_deco = body+ }+ where+ body = promoteLocTheta $ \pt theta -> + localize (join_bevel . solid_stroke_tip) $ + zapQuery (toPrimPath $ curveTipPath pt theta) >>= dcOpenPath @@ -431,12 +477,17 @@ (z,y) = trapezoidFromBasePoints 0.125 0.5 p2 x -revcurveTip :: InterpretUnit u => ArrowTip u+revcurveTip :: ArrowTip revcurveTip = - makeArrowTip retract_one len_one- (promoteR2 $ \pt theta -> - localize (join_bevel . solid_stroke_tip) $ - toPrimPath (curveTipRevPath pt theta) >>= openStroke)+ ArrowTip+ { retract_distance = const 1+ , tip_half_len = 0.5+ , tip_deco = body+ }+ where+ body = promoteLocTheta $ \pt theta -> + localize (join_bevel . solid_stroke_tip) $ + zapQuery (toPrimPath $ curveTipRevPath pt theta) >>= dcOpenPath @@ -458,7 +509,7 @@ base_len = vlength base_vec theta = vdirection base_vec half_ulen = 0.5 * ratio_to_base * base_len- base_mid = displaceParallel (0.5 * base_len) theta p1- ubase_mid = displacePerpendicular u theta base_mid- cp1 = displaceParallel (-half_ulen) theta ubase_mid- cp2 = displaceParallel half_ulen theta ubase_mid+ base_mid = dispParallel (0.5 * base_len) theta p1+ ubase_mid = dispPerpendicular u theta base_mid+ cp1 = dispParallel (-half_ulen) theta ubase_mid+ cp2 = dispParallel half_ulen theta ubase_mid
src/Wumpus/Drawing/Connectors/Base.hs view
@@ -18,16 +18,19 @@ ( Connector ++ , ArrowTip(..) , ArrowConnector- , ArrowTip- , makeArrowTip , leftArrow , rightArrow , leftRightArrow , uniformArrow ++ , rightArrowPath+ - , promoteConn+ , buildConn ) where @@ -39,91 +42,143 @@ import Data.AffineSpace -- package: vector-space --import Control.Applicative-+import Data.Monoid -- | The type of Connectors - a query from start and end point to -- a Path. -- type Connector u = ConnectorQuery u (AbsPath u) +-- | Arrowhead /algorithm/ - the components of an arrowhead.+-- +-- Retract distance may have to account for line width.+--+data ArrowTip = ArrowTip+ { retract_distance :: Double -> En+ , tip_half_len :: En+ , tip_deco :: LocThetaGraphic En+ } +-- Ideally there should be a plus operation to combine tips +-- allowing double tips.+-- type ArrowConnector u = ConnectorImage u (AbsPath u) -type TipDraw = Point2 En -> Radian -> GraphicAns En --- | TipAns - retract_distance * tip length * TipDraw----type TipAns u = (u, u, TipDraw) +runArrowTip :: InterpretUnit u => ArrowTip -> Query u (u, u, LocThetaGraphic u)+runArrowTip (ArrowTip df len deco) = + getLineWidth >>= \lw -> + uconvertCtx1 (df lw) >>= \uretd ->+ uconvertCtx1 len >>= \ulen ->+ return (uretd, ulen, uconvF deco) -data ArrowTip u = ArrowTip { getArrowTip :: CF (TipAns u) } +-- | Connector with an arrow tip at the end point (i.e right).+--+rightArrow :: (Real u, Floating u, InterpretUnit u) + => ArrowTip -> Connector u -> ArrowConnector u+rightArrow alg conn = promoteConn $ \p0 p1 ->+ zapConnectorQuery conn p0 p1 >>= \full_path -> + rightArrowPath alg full_path -- | Connector with an arrow tip at the start point (i.e left). -- leftArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip u -> Connector u -> ArrowConnector u-leftArrow tipl conn = promoteR2 $ \p0 p1 ->- apply2R2 conn p0 p1 >>= \full_path -> - getArrowTip tipl >>= \(dxl,wl,mkl) -> - uconvertCtxF p0 >>= \emp0 -> - let angl = tipDirectionL wl full_path- short_path = shortenL dxl full_path- deco = convertTipAns $ mkl emp0 angl- in fmap (replaceAns full_path) $ - decorateR0 deco $ toPrimPath short_path >>= openStroke---- | Connector with an arrow tip at the end point (i.e right).----rightArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip u -> Connector u -> ArrowConnector u-rightArrow tipr conn = promoteR2 $ \p0 p1 ->- apply2R2 conn p0 p1 >>= \full_path -> - getArrowTip tipr >>= \(dxr,wr,mkl) -> - uconvertCtxF p1 >>= \emp1 -> - let angr = tipDirectionR wr full_path- short_path = shortenR dxr full_path- deco = convertTipAns $ mkl emp1 angr- in fmap (replaceAns full_path) $ - decorateR0 deco $ toPrimPath short_path >>= openStroke+ => ArrowTip -> Connector u -> ArrowConnector u+leftArrow alg conn = promoteConn $ \p0 p1 ->+ zapConnectorQuery conn p0 p1 >>= \full_path -> + leftArrowPath alg full_path --- | Connector with two arrow tips, possibly different.+-- | Connector with different arrow tips at the start point and +-- end points. -- leftRightArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip u -> ArrowTip u -> Connector u - -> ArrowConnector u-leftRightArrow tipl tipr conn = promoteR2 $ \p0 p1 ->- apply2R2 conn p0 p1 >>= \full_path -> - getArrowTip tipl >>= \(dxl,wl,mkl) -> - getArrowTip tipr >>= \(dxr,wr,mkr) -> - uconvertCtxF p0 >>= \emp0 -> - uconvertCtxF p1 >>= \emp1 -> - let angl = tipDirectionL wl full_path- angr = tipDirectionR wr full_path- short_path = shortenPath dxl dxr full_path- deco = convertTipAns $ mkl emp0 angl `oplus` mkr emp1 angr - in fmap (replaceAns full_path) $ - decorateR0 deco $ toPrimPath short_path >>= openStroke+ => ArrowTip -> ArrowTip -> Connector u -> ArrowConnector u+leftRightArrow algl algr conn = promoteConn $ \p0 p1 ->+ zapConnectorQuery conn p0 p1 >>= \full_path -> + leftRightArrowPath algl algr full_path --- | Connector with the same arrow tip at both ends.++-- | Connector with the same arrow tip at the start point and +-- end points. -- uniformArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip u -> Connector u -> ArrowConnector u-uniformArrow utip conn = leftRightArrow utip utip conn+ => ArrowTip -> Connector u -> ArrowConnector u+uniformArrow alg conn = promoteConn $ \p0 p1 ->+ zapConnectorQuery conn p0 p1 >>= \full_path -> + leftRightArrowPath alg alg full_path +-- TODO - possible there are opportunities to be more +-- compositional here. -convertTipAns :: InterpretUnit u => GraphicAns En -> Graphic u-convertTipAns = uconvImageF . pure +-- | Path with an arrow tip at the start point (i.e left).+--+-- TODO - shortening a curve does not seem to be working properly...+-- +--+leftArrowPath :: (Real u, Floating u, InterpretUnit u) + => ArrowTip -> AbsPath u -> Image u (AbsPath u)+leftArrowPath alg full_path =+ zapQuery (runArrowTip alg) >>= \(retract, len, deco) -> + let short_path = if retract > 0 then shortenL retract full_path + else full_path+ mid_ang = tipDirectionL len full_path+ tip = applyLocTheta deco (tipL full_path) mid_ang+ in replaceAns full_path $ + decorate tip $ zapQuery (toPrimPath short_path) >>= dcOpenPath++++-- | Path with an arrow tip at the end point (i.e right).+--+-- TODO - shortening a curve does not seem to be working properly...+-- +--+rightArrowPath :: (Real u, Floating u, InterpretUnit u) + => ArrowTip -> AbsPath u -> Image u (AbsPath u)+rightArrowPath alg full_path =+ zapQuery (runArrowTip alg) >>= \(retract, len, deco) -> + let short_path = if retract > 0 then shortenR retract full_path + else full_path+ mid_ang = tipDirectionR len full_path+ tip = applyLocTheta deco (tipR full_path) mid_ang+ in replaceAns full_path $ + decorate tip $ zapQuery (toPrimPath short_path) >>= dcOpenPath+++++-- | Path with an arrow tip at the end point (i.e right).+--+-- TODO - shortening a curve does not seem to be working properly...+-- +--+leftRightArrowPath :: (Real u, Floating u, InterpretUnit u) + => ArrowTip -> ArrowTip -> AbsPath u -> Image u (AbsPath u)+leftRightArrowPath algl algr full_path =+ zapQuery (runArrowTip algl) >>= \(retractl, lenl, decol) -> + zapQuery (runArrowTip algr) >>= \(retractr, lenr, decor) -> + let short_path = shortenPath retractl retractr full_path+ mid_angl = tipDirectionL lenl full_path+ mid_angr = tipDirectionR lenr full_path+ tipl = applyLocTheta decol (tipL full_path) mid_angl+ tipr = applyLocTheta decor (tipR full_path) mid_angr+ in replaceAns full_path $ + decorate (tipl `mappend` tipr) $ + zapQuery (toPrimPath short_path) >>= dcOpenPath++++ -- | Helper - direction looks best at half the retract distance. -- tipDirectionL :: (Real u, Floating u) => u -> AbsPath u -> Radian@@ -136,37 +191,28 @@ -makeArrowTip :: Query u -> Query u -> LocThetaGraphic En -> ArrowTip u-makeArrowTip retractq lengthq gf = ArrowTip body- where- body = drawingCtx >>= \ctx -> - let rdist = runCF ctx retractq- tlen = runCF ctx lengthq- drawf = runCF ctx gf- in return (rdist,tlen,drawf) - -- | Promote a function from source and dest points to a connector -- function accounting for the separator values in the -- DrawingContext. ----- This should be used instead of @promoteR2@ for functions +-- This should be used instead of @promoteConn@ for functions -- building connectors. ---promoteConn :: (Real u, Floating u, InterpretUnit u) - => (Point2 u -> Point2 u -> CF a) - -> CF (Point2 u -> Point2 u -> a)-promoteConn fn = promoteR2 $ \p0 p1 -> +buildConn :: (Real u, Floating u, InterpretUnit u) + => (Point2 u -> Point2 u -> Image u a) + -> ConnectorImage u a+buildConn fn = promoteConn $ \p0 p1 -> connectorSrcSpace >>= \sep0 -> connectorDstSpace >>= \sep1 -> connectorSrcOffset >>= \off0 -> connectorDstOffset >>= \off1 -> let ang = vdirection $ pvec p0 p1- in fn (displacePerpendicular off0 ang $ p0 .+^ avec ang sep0) - (displacePerpendicular off1 ang $ p1 .-^ avec ang sep1)+ in fn (dispPerpendicular off0 ang $ p0 .+^ avec ang sep0) + (dispPerpendicular off1 ang $ p1 .-^ avec ang sep1) ----- CAUTION - promoteConn projects the spacers along the (straight)+-- CAUTION - buildConn projects the spacers along the (straight) -- connector line. This might not be what is wanted for jointed -- connectors. --
src/Wumpus/Drawing/Connectors/BoxConnectors.hs view
@@ -54,12 +54,12 @@ -- connbox :: (Real u, Floating u, InterpretUnit u) => ConnectorBox u-connbox = promoteR2 $ \p0 p1 -> +connbox = promoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> connectorDstArm >>= \dst_arm -> let ang = vdirection $ pvec p0 p1 - bl = displaceOrtho (V2 (-src_arm) (-src_arm)) ang p0- tl = displaceOrtho (V2 (-src_arm) src_arm ) ang p0- br = displaceOrtho (V2 dst_arm (-src_arm)) ang p1- tr = displaceOrtho (V2 dst_arm src_arm ) ang p1- in vertexPP [ bl, br, tr, tl ] >>= closedStroke+ bl = dispOrtho (V2 (-src_arm) (-src_arm)) ang p0+ tl = dispOrtho (V2 (-src_arm) src_arm ) ang p0+ br = dispOrtho (V2 dst_arm (-src_arm)) ang p1+ tr = dispOrtho (V2 dst_arm src_arm ) ang p1+ in zapQuery (vertexPP [ bl, br, tr, tl ]) >>= dcClosedPath STROKE
src/Wumpus/Drawing/Connectors/ConnectorPaths.hs view
@@ -51,7 +51,7 @@ import Wumpus.Drawing.Paths.Absolute import Wumpus.Basic.Geometry.Quadrant -- package: wumpus-basic-import Wumpus.Basic.Kernel hiding ( promoteR2 )+import Wumpus.Basic.Kernel hiding ( promoteConn ) import Wumpus.Core -- package: wumpus-core @@ -65,7 +65,7 @@ -- | Straight line connector. -- connline :: (Real u, Floating u, InterpretUnit u) => Connector u-connline = promoteConn $ \p0 p1 -> return $ line1 p0 p1+connline = qpromoteConn $ \p0 p1 -> return $ line1 p0 p1 @@ -81,7 +81,7 @@ -- connarc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) => Connector u-connarc = promoteConn $ \p0 p1 -> +connarc = qpromoteConn $ \p0 p1 -> connectorArcAngle >>= \arc_ang -> let v1 = pvec p0 p1 hlen = 0.5 * vlength v1@@ -104,7 +104,7 @@ -- connhdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connhdiagh = promoteConn $ \p0 p1 -> +connhdiagh = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> connectorDstArm >>= \dst_arm -> case quadrant $ vdirection $ pvec p0 p1 of@@ -133,7 +133,7 @@ -- connvdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connvdiagv = promoteConn $ \p0 p1 -> +connvdiagv = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> connectorDstArm >>= \dst_arm -> case quadrant $ vdirection $ pvec p0 p1 of@@ -161,7 +161,7 @@ -- conndiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-conndiagh = promoteConn $ \p0 p1 -> +conndiagh = qpromoteConn $ \p0 p1 -> connectorDstArm >>= \dst_arm -> case quadrant $ vdirection $ pvec p0 p1 of QUAD_NE -> right p0 p1 dst_arm@@ -186,7 +186,7 @@ -- conndiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-conndiagv = promoteConn $ \p0 p1 -> +conndiagv = qpromoteConn $ \p0 p1 -> connectorDstArm >>= \dst_arm -> case quadrant $ vdirection $ pvec p0 p1 of QUAD_NE -> up p0 p1 dst_arm@@ -211,7 +211,7 @@ -- connhdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connhdiag = promoteConn $ \p0 p1 -> +connhdiag = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> case quadrant $ vdirection $ pvec p0 p1 of QUAD_NE -> right p0 p1 src_arm@@ -236,7 +236,7 @@ -- connvdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connvdiag = promoteConn $ \p0 p1 -> +connvdiag = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> case quadrant $ vdirection $ pvec p0 p1 of QUAD_NE -> up p0 p1 src_arm@@ -263,12 +263,12 @@ -- connabar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connabar = promoteConn $ \p0 p1 ->+connabar = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> connectorDstArm >>= \dst_arm -> let ang = vdirection $ pvec p0 p1- in return $ vertexPath [ p0, adisp_north src_arm ang p0- , adisp_north dst_arm ang p1, p1 ]+ in return $ vertexPath [ p0, dispDirectionTheta UP src_arm ang p0+ , dispDirectionTheta UP dst_arm ang p1, p1 ] -- | Bar connector.@@ -281,12 +281,12 @@ -- connbbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connbbar = promoteConn $ \p0 p1 ->+connbbar = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> connectorDstArm >>= \dst_arm -> let ang = vdirection $ pvec p0 p1- in return $ vertexPath [ p0, adisp_south src_arm ang p0- , adisp_south dst_arm ang p1, p1 ]+ in return $ vertexPath [ p0, dispDirectionTheta DOWN src_arm ang p0+ , dispDirectionTheta DOWN dst_arm ang p1, p1 ] @@ -300,7 +300,7 @@ -- connaright :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connaright = promoteConn $ \ p0@(P2 x0 _) p1@(P2 _ y1) ->+connaright = qpromoteConn $ \ p0@(P2 x0 _) p1@(P2 _ y1) -> let mid = P2 x0 y1 in return $ vertexPath [p0, mid, p1] @@ -314,7 +314,7 @@ -- connbright :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connbright = promoteConn $ \ p0@(P2 _ y0) p1@(P2 x1 _) ->+connbright = qpromoteConn $ \ p0@(P2 _ y0) p1@(P2 x1 _) -> let mid = P2 x1 y0 in return $ vertexPath [p0, mid, p1] @@ -341,7 +341,7 @@ -- connhrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connhrr = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+connhrr = qpromoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) -> fmap (directional x0 x1) connectorSrcArm >>= \ src_arm -> let a0 = p0 .+^ hvec src_arm a1 = a0 .+^ vvec (y1 - y0)@@ -361,7 +361,7 @@ -- connrrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connrrh = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+connrrh = qpromoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) -> fmap (directional x0 x1) connectorDstArm >>= \ dst_arm -> let a1 = p1 .-^ hvec dst_arm a0 = a1 .-^ vvec (y1 - y0)@@ -378,7 +378,7 @@ -- connvrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connvrr = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+connvrr = qpromoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) -> fmap (directional y0 y1) connectorSrcArm >>= \ src_arm -> let a0 = p0 .+^ vvec src_arm a1 = a0 .+^ hvec (x1 - x0)@@ -395,7 +395,7 @@ -- connrrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => Connector u-connrrv = promoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->+connrrv = qpromoteConn $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) -> fmap (directional y0 y1) connectorDstArm >>= \ dst_arm -> let a1 = p1 .-^ vvec dst_arm a0 = a1 .-^ hvec (x1 - x0)@@ -432,15 +432,15 @@ -- loopbody :: (Real u, Floating u, Tolerance u, InterpretUnit u) => (u -> u) -> Connector u-loopbody fn = promoteConn $ \p0 p1 ->+loopbody fn = qpromoteConn $ \p0 p1 -> connectorSrcArm >>= \src_arm -> connectorDstArm >>= \dst_arm -> connectorLoopSize >>= \loop_len -> let ang = vdirection $ pvec p0 p1 - a0 = displaceParallel (negate src_arm) ang p0- a1 = displacePerpendicular (fn loop_len) ang a0- z0 = displaceParallel dst_arm ang p1- z1 = displacePerpendicular (fn loop_len) ang z0+ a0 = dispParallel (negate src_arm) ang p0+ a1 = dispPerpendicular (fn loop_len) ang a0+ z0 = dispParallel dst_arm ang p1+ z1 = dispPerpendicular (fn loop_len) ang z0 in return $ vertexPath [ p0, a0, a1, z1, z0, p1 ] -- | Bezier curve connector - the control points are positioned @@ -456,7 +456,7 @@ -- connhbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => Connector u-connhbezier = promoteConn $ \p0 p1 -> +connhbezier = qpromoteConn $ \p0 p1 -> fmap (2*) connectorSrcArm >>= \src_arm -> fmap (2*) connectorDstArm >>= \dst_arm -> case quadrant $ vdirection $ pvec p0 p1 of@@ -483,7 +483,7 @@ -- connvbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => Connector u-connvbezier = promoteConn $ \p0 p1 -> +connvbezier = qpromoteConn $ \p0 p1 -> fmap (2*) connectorSrcArm >>= \src_arm -> fmap (2*) connectorDstArm >>= \dst_arm -> case quadrant $ vdirection $ pvec p0 p1 of
− src/Wumpus/Drawing/Connectors/Loop.hs
@@ -1,86 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Connectors.Loop--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Open loop for a circle (useful for automata diagrams).--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Connectors.Loop- ( - loop- , loopPoints- ) where---import Wumpus.Drawing.Paths.Absolute--import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Kernel-import Wumpus.Core -- package: wumpus-core---import Data.AffineSpace -- package: vector-space------ | Note this has problems vis adding tips as the actual start--- and end points are synthesized.----loop :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => ConnectorQuery u (AbsPath u)-loop = promoteR2 $ \ctr radpt -> - let incl = lineDirection ctr radpt- radius = abs $ vlength $ pvec ctr radpt- ps = loopPoints radius ctr incl- in return $ curvePath ps---- | Note - intermediate names and quadrants represent a loop --- drawn upwards.--- -loopPoints :: (Real u, Floating u) => u -> Point2 u -> Radian -> [Point2 u]-loopPoints circ_radius circ_ctr incl = - [ startl, cp1, cp2, kitel, cp3, cp4, top, cp5, cp6, kiter, cp7, cp8, startr ]- where- hw = 1.25 * circ_radius- height = 3.8 * circ_radius- hminor = 2.72 * circ_radius- hbase = circ_radius / 3- theta = toRadian $ asin $ hbase / circ_radius- start_vec = avec (circularModulo $ incl - quarter_pi) (0.26 * circ_radius)- end_vec = avec (circularModulo $ incl + quarter_pi) (0.26 * circ_radius) - minor_down = negate $ 0.8 * circ_radius - major_up = 0.52 * circ_radius- top_right = negate $ 0.8 * circ_radius- top_left = 0.8 * circ_radius-- top = displaceParallel height incl circ_ctr- kiter = displaceOrtho (V2 hminor (-hw)) incl circ_ctr- kitel = displaceOrtho (V2 hminor (hw) ) incl circ_ctr- - startr = circ_ctr .+^ avec (circularModulo $ incl - theta) circ_radius- startl = circ_ctr .+^ avec (circularModulo $ incl + theta) circ_radius-- -- quadrant III- cp1 = startl .+^ end_vec - cp2 = displaceParallel minor_down incl kitel-- -- quadrant II - cp3 = displaceParallel major_up incl kitel- cp4 = displacePerpendicular top_left incl top-- -- quadrant I- cp5 = displacePerpendicular top_right incl top- cp6 = displaceParallel major_up incl kiter-- -- quadrant IV - cp7 = displaceParallel minor_down incl kiter- cp8 = startr .+^ start_vec
src/Wumpus/Drawing/Dots/AnchorDots.hs view
@@ -1,7 +1,4 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -32,6 +29,14 @@ , DDotLocImage -- * Dots with anchor points+ , smallDisk+ , largeDisk++ , smallCirc+ , largeCirc+++ , dotNone , dotChar , dotText , dotHLine@@ -58,13 +63,11 @@ ) where -import Wumpus.Drawing.Dots.Marks+import Wumpus.Drawing.Dots.SimpleDots ( MarkSize )+import qualified Wumpus.Drawing.Dots.SimpleDots as SD import Wumpus.Drawing.Text.Base.RotTextZero -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Geometry.Intersection-import Wumpus.Basic.Geometry.Paths-import Wumpus.Basic.Geometry.Quadrant+import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core@@ -74,17 +77,15 @@ import Control.Applicative --- An existential thing that supports anchors.--- This means any dot can retun the same (opaque) structure------ But it does mean that which anchor class are supported is --- fixed - the datatype needs a field for each one.--- Supporting north, southeast etc. will also be tedious...++-- | All dots return the same thing a 'DotAnchor' which supports +-- the same (limited) see of anchors. ---data DotAnchor u = forall s. - DotAnchor { center_anchor :: Point2 u- , radial_anchor :: Radian -> Point2 u- , cardinal_anchor :: Cardinal -> Point2 u }+data DotAnchor u = DotAnchor + { center_anchor :: Point2 u+ , radial_anchor :: Radian -> Point2 u+ , cardinal_anchor :: Cardinal -> Point2 u + } type instance DUnit (DotAnchor u) = u @@ -144,16 +145,33 @@ polyCardinal f NORTH_WEST = f (0.75 * pi) +-- | All anchors are the center!+--+zeroAnchor :: Point2 u -> DotAnchor u+zeroAnchor ctr = + DotAnchor { center_anchor = ctr+ , radial_anchor = const ctr + , cardinal_anchor = const ctr } + rectangleAnchor :: (Real u, Floating u) => u -> u -> Point2 u -> DotAnchor u rectangleAnchor hw hh ctr = DotAnchor { center_anchor = ctr , radial_anchor = fn , cardinal_anchor = rectCardinal hw hh ctr } where- fn theta = displaceVec (rectRadialVector hw hh theta) ctr+ fn theta = displace (rectRadialVector hw hh theta) ctr +circleAnchor :: Floating u => u -> Point2 u -> DotAnchor u+circleAnchor rad ctr = + DotAnchor { center_anchor = ctr+ , radial_anchor = fn + , cardinal_anchor = radialCardinal rad ctr }+ where+ fn theta = displace (avec theta rad) ctr++ polygonAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) => [Point2 u] -> Point2 u -> DotAnchor u polygonAnchor ps ctr = @@ -172,33 +190,41 @@ hh = 0.5 * (y2 - y1) in rectangleAnchor hw hh (bl .+^ vec hw hh) -rectangleLDO :: (Real u, Floating u) - => u -> u -> LocQuery u (DotAnchor u)-rectangleLDO w h = - promoteR1 $ \pt -> pure $ rectangleAnchor (w*0.5) (h*0.5) pt +zeroLDO :: LocQuery u (DotAnchor u)+zeroLDO = qpromoteLoc $ \pt -> return $ zeroAnchor pt -circleAnchor :: Floating u => u -> Point2 u -> DotAnchor u-circleAnchor rad ctr = DotAnchor ctr - (\theta -> ctr .+^ (avec theta rad))- (radialCardinal rad ctr)+rectangleLDO :: (Real u, Floating u, InterpretUnit u) + => MarkSize -> MarkSize -> LocQuery u (DotAnchor u)+rectangleLDO w h = qpromoteLoc $ \pt -> + (\uw uh -> rectangleAnchor (uw*0.5) (uh*0.5) pt) + <$> uconvertCtx1 w <*> uconvertCtx1 h -circleLDO :: (Floating u, InterpretUnit u) => LocQuery u (DotAnchor u)-circleLDO = - promoteR1 $ \pt -> - markHeight >>= \diam -> pure $ circleAnchor (diam * 0.5) pt --- This might be better taking a function: ctr -> poly_points--- ...----polygonLDO :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => (u -> Point2 u -> [Point2 u]) -> LocQuery u (DotAnchor u)-polygonLDO mk = - promoteR1 $ \ctr -> - markHeight >>= \h -> let ps = mk h ctr in pure $ polygonAnchor ps ctr+circleLDO :: (Floating u, InterpretUnit u) + => MarkSize -> LocQuery u (DotAnchor u)+circleLDO rad = qpromoteLoc $ \pt -> + uconvertCtx1 rad >>= \urad -> pure $ circleAnchor urad pt +-- Probably better just using bounding circle for polygons +-- If you really care about anchors use shapes+-- ++-- Triangle probably benefits proper calculation...++triangleLDO :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => MarkSize -> LocQuery u (DotAnchor u)+triangleLDO h = qpromoteLoc $ \pt -> + uconvertCtx1 h >>= \uh -> + let alg = pathIterateLocus $ fn3 $ equilateralTriangleVertices uh+ ps = runPathAlgPoint pt alg+ in return $ polygonAnchor ps pt+ where+ fn3 (a,b,c) = [a,b,c]++ -------------------------------------------------------------------------------- @@ -206,6 +232,27 @@ type DDotLocImage = DotLocImage Double ++dotNone :: InterpretUnit u => DotLocImage u+dotNone = intoLocImage zeroLDO SD.dotNone++++smallDisk :: (Floating u, Real u, InterpretUnit u) => DotLocImage u+smallDisk = intoLocImage (circleLDO 0.25) SD.smallDisk+++largeDisk :: (Floating u, Real u, InterpretUnit u) => DotLocImage u+largeDisk = intoLocImage (circleLDO 1.00) SD.largeDisk++smallCirc :: (Floating u, Real u, InterpretUnit u) => DotLocImage u+smallCirc = intoLocImage (circleLDO 0.25) SD.smallCirc+++largeCirc :: (Floating u, Real u, InterpretUnit u) => DotLocImage u+largeCirc = intoLocImage (circleLDO 1.00) SD.largeCirc++ dotChar :: (Floating u, Real u, InterpretUnit u) => Char -> DotLocImage u dotChar ch = dotText [ch] @@ -218,73 +265,77 @@ dotText :: (Floating u, Real u, InterpretUnit u) => String -> DotLocImage u -dotText ss = pushR1 (mapAns bboxRectAnchor) $ ccTextline ss+dotText ss = fmap bboxRectAnchor $ ccTextline ss -- Note - maybe Wumpus-Basic should have a @swapAns@ function? dotHLine :: (Floating u, InterpretUnit u) => DotLocImage u-dotHLine = intoLocImage circleLDO markHLine+dotHLine = intoLocImage (circleLDO 0.5) SD.dotHLine dotVLine :: (Floating u, InterpretUnit u) => DotLocImage u-dotVLine = intoLocImage circleLDO markVLine+dotVLine = intoLocImage (circleLDO 0.5) SD.dotVLine dotX :: (Floating u, InterpretUnit u) => DotLocImage u-dotX = intoLocImage circleLDO markX+dotX = intoLocImage (circleLDO 0.5) SD.dotX dotPlus :: (Floating u, InterpretUnit u) => DotLocImage u-dotPlus = intoLocImage circleLDO markPlus+dotPlus = intoLocImage (circleLDO 0.5) SD.dotPlus dotCross :: (Floating u, InterpretUnit u) => DotLocImage u-dotCross = intoLocImage circleLDO markCross+dotCross = intoLocImage (circleLDO 0.5) SD.dotCross dotDiamond :: (Floating u, InterpretUnit u) => DotLocImage u-dotDiamond = intoLocImage circleLDO markDiamond+dotDiamond = intoLocImage (circleLDO 0.5) SD.dotDiamond dotFDiamond :: (Floating u, InterpretUnit u) => DotLocImage u-dotFDiamond = intoLocImage circleLDO markFDiamond+dotFDiamond = intoLocImage (circleLDO 0.5) SD.dotFDiamond dotDisk :: (Floating u, InterpretUnit u) => DotLocImage u-dotDisk = intoLocImage circleLDO markDisk+dotDisk = intoLocImage (circleLDO 0.5) SD.dotDisk dotSquare :: (Floating u, Real u, InterpretUnit u) => DotLocImage u-dotSquare = - markHeight >>= \h -> intoLocImage (rectangleLDO h h) markSquare+dotSquare = intoLocImage (rectangleLDO 1 1) SD.dotSquare dotCircle :: (Floating u, InterpretUnit u) => DotLocImage u-dotCircle = intoLocImage circleLDO markCircle+dotCircle = intoLocImage (circleLDO 0.5) SD.dotCircle dotPentagon :: (Floating u, InterpretUnit u) => DotLocImage u-dotPentagon = intoLocImage circleLDO markPentagon+dotPentagon = intoLocImage (circleLDO 0.5) SD.dotPentagon dotStar :: (Floating u, InterpretUnit u) => DotLocImage u-dotStar = intoLocImage circleLDO markStar+dotStar = intoLocImage (circleLDO 0.5) SD.dotStar dotAsterisk :: (Floating u, InterpretUnit u) => DotLocImage u-dotAsterisk = intoLocImage circleLDO markAsterisk+dotAsterisk = intoLocImage (circleLDO 0.5) SD.dotAsterisk dotOPlus :: (Floating u, InterpretUnit u) => DotLocImage u-dotOPlus = intoLocImage circleLDO markOPlus+dotOPlus = intoLocImage (circleLDO 0.5) SD.dotOPlus dotOCross :: (Floating u, InterpretUnit u) => DotLocImage u-dotOCross = intoLocImage circleLDO markOCross+dotOCross = intoLocImage (circleLDO 0.5) SD.dotOCross dotFOCross :: (Floating u, InterpretUnit u) => DotLocImage u-dotFOCross = intoLocImage circleLDO markFOCross+dotFOCross = intoLocImage (circleLDO 0.5) SD.dotFOCross dotTriangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => DotLocImage u-dotTriangle = intoLocImage (polygonLDO fn) markTriangle- where - fn h ctr = let (bl,br,top) = equilateralTrianglePoints h ctr in [bl,br,top]+dotTriangle = intoLocImage (triangleLDO 1) SD.dotTriangle+++intoLocImage :: LocQuery u a -> LocImage u z -> LocImage u a+intoLocImage mq gf = promoteLoc $ \pt -> + askDC >>= \ctx -> + let ans = runLocQuery pt ctx mq+ in replaceAns ans $ applyLoc gf pt
− src/Wumpus/Drawing/Dots/Marks.hs
@@ -1,242 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Dots.Marks--- Copyright : (c) Stephen Tetley 2010-2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Marks - dots without anchor handles.------ The text and char marks need loaded glyph metrics for proper --- centering. ------ \*\* WARNING \*\* - names are expected to change - filled and--- background-filled marks need a naming convention.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Dots.Marks- ( --- -- * Marks- markChar- , markText-- , markHLine- , markVLine- , markX- , markPlus- , markCross- , markDiamond- , markFDiamond- , markBDiamond - , markDisk- , markSquare- , markCircle - , markPentagon- , markStar- , markAsterisk- , markOPlus- , markOCross- , markFOCross- , markTriangle-- ) where---import Wumpus.Drawing.Text.Base.RotTextZero--import Wumpus.Basic.Geometry.Paths -- package: wumpus-basic-import Wumpus.Basic.Kernel --import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space-import Data.VectorSpace----- Marks should be the height of a lower-case letter...---- NOTES------ TikZ has both stroked and bordered (filled and outline-stroked)--- marks e.g. square and square*--------infixr 9 `renderPathWith`--renderPathWith :: LocQuery u PrimPath - -> (PrimPath -> Graphic u) - -> LocGraphic u-renderPathWith qy mk = promoteR1 $ \pt -> apply1R1 qy pt >>= mk----markChar :: (Real u, Floating u, InterpretUnit u) => Char -> LocGraphic u-markChar ch = markText [ch]-----markText :: (Real u, Floating u, InterpretUnit u) => String -> LocGraphic u-markText ss = pushR1 ignoreAns $ ccTextline ss------- | Supplied point is the center.----axialLine :: (Fractional u, InterpretUnit u) => Vec2 u -> LocGraphic u-axialLine v = moveStart (\ctr -> ctr .-^ (0.5 *^ v)) (locStraightLine v)---markHLine :: (Fractional u, InterpretUnit u) => LocGraphic u -markHLine = markHeight >>= \h -> axialLine (hvec h)---markVLine :: (Fractional u, InterpretUnit u) => LocGraphic u -markVLine = markHeight >>= \h -> axialLine (vvec h) ---markX :: (Fractional u, InterpretUnit u) => LocGraphic u-markX = markHeight >>= mkX - where- mkX h = let w = 0.75 * h- in axialLine (vec w h) `oplus` axialLine (vec (-w) h)----markPlus :: (Fractional u, InterpretUnit u) => LocGraphic u-markPlus = markVLine `oplus` markHLine---markCross :: (Floating u, InterpretUnit u) => LocGraphic u-markCross = markHeight >>= mkCross- where- mkCross h = axialLine (avec ang h) `oplus` axialLine (avec (-ang) h)- ang = pi*0.25 ---- Note - height is extended slightly to look good...--pathDiamond :: (Fractional u, InterpretUnit u) - => LocQuery u PrimPath-pathDiamond = promoteR1 $ \pt -> - markHeight >>= \h -> let cp = diamondCoordPath (0.5*h) (0.66*h) - in coordinatePrimPath cp pt------ closedStroke :: (a -> ctx -> prim) --- pathDiamond :: (ctx -> pt -> a)--- ans :: (ctx -> pt -> prim)--markDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u-markDiamond = pathDiamond `renderPathWith` closedStroke--markFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u-markFDiamond = pathDiamond `renderPathWith` filledPath----- Note - the (const . fn) composition doesn\'t /tell/ much about--- what is going on - though obviously it can be decoded - make --- the function obvious to the second argument. --- --- A named combinator might be better.-----markBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u-markBDiamond = pathDiamond `renderPathWith` borderedPath----- | Note disk is filled.----markDisk :: (Fractional u, InterpretUnit u) => LocGraphic u-markDisk = markHalfHeight >>= filledDisk----markSquare :: (Fractional u, InterpretUnit u) => LocGraphic u-markSquare = - markHeight >>= \h -> - let d = 0.5*(-h) in moveStart (displace d d) $ strokedRectangle h h- ---markCircle :: (Fractional u, InterpretUnit u) => LocGraphic u-markCircle = markHalfHeight >>= strokedDisk---markBCircle :: (Fractional u, InterpretUnit u) => LocGraphic u-markBCircle = markHalfHeight >>= borderedDisk ----markPentagon :: (Floating u, InterpretUnit u) => LocGraphic u-markPentagon = promoteR1 $ \pt -> - pentagonPath pt >>= closedStroke- where- pentagonPath pt = markHalfHeight >>= \hh -> - coordinatePrimPath (polygonCoordPath 5 hh) pt-- ---markStar :: (Floating u, InterpretUnit u) => LocGraphic u -markStar = markHeight >>= \h -> starLines (0.5*h)--starLines :: (Floating u, InterpretUnit u) => u -> LocGraphic u-starLines hh = promoteR1 $ \ctr -> - let cp = polygonCoordPath 5 hh- in step $ map (fn ctr) $ cp ctr- where- fn p0 p1 = straightLine p0 p1- step (x:xs) = oconcat x xs- step _ = error "starLines - unreachable"---markAsterisk :: (Floating u, InterpretUnit u) => LocGraphic u-markAsterisk = markHeight >>= asteriskLines--asteriskLines :: (Floating u, InterpretUnit u) => u -> LocGraphic u-asteriskLines h = lineF1 `oplus` lineF2 `oplus` lineF3- where- ang = (pi*2) / 6- lineF1 = axialLine (vvec h)- lineF2 = axialLine (avec ((pi*0.5) + ang) h)- lineF3 = axialLine (avec ((pi*0.5) + ang + ang) h)---markOPlus :: (Fractional u, InterpretUnit u) => LocGraphic u-markOPlus = markCircle `oplus` markPlus---markOCross :: (Floating u, InterpretUnit u) => LocGraphic u-markOCross = markCircle `oplus` markCross---markFOCross :: (Floating u, InterpretUnit u) => LocGraphic u-markFOCross = markCross `oplus` markBCircle ----- bkCircle :: (Fractional u, InterpretUnit u) => LocGraphic u--- bkCircle = disk (fillAttr attr) (0.5*markHeight attr) ----markTriangle :: (Floating u, InterpretUnit u) => LocGraphic u-markTriangle = tripath `renderPathWith` closedStroke- where- tripath = promoteR1 $ \pt -> - markHeight >>= \h -> - let cp = equilateralTriangleCoordPath h- in coordinatePrimPath cp pt-
+ src/Wumpus/Drawing/Dots/SimpleDots.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Dots.SimpleDots+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Simple dots - no anchor handles.+-- +-- Use these where you just want to draw Dots, and do not need+-- connectors between them. +--+-- The text and char marks need loaded glyph metrics for proper +-- centering. +--+-- \*\* WARNING \*\* - names are expected to change - filled and+-- background-filled marks need a naming convention.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Dots.SimpleDots+ ( ++ -- * Unit for marks (0.75 the font size)+ MarkSize++ , smallDisk+ , largeDisk+ , smallCirc+ , largeCirc ++++ -- * Dots+ , dotNone++ , dotChar+ , dotText++ , dotHLine+ , dotVLine+ , dotX+ , dotPlus+ , dotCross+ , dotDiamond+ , dotFDiamond+ , dotBDiamond + , dotDisk+ , dotSquare+ , dotCircle + , dotPentagon+ , dotStar+ , dotAsterisk+ , dotOPlus+ , dotOCross+ , dotFOCross+ , dotTriangle++ ) where+++import Wumpus.Drawing.Text.Base.RotTextZero++import Wumpus.Basic.Geometry -- package: wumpus-basic+import Wumpus.Basic.Kernel ++import Wumpus.Core -- package: wumpus-core++import Data.VectorSpace -- package: vector-space++import Data.Monoid++-- Marks should be the height of a lower-case letter...++-- NOTES+--+-- TikZ has both stroked and bordered (filled and outline-stroked)+-- marks e.g. square and square*+--++-- Cap height is a good size for Dots.+++-- | MarkUnit is a contextual unit like 'Em' and 'En'.+-- +-- It is 3\/4 of the current font size.+--+newtype MarkSize = MarkSize { getMarkSize :: Double }+ deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)++instance Show MarkSize where+ showsPrec p d = showsPrec p (getMarkSize d)+++instance InterpretUnit MarkSize where+ normalize sz a = (realToFrac a) * 0.75 * fromIntegral sz+ dinterp sz d = (4/3) * (realToFrac d) / (fromIntegral sz)+++umark :: InterpretUnit u => LocGraphic MarkSize -> LocGraphic u+umark = uconvF+++-- | Filled disk - radius 0.25 MarkSize.+--+smallDisk :: InterpretUnit u => LocGraphic u+smallDisk = umark $ dcDisk FILL 0.25+++-- | Filled disk - radius 1.0 MarkSize.+--+largeDisk :: InterpretUnit u => LocGraphic u+largeDisk = umark $ dcDisk FILL 1+++-- | Stroked disk (circle) - radius 0.25 MarkSize.+--+smallCirc :: InterpretUnit u => LocGraphic u+smallCirc = umark $ dcDisk STROKE 0.25+++-- | Stroked disk (circle) - radius 1.0 MarkSize.+--+largeCirc :: InterpretUnit u => LocGraphic u+largeCirc = umark $ dcDisk STROKE 1+++-- possibly:+-- szCirc :: u -> LocGraphic u++dotNone :: InterpretUnit u => LocGraphic u+dotNone = emptyLocImage++dotChar :: (Real u, Floating u, InterpretUnit u) => Char -> LocGraphic u+dotChar ch = dotText [ch]++++dotText :: (Real u, Floating u, InterpretUnit u) => String -> LocGraphic u+dotText ss = ignoreAns $ ccTextline ss+++++-- | Supplied point is the center.+--+axialLine :: (Fractional u, InterpretUnit u) => Vec2 u -> LocGraphic u+axialLine v = moveStart (negateV (0.5 *^ v)) (locStraightLine v)+++dotHLine :: (Fractional u, InterpretUnit u) => LocGraphic u +dotHLine = umark $ axialLine (hvec 1)+++dotVLine :: (Fractional u, InterpretUnit u) => LocGraphic u +dotVLine = umark $ axialLine (vvec 1) +++dotX :: (Fractional u, InterpretUnit u) => LocGraphic u+dotX = umark $ axialLine (vec 0.75 1) `mappend` axialLine (vec (-0.75) 1)++++dotPlus :: (Fractional u, InterpretUnit u) => LocGraphic u+dotPlus = dotVLine `mappend` dotHLine+++dotCross :: (Floating u, InterpretUnit u) => LocGraphic u+dotCross = + umark $ axialLine (avec ang 1) `mappend` axialLine (avec (-ang) 1)+ where + ang = pi*0.25 ++++++dotDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u+dotDiamond = umark $ drawVertexPathAlg STROKE (diamondPathAlg 0.5 0.66)++dotFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u+dotFDiamond = umark $ drawVertexPathAlg FILL (diamondPathAlg 0.5 0.66)++++dotBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u+dotBDiamond = umark $ drawVertexPathAlg FILL_STROKE (diamondPathAlg 0.5 0.66)+++-- | Note disk is filled.+--+dotDisk :: (Fractional u, InterpretUnit u) => LocGraphic u+dotDisk = umark $ dcDisk FILL 0.5++++dotSquare :: (Fractional u, InterpretUnit u) => LocGraphic u+dotSquare = umark $ drawVertexPathAlg STROKE (rectanglePathAlg 1 1)+++dotCircle :: (Fractional u, InterpretUnit u) => LocGraphic u+dotCircle = umark $ dcDisk STROKE 0.5+++dotBCircle :: (Fractional u, InterpretUnit u) => LocGraphic u+dotBCircle = umark $ dcDisk FILL_STROKE 0.5++++dotPentagon :: (Floating u, InterpretUnit u) => LocGraphic u+dotPentagon = umark $ drawVertexPathAlg STROKE (polygonPathAlg 5 0.5)+ +++dotStar :: (Floating u, InterpretUnit u) => LocGraphic u +dotStar = umark $ starLines 0.5++starLines :: (Floating u, InterpretUnit u) => u -> LocGraphic u+starLines hh = promoteLoc $ \ctr -> + let ps = runPathAlgPoint ctr $ polygonPathAlg 5 hh+ in step $ map (fn ctr) ps+ where+ fn p0 p1 = straightLine p0 p1+ step (x:xs) = mconcat $ x:xs+ step _ = error "starLines - unreachable"+++dotAsterisk :: (Floating u, InterpretUnit u) => LocGraphic u+dotAsterisk = umark $ asteriskLines 1++asteriskLines :: (Floating u, InterpretUnit u) => u -> LocGraphic u+asteriskLines h = lineF1 `mappend` lineF2 `mappend` lineF3+ where+ ang = (pi*2) / 6+ lineF1 = axialLine (vvec h)+ lineF2 = axialLine (avec ((pi*0.5) + ang) h)+ lineF3 = axialLine (avec ((pi*0.5) + ang + ang) h)+++dotOPlus :: (Fractional u, InterpretUnit u) => LocGraphic u+dotOPlus = dotCircle `mappend` dotPlus+++dotOCross :: (Floating u, InterpretUnit u) => LocGraphic u+dotOCross = dotCircle `mappend` dotCross+++dotFOCross :: (Floating u, InterpretUnit u) => LocGraphic u+dotFOCross = dotBCircle `mappend` dotCross+++-- bkCircle :: (Fractional u, InterpretUnit u) => LocGraphic u+-- bkCircle = disk (fillAttr attr) (0.5*markHeight attr) ++++dotTriangle :: (Floating u, InterpretUnit u) => LocGraphic u+dotTriangle = umark $ drawVertexPathAlg STROKE alg + where+ alg = pathIterateLocus $ fn3 $ equilateralTriangleVertices 1+ fn3 = \(a,b,c) -> [a,b,c]
src/Wumpus/Drawing/Extras/Axes.hs view
@@ -26,24 +26,23 @@ import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core +import Data.Monoid -- Note - axes need labels working out... --- | Draw axes from (0,0).+-- | Simple orthonormal axes using snap grid units. -- orthontAxes :: (Real u, Floating u, InterpretUnit u)- => (Double, Double) -> Graphic u-orthontAxes (w,h) = - snapmove (1,1) >>= \(V2 w1 h1) ->+ => (Int,Int) -> (Int,Int) -> LocGraphic u+orthontAxes (xl,xr) (yl,yr) = + promoteLoc $ \(P2 x y) -> + snapmove (1,1) >>= \(V2 uw uh) -> let conn1 = rightArrow barb45 connline- uw = w1 * realToFrac w- uh = h1 * realToFrac h- ptX = displaceH uw zeroPt- ptY = displaceV uh zeroPt- in localize cap_square $ graphic_ (connect conn1 zeroPt ptX) - `oplus` graphic_ (connect conn1 zeroPt ptY)-+ xPtl = P2 (x - (uw * fromIntegral xl)) y+ xPtr = P2 (x + (uw * fromIntegral xr)) y+ yPtl = P2 x (y - (uh * fromIntegral yl))+ yPtr = P2 x (y + (uh * fromIntegral yr))+ in localize cap_square $ ignoreAns (connect xPtl xPtr conn1) + `mappend` ignoreAns (connect yPtl yPtr conn1) - -
+ src/Wumpus/Drawing/Extras/Clip.hs view
@@ -0,0 +1,41 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Extras.Clip+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Clipping paths.+--+-- Note - at the moment there is nothing much to this module.+-- Ideally, clipping would be defined in Wumpus-Basic, but clipping+-- needs a higher level path object than Wumpus-Basic provides.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Extras.Clip+ ( + + locClip++ ) where+++import Wumpus.Drawing.Paths.Relative++import Wumpus.Basic.Kernel -- package: wumpus-basic+++++-- | Clip a LocGraphic.+--+locClip :: InterpretUnit u => RelPath u -> LocGraphic u -> LocGraphic u+locClip rp gf = promoteLoc $ \pt -> + zapQuery (toPrimPath pt rp) >>= \pp -> clipImage pp (gf `at` pt)+
src/Wumpus/Drawing/Extras/Grids.hs view
@@ -20,6 +20,8 @@ GridContextF , grid , standard_grid+ , dotted_major_grid+ , grid_major_colour , grid_major_line_width , grid_major_dotnum@@ -33,11 +35,14 @@ ) where +import Wumpus.Drawing.Basis.DrawingPrimitives+import Wumpus.Drawing.Basis.LocTrace+ import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core import Wumpus.Core.Colour ( black ) -+import Data.Monoid type GridContextF = GridProps -> GridProps@@ -74,18 +79,16 @@ -grid :: (Fractional u, InterpretUnit u) - => GridContextF -> (Int,Int) -> (Int,Int) -> Graphic u -grid upd bl tr = go (upd default_grid_props)- where- go props | gp_minor_subdivs props < 1 = gridMajor bl tr props- | otherwise = gridMinor bl tr props `oplus` gridMajor bl tr props -- standard_grid :: GridContextF standard_grid = id +dotted_major_grid :: GridContextF+dotted_major_grid = + grid_minor_subdivisions 0 . grid_major_dotnum 2++-- Setters for client code.+ grid_major_colour :: RGBi -> GridContextF grid_major_colour rgb = (\s -> s { gp_major_colour = rgb }) @@ -96,7 +99,7 @@ grid_major_dotnum n = (\s -> s { gp_major_dotnum = n }) grid_minor_subdivisions :: Int -> GridContextF-grid_minor_subdivisions n = (\s -> s { gp_major_dotnum = n })+grid_minor_subdivisions n = (\s -> s { gp_minor_subdivs = n }) grid_minor_colour :: RGBi -> GridContextF grid_minor_colour rgb = (\s -> s { gp_minor_colour = rgb })@@ -117,28 +120,20 @@ --------------------------------------------------------------------------------- ---gridMinor :: (Fractional u, InterpretUnit u) - => (Int,Int) -> (Int,Int) -> GridProps -> Graphic u-gridMinor bl tr props = - let mi = minorInterior bl tr (gp_minor_subdivs props)- minF = lineProps (gp_minor_colour props) (gp_minor_lnwidth props)- (gp_minor_dotnum props)- in localize minF mi--gridMajor :: (Fractional u, InterpretUnit u) - => (Int,Int) -> (Int,Int) -> GridProps -> Graphic u-gridMajor bl tr props = - let mj = majorInterior bl tr- outer = outerRect bl tr- majF = lineProps (gp_major_colour props) (gp_major_lnwidth props)- (gp_major_dotnum props) - in localize majF (mj `oplus` outer)+-- Drawing context updaters... +major_line_update :: GridProps -> DrawingContextF+major_line_update (GridProps { gp_major_colour = rgb+ , gp_major_lnwidth = lnwidth+ , gp_major_dotnum = dotnum }) = + lineProps rgb lnwidth dotnum +minor_line_update :: GridProps -> DrawingContextF+minor_line_update (GridProps { gp_minor_colour = rgb+ , gp_minor_lnwidth = lnwidth+ , gp_minor_dotnum = dotnum }) = + lineProps rgb lnwidth dotnum lineProps :: RGBi -> Double -> Int -> DrawingContextF@@ -149,81 +144,67 @@ dashesF = set_dash_pattern $ Dash 0 [(1,n)] --- | Coordinates are expected to be normalized.----outerRect :: (Fractional u, InterpretUnit u) - => (Int,Int) -> (Int,Int) -> Graphic u -outerRect cbl@(xmin,ymin) (xmaj,ymaj) = - snapmove (xmaj-xmin, ymaj-ymin) >>= \(V2 uw uh) ->- position cbl >>= \bl ->- strokedRectangle uw uh `at` bl +-------------------------------------------------------------------------------- --- | The major interior is the snap grid. ----majorInterior :: (Fractional u, InterpretUnit u)- => (Int,Int) -> (Int,Int) -> Graphic u-majorInterior cbl@(xmin,ymin) (xmaj,ymaj) = - snapmove (xmaj-xmin, ymaj-ymin) >>= \(V2 uw uh) ->- snapmove (1,1) >>= \(V2 w1 h1) ->- position cbl >>= \bl ->- let xcount = sub1 (xmaj - xmin)- ycount = sub1 (ymaj - ymin)- hlines = chainlike ycount (displaceV h1) (hline uw)- vlines = chainlike xcount (displaceH w1) (vline uh)- in (apply1R1 hlines $ displaceV h1 bl) - `oplus` (apply1R1 vlines $ displaceH w1 bl) +grid :: (Fractional u, InterpretUnit u) + => GridContextF -> Int -> Int -> LocGraphic u +grid upd nx ny = + snapmove (1,1) >>= \(V2 uw uh) ->+ let props = upd default_grid_props+ width = uw * fromIntegral nx+ height = uh * fromIntegral ny+ intrr = gridInterior nx width uw ny height uh props+ rect = localize (major_line_update props) $ + blRectangle STROKE width height+ in intrr `mappend` rect + +gridInterior :: (Fractional u, InterpretUnit u) + => Int -> u -> u -> Int -> u -> u -> GridProps -> LocGraphic u+gridInterior nx w uw ny h uh props = hlines `mappend` vlines+ where+ hlines = horizontalLines ny w uh props+ vlines = verticalLines nx h uw props --- | The minor interior divides each element of the snap grid.----minorInterior :: (Fractional u, InterpretUnit u)- => (Int,Int) -> (Int,Int) -> Int -> Graphic u-minorInterior cbl@(xmin,ymin) (xmaj,ymaj) scount = - snapmove (xmaj-xmin, ymaj-ymin) >>= \(V2 uw uh) ->- snapmove (1,1) >>= \(V2 w1 h1) ->- position cbl >>= \bl ->- let xcount = xmaj - xmin- ycount = ymaj - ymin- subw1 = w1 / fromIntegral scount- subh1 = h1 / fromIntegral scount- hlines1 = moveStart (displaceV subh1) - $ chainlike (scount-1) (displaceV subh1) (hline uw)+horizontalLines :: (Fractional u, InterpretUnit u) + => Int -> u -> u -> GridProps -> LocGraphic u+horizontalLines numh w uh props@(GridProps { gp_minor_subdivs = subs })+ | subs > 0 = let dy = uh / (fromIntegral subs)+ n = (numh * subs) - 1+ in moveStart (vvec dy) $ minorMajor n subs (vvec dy) mnr mjr+ | otherwise = moveStart (vvec uh) $ duplicate numh (vvec uh) mjr+ where+ mnr = localize (minor_line_update props) $ hline w+ mjr = localize (major_line_update props) $ hline w - vlines1 = moveStart (displaceH subw1) - $ chainlike (scount-1) (displaceH subw1) (vline uh)- hlines = chainlike ycount (displaceV h1) hlines1- vlines = chainlike xcount (displaceH w1) vlines1 - in (apply1R1 hlines bl) - `oplus` (apply1R1 vlines bl) --- This doesn\'t work as an advGraphic----- | This is an operation chain should support, but chain needs a --- rethink...----chainlike :: Int -> PointDisplace u -> LocGraphic u -> LocGraphic u-chainlike i mv g = promoteR1 $ \start -> go (i-1) (g `at` start) (mv start)+verticalLines :: (Fractional u, InterpretUnit u) + => Int -> u -> u -> GridProps -> LocGraphic u+verticalLines numv h uw props@(GridProps { gp_minor_subdivs = subs })+ | subs > 0 = let dx = uw / (fromIntegral subs)+ n = (numv * subs) - 1+ in moveStart (hvec dx) $ minorMajor n subs (hvec dx) mnr mjr+ | otherwise = moveStart (hvec uw) $ duplicate numv (hvec uw) mjr where- go n acc pt | n < 1 = acc- | otherwise = go (n-1) (acc `oplus` (g `at` pt)) (mv pt)- + mnr = localize (minor_line_update props) $ vline h+ mjr = localize (major_line_update props) $ vline h -vline :: InterpretUnit u => u -> LocGraphic u -vline len = locStraightLine $ vvec len -hline :: InterpretUnit u => u -> LocGraphic u -hline len = locStraightLine $ hvec len ---sub1 :: Num u => u -> u-sub1 = subtract 1+minorMajor :: Num u + => Int -> Int -> Vec2 u -> LocGraphic u -> LocGraphic u + -> LocGraphic u+minorMajor count alt mv mnr mjr = execLocTrace (step count)+ where+ step n | n <= 0 = return ()+ | n `mod` alt == 0 = insertl mjr >> moveBy mv >> step (n-1)+ | otherwise = insertl mnr >> moveBy mv >> step (n-1)+
+ src/Wumpus/Drawing/Extras/Loop.hs view
@@ -0,0 +1,95 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Extras.Loop+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Open loop for a circle (useful for automata diagrams).+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Extras.Loop+ ( + loop+ , loopPoints+ ) where+++import Wumpus.Drawing.Paths.Absolute++import Wumpus.Basic.Geometry.Base -- package: wumpus-basic+import Wumpus.Basic.Kernel+import Wumpus.Core -- package: wumpus-core+++import Data.AffineSpace -- package: vector-space+++-- TODO - Loop is a decoration not a connector.+-- It should probably have the same signature as wedge / arc.++-- | Generate a loop - suitable for decorating a circle.+--+-- The radius and the (implicit) start point are the center and +-- radius of the initial circle not the loop itself.+--+loop :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Point2 u -> Radian -> Query u (AbsPath u)+loop zradius zctr ang = return $ curvePath $ loopPoints zradius zctr ang++++-- Should be able to use trig to get a loop suitable for+-- decorating rectangles (provided the start-to-end arc is smaller+-- than the side length+++++-- | Note - intermediate names and quadrants represent a loop +-- drawn upwards.+-- +loopPoints :: (Real u, Floating u) => u -> Point2 u -> Radian -> [Point2 u]+loopPoints circ_radius circ_ctr incl = + [ startl, cp1, cp2, kitel, cp3, cp4, top, cp5, cp6, kiter, cp7, cp8, startr ]+ where+ hw = 1.25 * circ_radius+ height = 3.8 * circ_radius+ hminor = 2.72 * circ_radius+ hbase = circ_radius / 3+ theta = toRadian $ asin $ hbase / circ_radius+ start_vec = avec (circularModulo $ incl - quarter_pi) (0.26 * circ_radius)+ end_vec = avec (circularModulo $ incl + quarter_pi) (0.26 * circ_radius) + minor_down = negate $ 0.8 * circ_radius + major_up = 0.52 * circ_radius+ top_right = negate $ 0.8 * circ_radius+ top_left = 0.8 * circ_radius++ top = dispParallel height incl circ_ctr+ kiter = dispOrtho (V2 hminor (-hw)) incl circ_ctr+ kitel = dispOrtho (V2 hminor (hw) ) incl circ_ctr+ + startr = circ_ctr .+^ avec (circularModulo $ incl - theta) circ_radius+ startl = circ_ctr .+^ avec (circularModulo $ incl + theta) circ_radius++ -- quadrant III+ cp1 = startl .+^ end_vec + cp2 = dispParallel minor_down incl kitel++ -- quadrant II + cp3 = dispParallel major_up incl kitel+ cp4 = dispPerpendicular top_left incl top++ -- quadrant I+ cp5 = dispPerpendicular top_right incl top+ cp6 = dispParallel major_up incl kiter++ -- quadrant IV + cp7 = dispParallel minor_down incl kiter+ cp8 = startr .+^ start_vec
− src/Wumpus/Drawing/Extras/Turtle/TurtleClass.hs
@@ -1,91 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Extras.Turtle.TurtleClass--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Turtle monad and monad transformer.------ The Turtle monad embodies the LOGO style of imperative --- drawing - sending commands to update the a cursor.------ While Wumpus generally aims for a more compositional,--- \"coordinate-free\" style of drawing, some types of diagram --- are more easily expressed in the LOGO style.------ Note - as turtle drawing with Wumpus is a /local effect/, --- there is only one instance of TurtleM. Potentially TurtleM --- will be removed and the functions implemented directly. --------------------------------------------------------------------------------------module Wumpus.Drawing.Extras.Turtle.TurtleClass- (-- Coord-- , TurtleM(..)-- , setsLoc- , setsLoc_-- -- * movement- , resetLoc- , moveLeft- , moveRight- , moveUp- , moveDown- , nextLine- -- ) where----type Coord = (Int,Int)---class Monad m => TurtleM m where- getLoc :: m (Int,Int)- setLoc :: (Int,Int) -> m ()- getOrigin :: m (Int,Int)- setOrigin :: (Int,Int) -> m ()----setsLoc :: TurtleM m => (Coord -> (a,Coord)) -> m a-setsLoc f = getLoc >>= \coord -> - let (a,coord') = f coord in setLoc coord' >> return a--setsLoc_ :: TurtleM m => (Coord -> Coord) -> m ()-setsLoc_ f = getLoc >>= \coord -> setLoc (f coord)---resetLoc :: TurtleM m => m ()-resetLoc = getOrigin >>= setLoc---moveRight :: TurtleM m => m ()-moveRight = setsLoc_ $ \(x,y)-> (x+1, y)---moveLeft :: TurtleM m => m ()-moveLeft = setsLoc_ $ \(x,y) -> (x-1,y)--moveUp :: TurtleM m => m ()-moveUp = setsLoc_ $ \(x,y) -> (x,y+1)--moveDown :: TurtleM m => m ()-moveDown = setsLoc_ $ \(x,y) -> (x ,y-1)---nextLine :: TurtleM m => m ()-nextLine = getOrigin >>= \(ox,_) ->- setsLoc_ $ \(_,y) -> (ox,y-1)-
− src/Wumpus/Drawing/Extras/Turtle/TurtleMonad.hs
@@ -1,132 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Extras.Turtle.TurtleMonad--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC ------ Turtle monad transformer.------ The Turtle monad embodies the LOGO style of imperative --- drawing - sending commands to update the a cursor.------ While Wumpus generally aims for a more compositional,--- \"coordinate-free\" style of drawing, some types of --- diagram are more easily expressed in the LOGO style.------ Turtle is only a transformer - it is intended to be run within--- a 'Drawing'.--------------------------------------------------------------------------------------module Wumpus.Drawing.Extras.Turtle.TurtleMonad- (- -- * Re-exports- module Wumpus.Drawing.Extras.Turtle.TurtleClass-- -- * Turtle transformer- , TurtleT- , runTurtleT-- - ) where--import Wumpus.Drawing.Extras.Turtle.TurtleClass--import Wumpus.Basic.Kernel -- package: wumpus-basic---import Control.Applicative-import Control.Monad----- Note - if Turtle is now just a /local effect/ monad is the --- Turtle class still needed? Afterall, there is (probably)--- only ever going to be one instance.------- Turtle is a Reader / State monad--- --- The env is the horizontal and vertical move distances.--- --- The state is the current coordinate and the origin.-----data TurtleState = TurtleState - { _turtle_origin :: (Int,Int)- , _current_coord :: (Int,Int)- }--newtype TurtleT u m a = TurtleT { - getTurtleT :: TurtleState -> m (a, TurtleState) }-- -type instance MonUnit (TurtleT u m a) = u---- Functor----instance Monad m => Functor (TurtleT u m) where- fmap f m = TurtleT $ \s -> getTurtleT m s >>= \(a,s') ->- return (f a, s')----- Applicative --instance Monad m => Applicative (TurtleT u m) where- pure a = TurtleT $ \s -> return (a,s)- mf <*> ma = TurtleT $ \s -> getTurtleT mf s >>= \(f,s') ->- getTurtleT ma s' >>= \(a,s'') ->- return (f a,s'') ----- Monad --instance Monad m => Monad (TurtleT u m) where- return a = TurtleT $ \s -> return (a,s)- m >>= k = TurtleT $ \s -> getTurtleT m s >>= \(a,s') ->- (getTurtleT . k) a s'-----instance Monad m => TurtleM (TurtleT u m) where- getLoc = TurtleT $ \s@(TurtleState _ c) -> return (c,s)- setLoc c = TurtleT $ \(TurtleState o _) -> return ((),TurtleState o c)- getOrigin = TurtleT $ \s@(TurtleState o _) -> return (o,s)- setOrigin o = TurtleT $ \(TurtleState _ c) -> return ((),TurtleState o c)---runTurtleT :: (Monad m, Num u) - => (Int,Int) -> TurtleT u m a -> m a-runTurtleT ogin mf = getTurtleT mf st0 >>= \(a,_) -> return a- where - st0 = TurtleState ogin ogin ----------------------------------------------------------------------------------------- Cross instances--instance DrawingCtxM m => DrawingCtxM (TurtleT u m) where- askDC = TurtleT $ \s -> askDC >>= \ ctx -> return (ctx,s)- localize upd mf = TurtleT $ \s -> localize upd (getTurtleT mf s)----- This needs undecidable instances...--instance (Monad m, TraceM m, u ~ MonUnit (m ()) ) => TraceM (TurtleT u m) where- trace a = TurtleT $ \s -> trace a >> return ((),s)- fontDelta mf = TurtleT $ \s -> fontDelta $ getTurtleT mf s--
src/Wumpus/Drawing/Paths/Absolute.hs view
@@ -18,11 +18,11 @@ module Wumpus.Drawing.Paths.Absolute ( - module Wumpus.Drawing.Paths.Base.AbsBuilder- , module Wumpus.Drawing.Paths.Base.AbsPath+ module Wumpus.Drawing.Paths.Base.AbsPath+ , module Wumpus.Drawing.Paths.Base.PathBuilder ) where -import Wumpus.Drawing.Paths.Base.AbsBuilder import Wumpus.Drawing.Paths.Base.AbsPath+import Wumpus.Drawing.Paths.Base.PathBuilder
− src/Wumpus/Drawing/Paths/Base/AbsBuilder.hs
@@ -1,561 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.Base.AbsBuilder--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Build absolute paths monadically.------ \*\* WARNING \*\* this module is an experiment, and may --- change significantly or even be dropped from future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.Base.AbsBuilder- ( -- AbsBuild- , runAbsBuild- , execAbsBuild- , evalAbsBuild-- , tip-- , absline- , abscurve- , absmove-- , relline- , relcurve- , relmove-- , rellineParallel- , rellinePerpendicular-- , relmoveParallel- , relmovePerpendicular---- , ctrlcurve-- , insert- , vamp- , cycle- , setIncline-- -- * Derived operators- , pen_colour- , pen_width-- , hline- , vline- , aline-- , hmove- , vmove- , amove-- , line_up- , line_down- , line_left- , line_right-- , line_up_left- , line_up_right- , line_down_left- , line_down_right-- , line_north- , line_south- , line_east- , line_west- , line_northeast- , line_northwest- , line_southeast- , line_southwest-- , move_up- , move_down- , move_left- , move_right-- , move_up_left- , move_up_right- , move_down_left- , move_down_right-- , move_north- , move_south- , move_east- , move_west- , move_northeast- , move_northwest- , move_southeast- , move_southwest--- ) where--import Wumpus.Drawing.Paths.Base.AbsPath-import qualified Wumpus.Drawing.Paths.Base.AbsPath as A-import Wumpus.Drawing.Paths.Base.BuildCommon-import qualified Wumpus.Drawing.Paths.Base.RelPath as R---import Wumpus.Basic.Geometry ( half_pi ) -- package: wumpus-basic-import Wumpus.Basic.Kernel--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space-import Data.VectorSpace--import Control.Applicative hiding ( empty )-import Data.Monoid--import Prelude hiding ( log, cycle )------ State monad building is quite good - it ameliorates the problem--- of joining to the end point of an empty path...--data St u = St- { current_point :: Point2 u - , current_incline :: Radian- , cumulative_path :: AbsPath u- , active_path :: (Point2 u, AbsPath u)- , pen_dc_modifier :: DrawingContextF- }--type instance DUnit (St u) = u--type Log u = BuildLog (Graphic u)----- | Absolute Path builder monad.----newtype AbsBuild u a = AbsBuild { - getAbsBuild :: St u -> (a, St u, Log u) }--type instance DUnit (AbsBuild u a) = u-------------------------------------------------------------------------------------- instances----instance Functor (AbsBuild u) where- fmap f mf = AbsBuild $ \s0 -> let (a,s1,w1) = getAbsBuild mf s0- in (f a, s1, w1)---instance Applicative (AbsBuild u) where- pure a = AbsBuild $ \s0 -> (a,s0,mempty)- mf <*> ma = AbsBuild $ \s0 -> let (f,s1,w1) = getAbsBuild mf s0- (a,s2,w2) = getAbsBuild ma s1- in (f a,s2,w1 `mappend` w2)--instance Monad (AbsBuild u) where- return a = AbsBuild $ \s0 -> (a,s0,mempty)- m >>= k = AbsBuild $ \s0 -> let (a,s1,w1) = getAbsBuild m s0- (b,s2,w2) = (getAbsBuild . k) a s1- in (b, s2, w1 `mappend` w2)-------- | The initial state is needs the start point.----initSt :: Floating u => Point2 u -> St u-initSt pt = St { current_point = pt- , current_incline = 0- , cumulative_path = empty pt- , active_path = (pt, empty pt)- , pen_dc_modifier = id- }---- run - (path,graphic)--- exec - graphic--- eval - path---- | Note - runAbsBuild drops the monadic answer and returns the--- constructed path and a trace of the inserts and sub-paths.----runAbsBuild :: (Floating u, InterpretUnit u)- => Point2 u -> AbsBuild u a -> (AbsPath u, Graphic u)-runAbsBuild pt mf = post $ getAbsBuild mf (initSt pt)- where- post (_,st,log) = let sub_last = snd $ active_path st- cf = pen_dc_modifier st- log_last = logSubPath PATH_OPEN cf sub_last- log2 = log `mappend` log_last- empty_gfx = emptyLocGraphic `at` pt- (pen,ins) = extractTrace empty_gfx log2- in (cumulative_path st, pen `oplus` ins)----- | Run an 'AbsBuild' - return the Graphic formed by the pen --- trace and the insert trace, /forget/ the outline of the path.--- -execAbsBuild :: (Floating u, InterpretUnit u)- => Point2 u -> AbsBuild u a -> Graphic u-execAbsBuild pt mf = snd $ runAbsBuild pt mf------ | Run an 'AbsBuild' - return the outline of the path, /forget/--- the Graphic formed by the pen trace and the insert trace.--- -evalAbsBuild :: (Floating u, InterpretUnit u)- => Point2 u -> AbsBuild u a -> AbsPath u-evalAbsBuild pt mf = fst $ runAbsBuild pt mf----logSubPath :: InterpretUnit u - => PathEnd -> DrawingContextF -> AbsPath u -> Log u -logSubPath spe upd subp - | A.null subp = mempty- | otherwise = pen1 (toPrimPath subp >>= localize upd . drawF)- where- drawF = if spe == PATH_OPEN then openStroke else closedStroke----tellSubClosed :: InterpretUnit u - => DrawingContextF -> AbsPath u -> AbsBuild u ()-tellSubClosed upd subp = - AbsBuild $ \s0 -> ((), s0, logSubPath PATH_CLOSED upd subp)--tellSubOpen :: InterpretUnit u - => DrawingContextF -> AbsPath u -> AbsBuild u ()-tellSubOpen upd subp = - AbsBuild $ \s0 -> ((), s0, logSubPath PATH_OPEN upd subp)---tellInsert :: Graphic u -> AbsBuild u ()-tellInsert g1 = - AbsBuild $ \s0 -> ((),s0, insert1 g1)---sets_ :: (St u -> St u) -> AbsBuild u ()-sets_ f = AbsBuild $ \s0 -> ((), f s0, mempty)---gets :: (St u -> a) -> AbsBuild u a-gets f = AbsBuild $ \s0 -> (f s0, s0, mempty)--------------------------------------------------------------------------------------- operations--tip :: AbsBuild u (Point2 u)-tip = gets current_point---- | Helper - extend the path.----extendPath :: (Point2 u -> AbsPath u -> AbsPath u) -> Point2 u -> AbsBuild u ()-extendPath fn end_pt = sets_ upd- where- upd = (\s pt i j -> s { current_point = end_pt- , cumulative_path = fn pt i- , active_path = bimapR (fn pt) j })- <*> current_point <*> cumulative_path <*> active_path--absline :: Floating u => Point2 u -> AbsBuild u ()-absline p1 = extendPath (\_ acc -> acc `snocLineTo` p1) p1----abscurve :: (Floating u, Ord u, Tolerance u)- => Point2 u -> Point2 u -> Point2 u -> AbsBuild u ()-abscurve p1 p2 p3 = extendPath (\_ acc -> snocCurveTo acc p1 p2 p3) p3---- --- | 'absmove' is a pen up.----absmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => Point2 u -> AbsBuild u ()-absmove p1 = - gets active_path >>= \(_,ans) -> - gets pen_dc_modifier >>= \cf -> - tellSubOpen cf ans >> sets_ upd - where- upd = (\s i -> s { current_point = p1- , cumulative_path = i `snocLineTo` p1- , active_path = (p1, empty p1) }) - <*> cumulative_path---relline :: Floating u => Vec2 u -> AbsBuild u ()-relline v1 = gets current_point >>= \pt -> absline (pt .+^ v1)---relcurve :: (Floating u, Ord u, Tolerance u)- => Vec2 u -> Vec2 u -> Vec2 u -> AbsBuild u ()-relcurve v1 v2 v3 = - gets current_point >>= \pt -> - abscurve (pt .+^ v1) (pt .+^ v1 ^+^ v2) (pt .+^ v1 ^+^ v2 ^+^ v3)---relmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => Vec2 u -> AbsBuild u ()-relmove v1 = gets current_point >>= \pt -> absmove (pt .+^ v1)----rellineParallel :: Floating u => u -> AbsBuild u ()-rellineParallel u = gets current_incline >>= \ang -> relline (avec ang u)--rellinePerpendicular :: Floating u => u -> AbsBuild u ()-rellinePerpendicular u = - gets current_incline >>= \ang -> relline (avec (fn ang) u)- where- fn = circularModulo . (+ half_pi)--relmoveParallel :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-relmoveParallel u = gets current_incline >>= \ang -> relmove (avec ang u)---relmovePerpendicular :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-relmovePerpendicular u = - gets current_incline >>= \ang -> relmove (avec (fn ang) u)- where- fn = circularModulo . (+ half_pi)----ctrlcurve :: (Floating u, Ord u, Tolerance u) - => Radian -> Radian -> Point2 u -> AbsBuild u ()-ctrlcurve cin cout p1 = - extendPath (\p0 acc -> acc `append` controlCurve p0 cin cout p1) p1----insert :: Num u => LocGraphic u -> AbsBuild u ()-insert gf = gets current_point >>= \pt -> tellInsert (gf `at` pt)---penCtxUpdate :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => DrawingContextF -> AbsBuild u ()-penCtxUpdate cf = relmove (V2 0 0) >> sets_ upd- where- upd = (\s f -> s { pen_dc_modifier = cf . f })- <*> pen_dc_modifier------ Note - vamps should be a data type then we can have libraries --- of them.--vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => Vamp u -> AbsBuild u ()-vamp (Vamp vnext vstart upd relp path_end) = - gets current_point >>= \p0 -> - relmove vnext >> drawF upd (R.toAbsPath (p0 .+^ vstart) relp)- where- drawF = if path_end == PATH_OPEN then tellSubOpen else tellSubClosed--cycle :: (Floating u, InterpretUnit u) => AbsBuild u ()-cycle = - gets current_point >>= \pt -> - gets pen_dc_modifier >>= \cf ->- gets active_path >>= \(start,acc) -> - tellSubClosed cf (acc `snocLineTo` start) >> - sets_ (\s -> s { active_path = (pt, empty pt)})---setIncline :: Radian -> AbsBuild u ()-setIncline ang = sets_ upd- where- upd = (\s -> s { current_incline = ang })-------------------------------------------------------------------------------------- Derived operators---pen_colour :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => RGBi -> AbsBuild u ()-pen_colour rgb = penCtxUpdate (stroke_colour rgb)--pen_width :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => Double -> AbsBuild u ()-pen_width d = penCtxUpdate (set_line_width d)-----hline :: Floating u => u -> AbsBuild u ()-hline dx = relline (hvec dx)--vline :: Floating u => u -> AbsBuild u ()-vline dy = relline (vvec dy)--aline :: Floating u => u -> AbsBuild u ()-aline u = gets current_incline >>= \ang -> relline (avec ang u)--hmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-hmove dx = relmove (hvec dx)--vmove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-vmove dy = relmove (vvec dy)---amove :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-amove u = gets current_incline >>= \ang -> relmove (avec ang u)----line_up :: Floating u => u -> AbsBuild u ()-line_up u = relline (vvec u)--line_down :: Floating u => u -> AbsBuild u ()-line_down u = relline (vvec $ negate u)--line_left :: Floating u => u -> AbsBuild u ()-line_left u = relline (hvec $ negate u)- -line_right :: Floating u => u -> AbsBuild u ()-line_right u = relline (hvec u)---- | Diagonal lines --line_up_left :: Floating u => u -> AbsBuild u ()-line_up_left u = relline (vec (-u) u)--line_up_right :: Floating u => u -> AbsBuild u ()-line_up_right u = relline (vec u u)--line_down_left :: Floating u => u -> AbsBuild u ()-line_down_left u = relline (vec (-u) (-u))--line_down_right :: Floating u => u -> AbsBuild u ()-line_down_right u = relline (vec u (-u))----- Cardinal lines--line_north :: Floating u => u -> AbsBuild u ()-line_north = vline---line_south :: Floating u => u -> AbsBuild u ()-line_south = vline . negate--line_east :: Floating u => u -> AbsBuild u ()-line_east = hline--line_west :: Floating u => u -> AbsBuild u ()-line_west = hline . negate---line_northeast :: Floating u => u -> AbsBuild u ()-line_northeast = relline . avec (0.25 * pi)--line_northwest :: Floating u => u -> AbsBuild u ()-line_northwest = relline . avec (0.75 * pi)--line_southeast :: Floating u => u -> AbsBuild u ()-line_southeast = relline . avec (1.75 * pi)--line_southwest :: Floating u => u -> AbsBuild u ()-line_southwest = relline . avec (1.25 * pi)-----move_up :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_up u = relmove (vvec u)--move_down :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_down u = relmove (vvec $ negate u)--move_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_left u = relmove (hvec $ negate u)- -move_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_right u = relmove (hvec u)------ | Diagonal moves --move_up_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_up_left u = relmove (vec (-u) u)--move_up_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_up_right u = relmove (vec u u)--move_down_left :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_down_left u = relmove (vec (-u) (-u))--move_down_right :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_down_right u = relmove (vec u (-u))----- Cardinal moves--move_north :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_north = vmove---move_south :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_south = vmove . negate--move_east :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_east = hmove--move_west :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_west = hmove . negate---move_northeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_northeast = relmove . avec (0.25 * pi)--move_northwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_northwest = relmove . avec (0.75 * pi)--move_southeast :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_southeast = relmove . avec (1.75 * pi)--move_southwest :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => u -> AbsBuild u ()-move_southwest = relmove . avec (1.25 * pi)---
src/Wumpus/Drawing/Paths/Base/AbsPath.hs view
@@ -49,6 +49,8 @@ -- * Conversion , toPrimPath + , openAbsPath+ , closedAbsPath -- * Shortening , shortenPath@@ -79,6 +81,7 @@ , pathViewL , pathViewR + , optimizeLines , roundTrail , roundInterior@@ -269,7 +272,7 @@ -- Length is the length of the path as it is drawn, it is not a -- count of the number or path segments. ----- Length is cached so this operation is cheap - though this put +-- Length is cached so this operation is cheap - though this puts -- a tax on the build operations. -- length :: Num u => AbsPath u -> u@@ -400,8 +403,16 @@ +openAbsPath :: InterpretUnit u + => AbsPath u -> Image u (AbsPath u)+openAbsPath rp = replaceAns rp $+ zapQuery (toPrimPath rp) >>= dcOpenPath +closedAbsPath :: InterpretUnit u + => DrawStyle -> AbsPath u -> Image u (AbsPath u)+closedAbsPath sty rp = replaceAns rp $ + zapQuery (toPrimPath rp) >>= dcClosedPath sty -- | Turn a Path into an ordinary PrimPath.@@ -410,7 +421,7 @@ -- segment is the same point as the start point of the next -- segment. ---toPrimPath :: InterpretUnit u => AbsPath u -> Query PrimPath+toPrimPath :: InterpretUnit u => AbsPath u -> Query u PrimPath toPrimPath (AbsPath _ start segs _) = uconvertCtxF start >>= \dstart -> T.mapM uconvertCtxF segs >>= \dsegs ->@@ -689,6 +700,34 @@ +--------------------------------------------------------------------------------+++-- Path should be same length afterwards.++optimizeLines :: (Real u, Floating u, Ord u, Tolerance u) + => AbsPath u -> AbsPath u+optimizeLines (AbsPath _ sp0 segs _) = outer (zeroPath sp0) (viewl segs)+ where+ outer acc (AbsLineSeg _ p0 p1 :< se) = + inner acc (vdirection $ pvec p0 p1) p0 p1 (viewl se)++ outer acc (AbsCurveSeg _ _ p1 p2 p3 :< se) = + outer (snocCurveTo acc p1 p2 p3) (viewl se)++ outer acc EmptyL = acc++ inner acc d1 sp ep (AbsLineSeg _ p0 p1 :< se) =+ let d2 = vdirection $ pvec p0 p1 in + if (d1 == d2) + then inner acc d1 sp p1 (viewl se)+ else inner (acc `snocLineTo` ep) d2 ep p1 (viewl se)++ inner acc _ _ ep (AbsCurveSeg _ _ p1 p2 p3 :< se) = + let acc1 = snocCurveTo (snocLineTo acc ep) p1 p2 p3+ in outer acc1 (viewl se)++ inner acc _ _ ep EmptyL = acc `snocLineTo` ep -------------------------------------------------------------------------------- -- Round corners
− src/Wumpus/Drawing/Paths/Base/BuildCommon.hs
@@ -1,129 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.Base.BuildCommon--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Common data types for the monadic builders.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.Base.BuildCommon- ( -- BuildLog- , PathEnd(..)- , Vamp(..)- - , extractTrace- , addInsert- , addPen-- , insert1- , pen1- - ) where--import Wumpus.Drawing.Paths.Base.RelPath ( RelPath )--import Wumpus.Basic.Kernel -- package: wumpus-basic-import Wumpus.Basic.Utils.HList--import Wumpus.Core -- package: wumpus-core--import Data.Monoid---- | Monadic builders allow both inserts (patterned after TikZ)--- which are decorations along the path and sub paths that are --- stroked and possibly closed.----data BuildLog a = Log { insert_trace :: H a- , pen_trace :: H a- }- | NoLog--data PathEnd = PATH_CLOSED | PATH_OPEN- deriving (Eq,Show)---data Vamp u = Vamp - { vamp_move_span :: Vec2 u- , vamp_move_start :: Vec2 u- , vamp_dc_update :: DrawingContextF- , vamp_deco_path :: RelPath u- , vamp_path_end :: PathEnd- }--type instance DUnit (Vamp u) = u------------------------------------------------------------------------------------- instances--instance Monoid (BuildLog a) where- mempty = NoLog- NoLog `mappend` b = b- a `mappend` NoLog = a- Log li lp `mappend` Log ri rp = Log (li `appendH` ri) (lp `appendH` rp)------- | Extract the pen and insert drawings from a 'BuildLog'.------ Any sub-paths traced by the pen are drawn at the back in the --- Z-order.----extractTrace :: OPlus a => a -> BuildLog a -> (a,a)-extractTrace zero NoLog = (zero,zero)-extractTrace zero (Log ins pen) = (pent,inst)- where- pent = altconcat zero $ toListH $ pen - inst = altconcat zero $ toListH $ ins----- | Add an /insert/.------ This is a decoration drawn at the /current point/ during path--- building.--- -addInsert :: a -> BuildLog a -> BuildLog a-addInsert a NoLog = Log { insert_trace = wrapH a, pen_trace = emptyH }-addInsert a s@(Log { insert_trace=i }) = s { insert_trace = i `snocH` a }----- | Build a trace from an /insert/.------ This is a decoration drawn at the /current point/ during path--- building.--- -insert1 :: a -> BuildLog a-insert1 a = Log { insert_trace = wrapH a, pen_trace = emptyH }---- | Add a /pen/ drawing. ------ This is a stroked path sub-path formed prior to a @moveto@ --- instruction. Moveto is synonymous with /pen up/ - at a pen up--- and sub-path is drawn as a trace.--- -addPen :: a -> BuildLog a -> BuildLog a-addPen a NoLog = Log { insert_trace = wrapH a, pen_trace = emptyH }-addPen a s@(Log { pen_trace=i }) = s { pen_trace = i `snocH` a }----- | Build a trace from an /insert/.------ This is a decoration drawn at the /current point/ during path--- building.--- -pen1 :: a -> BuildLog a-pen1 a = Log { insert_trace = emptyH, pen_trace = wrapH a }---
+ src/Wumpus/Drawing/Paths/Base/PathBuilder.hs view
@@ -0,0 +1,576 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Base.PathBuilder+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Build relative paths monadically.+--+-- \*\* WARNING \*\* this module is an experiment, and may +-- change significantly or even be dropped from future revisions.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Base.PathBuilder+ ( ++ LocTraceM(..) -- re-export++ , PathSpec+ , PathSpecT++ , Vamp+ , PathTerm(..)+ , makeVamp++ , runPathSpec+ , execPathSpec+ , evalPathSpec++ , runPathSpecT+ , execPathSpecT+ , evalPathSpecT++ , execPivot+ , execPivotT+++ , PathOpM(..)+++ -- * Derived operators+ , pen_colour+ , pen_width++ , lines++ , hline+ , vline+ , aline++ + ) where++import Wumpus.Drawing.Basis.LocTrace+import Wumpus.Drawing.Paths.Base.RelPath+-- import qualified Wumpus.Drawing.Paths.Base.RelPath as R+++import Wumpus.Basic.Kernel -- package: wumpus-basic++import Wumpus.Core -- package: wumpus-core+++import Data.VectorSpace -- package: vector-space++import Control.Applicative+import Control.Monad+import Data.Monoid+import Prelude hiding ( null, cycle, lines )+++++++-- | The vector part of the @active_path@ is its start point. +-- This allows cycled paths.+--+data BuildSt u = BuildSt + { cumulative_tip :: Vec2 u+ , cumulative_path :: RelPath u+ , current_incline :: Radian+ , active_path :: ActivePath u+ , pen_trace :: LocGraphic u+ , ins_trace :: LocGraphic u+ , pen_dc_modifier :: DrawingContextF+ }++ -- TODO - is incline worthwhile?+++-- | The vector for @PEN_DOWN@ is the start-point not the current+-- tip. +-- +-- Startpoint is needed for cycling a path.+-- +data ActivePath u = PEN_UP+ | PEN_DOWN (Vec2 u) (RelPath u)+ ++++type instance DUnit (BuildSt u) = u+type instance DUnit (ActivePath u) = u+++newtype PathSpec u a = PathSpec { + getPathSpec :: BuildSt u -> (a, BuildSt u) }+++newtype PathSpecT u m a = PathSpecT { + getPathSpecT :: BuildSt u -> m (a, BuildSt u) } +++-- Note - splitting the state between BuildSt and the /path tip/+-- in LocTrace as actually detrimental to clarity of the code +-- below. It would make some sense to add the tip and the insert +-- trace to @BuildSt@ so everything is in one place.+++type instance MonUnit (PathSpec u a) = u+type instance MonUnit (PathSpecT u m a) = u+++-- | Vamps...+--+data Vamp u = Vamp + { vamp_move :: Vec2 u+ , vamp_path :: RelPath u+ , vamp_term :: PathTerm+ }+++type instance DUnit (Vamp u) = u+++data PathTerm = SUBPATH_OPEN | SUBPATH_CLOSED DrawStyle+ deriving (Eq,Show)+++makeVamp :: Vec2 u -> RelPath u -> PathTerm -> Vamp u+makeVamp v1 ph pe = Vamp { vamp_move = v1+ , vamp_path = ph+ , vamp_term = pe + }+++--------------------------------------------------------------------------------+-- instances+++-- Functor++instance Functor (PathSpec u) where+ fmap f mf = PathSpec $ \s0 -> let (a,s1) = getPathSpec mf s0 in (f a,s1)++instance Monad m => Functor (PathSpecT u m) where+ fmap f mf = PathSpecT $ \s0 -> + getPathSpecT mf s0 >>= \(a,s1) -> return (f a,s1)+++-- Applicative+ +instance Applicative (PathSpec u) where+ pure a = PathSpec $ \s0 -> (a, s0)+ mf <*> ma = PathSpec $ \s0 -> let (f,s1) = getPathSpec mf s0 + (a,s2) = getPathSpec ma s1+ in (f a, s2)++instance Monad m => Applicative (PathSpecT u m) where+ pure a = PathSpecT $ \s0 -> return (a, s0)+ mf <*> ma = PathSpecT $ \s0 -> + getPathSpecT mf s0 >>= \(f,s1) ->+ getPathSpecT ma s1 >>= \(a,s2) ->+ return (f a, s2)+++-- Monad++instance Monad (PathSpec u) where+ return a = PathSpec $ \s0 -> (a, s0)+ ma >>= k = PathSpec $ \s0 -> + let (a,s1) = getPathSpec ma s0 in (getPathSpec . k) a s1 ++instance Monad m => Monad (PathSpecT u m) where+ return a = PathSpecT $ \s0 -> return (a, s0)+ ma >>= k = PathSpecT $ \s0 -> + getPathSpecT ma s0 >>= \(a,s1) -> (getPathSpecT . k) a s1+ +++-- | Make the initial build state.+--+zeroBuildSt :: InterpretUnit u => BuildSt u+zeroBuildSt = BuildSt { cumulative_tip = V2 0 0+ , cumulative_path = mempty+ , current_incline = 0+ , active_path = PEN_UP+ , pen_trace = mempty+ , ins_trace = mempty+ , pen_dc_modifier = id+ }+++-- The /full/ versions throw away only parts of the @BuildSt@ .+--+++-- | Run a PathSpec - return a five-tuple.+--+-- > (ans, path, end_vector, pen_trace, insert_trace) +--+-- > ans - is the monadic answer, usually ().+--+-- > path - is the relative path formed by all movements during +-- > the build. This includes movement where the pen is _up_.+--+-- > end_vector - is the cumulative displacement from the start +-- > point.+--+-- > pen_trace - is ...+--+-- > insert_trace - +--+runPathSpec :: (Floating u, InterpretUnit u)+ => PathSpec u a + -> (a, RelPath u, Vec2 u, LocGraphic u, LocGraphic u)+runPathSpec mf = + post $ getPathSpec mf zeroBuildSt + where+ post (a,st) = let (ph,end,pen,ins) = postBuildSt st+ in (a,ph,end,pen,ins)++-- | /Close/ the BuildSt, extracting the values.+--+-- A partly drawn sub path will be added to the pen trace as an+-- open sub path.+--+postBuildSt :: InterpretUnit u + => BuildSt u -> (RelPath u, Vec2 u, LocGraphic u, LocGraphic u)+postBuildSt s0 = step (penUp SUBPATH_OPEN s0) + where+ step st = ( cumulative_path st+ , cumulative_tip st+ , pen_trace st+ , ins_trace st )+++++-- | Run an 'PathSpec' - return the LocGraphic formed by the pen +-- trace and the insert trace, /forget/ the outline of the path.+-- +-- Note - the insert trace is printed above the pen trace in the +-- z-order.+-- +execPathSpec :: (Floating u, InterpretUnit u)+ => PathSpec u a -> LocGraphic u+execPathSpec mf = post $ runPathSpec mf+ where+ post (_,_,_,g1,g2) = g1 `mappend` g2++++-- | Run an 'PathSpec' - return the outline of the path, /forget/+-- the the pen trace and the insert trace.+-- +evalPathSpec :: (Floating u, InterpretUnit u)+ => PathSpec u a -> RelPath u+evalPathSpec mf = post $ runPathSpec mf+ where+ post (_,ph,_,_,_) = ph+++-- | Transformer version of 'runPathSpec'+--+runPathSpecT :: (Monad m, Floating u, InterpretUnit u)+ => PathSpecT u m a + -> m (a, RelPath u, Vec2 u, LocGraphic u, LocGraphic u)+runPathSpecT mf = + liftM post $ getPathSpecT mf zeroBuildSt + where+ post (a,st) = let (ph,end,pen,ins) = postBuildSt st+ in (a,ph,end,pen,ins)+++-- | Transformer version of 'execPathSpec'+--+execPathSpecT :: (Monad m, Floating u, InterpretUnit u)+ => PathSpecT u m a -> m (LocGraphic u)+execPathSpecT mf = liftM post $ runPathSpecT mf+ where+ post (_,_,_,g1,g2) = g1 `mappend` g2+++-- | Transformer version of 'evalPathSpec'.+-- +evalPathSpecT :: (Monad m, Floating u, InterpretUnit u)+ => PathSpecT u m a -> m (RelPath u)+evalPathSpecT mf = liftM post $ runPathSpecT mf+ where+ post (_,ph,_,_,_) = ph+++++-- | Form a \"pivot path\" drawing from two path specifications.+-- The start point of the drawing is the pivot formed by joining+-- the paths.+--+execPivot :: (Floating u, InterpretUnit u)+ => PathSpec u a -> PathSpec u a -> LocGraphic u+execPivot ma mb = moveStart (negateV v) $ pen `mappend` ins+ where+ (v, _, _, pen, ins) = runPathSpec ( ma >> location >>= \ans -> + mb >> return ans )++-- | Transformer version of 'execPivot'.+-- +execPivotT :: (Floating u, InterpretUnit u, Monad m)+ => PathSpecT u m a -> PathSpecT u m a -> m (LocGraphic u)+execPivotT ma mb = + liftM post $ runPathSpecT ( ma >> location >>= \ans -> + mb >> return ans )+ where+ post (v, _, _, pen, ins) = moveStart (negateV v) $ pen `mappend` ins+ +++ +--------------------------------------------------------------------------------++-- BuildSt modifiers.++type BuildStF u = BuildSt u -> BuildSt u +++-- | Helper - extend the path with a line.+-- +-- This is an implicit PEN_DOWN if the active pen is UP.+--+extendPath :: Floating u + => Vec2 u -> BuildStF u+extendPath v1 = (\s v0 ph pa -> s { cumulative_tip = v0 ^+^ v1+ , cumulative_path = updP ph+ , active_path = updA v0 pa })+ <*> cumulative_tip <*> cumulative_path <*> active_path+ where+ updP ph = snocLineTo ph v1+ updA tip PEN_UP = PEN_DOWN tip (line1 v1)+ updA _ (PEN_DOWN v0 ph) = PEN_DOWN v0 (snocLineTo ph v1)+++++-- | Helper - extend the path with a curve.+--+-- This is an implicit PEN_DOWN if the active pen is UP.+-- +extendPathC :: (Floating u, Ord u, Tolerance u)+ => Vec2 u -> Vec2 u -> Vec2 u -> BuildStF u+extendPathC c1 c2 c3 = + (\s v0 ph pa -> s { cumulative_tip = v0 ^+^ c1 ^+^ c2 ^+^ c3+ , cumulative_path = updP ph+ , active_path = updA v0 pa })+ <*> cumulative_tip <*> cumulative_path <*> active_path+ where+ updP ph = snocCurveTo ph c1 c2 c3+ updA tip PEN_UP = PEN_DOWN tip (curve1 c1 c2 c2)+ updA _ (PEN_DOWN v0 ph) = PEN_DOWN v0 (snocCurveTo ph c1 c2 c3)+++-- | Helper - change the active_path to PEN_UP. +-- +-- This will implicitly log any partly drawn path.+--+penUp :: InterpretUnit u => PathTerm -> BuildStF u+penUp term = + (\s pt pa upd -> s { active_path = PEN_UP+ , pen_trace = pt `mappend` fn upd pa })+ <*> pen_trace <*> active_path <*> pen_dc_modifier+ where+ fn _ PEN_UP = mempty+ fn upd (PEN_DOWN v0 pa) = subPathDraw upd v0 pa term+++-- | Move the current tip.+--+-- This is an implicit PEN_UP if the active pen is DOWN.+-- +moveTip :: (Floating u, InterpretUnit u) + => Vec2 u -> BuildStF u+moveTip v1 = + (\s pa v0 cp -> let s1 = case pa of PEN_UP -> s; _ -> penUp SUBPATH_OPEN s+ in s1 { cumulative_tip = v0 ^+^ v1+ , cumulative_path = snocLineTo cp v1 })+ <*> active_path <*> cumulative_tip <*> cumulative_path+++-- | Cycle the current active path.+--+cycleAP :: (Floating u, InterpretUnit u) + => DrawStyle -> BuildStF u+cycleAP sty = + (\s pa vtip cp -> case pa of+ PEN_UP -> s+ PEN_DOWN v0 _ -> let s1 = penUp (SUBPATH_CLOSED sty) s+ mv = v0 ^-^ vtip+ in s1 { cumulative_tip = v0 + , cumulative_path = snocLineTo cp mv })+ <*> active_path <*> cumulative_tip <*> cumulative_path+ + ++-- | Change the drawing props of the current pen.+--+-- This is an implicit PEN_UP if the active pen is DOWN.+-- +changePen :: InterpretUnit u => DrawingContextF -> BuildStF u+changePen upd = + (\s pa df -> let s1 = case pa of PEN_UP -> s; _ -> penUp SUBPATH_OPEN s+ in s1 { pen_dc_modifier = (upd . df) })+ <*> active_path <*> pen_dc_modifier++++insertGf :: Num u => LocGraphic u -> BuildStF u+insertGf gf = + (\s ins v1 -> let g1 = moveStart v1 gf+ in s { ins_trace = ins `mappend` g1 })+ <*> ins_trace <*> cumulative_tip+ +++appendVamp :: (Floating u, InterpretUnit u) + => Vamp u -> BuildStF u+appendVamp (Vamp { vamp_path = vph, vamp_term = term, vamp_move = mv }) =+ next . penUp SUBPATH_OPEN+ where+ next = (\s v1 cp trc df -> let p1 = subPathDraw df v1 vph term+ in s { cumulative_tip = v1 ^+^ mv+ , cumulative_path = snocLineTo cp mv+ , pen_trace = trc `mappend` p1 })+ <*> cumulative_tip <*> cumulative_path + <*> pen_trace <*> pen_dc_modifier+ +++subPathDraw :: InterpretUnit u + => DrawingContextF -> Vec2 u -> RelPath u -> PathTerm + -> LocGraphic u+subPathDraw upd v0 subp term = promoteLoc $ \pt -> + zapQuery (toPrimPath (displace v0 pt) subp) >>= \pp -> localize upd (drawF pp)+ where+ drawF = case term of+ SUBPATH_OPEN -> dcOpenPath+ SUBPATH_CLOSED sty -> dcClosedPath sty++++++--------------------------------------------------------------------------------+-- LocTraceM instances++-- Note - path building does not support forking (LocForkTraceM). ++-- moveBy becomes a pen up++instance (Floating u, InterpretUnit u) => + LocTraceM (PathSpec u) where+ insertl a = PathSpec $ \s0 -> ((), insertGf a s0)+ location = PathSpec $ \s0 -> (cumulative_tip s0, s0)+ moveBy v = PathSpec $ \s0 -> ((), moveTip v s0)+++++instance (Monad m, Floating u, InterpretUnit u) => + LocTraceM (PathSpecT u m) where+ insertl a = PathSpecT $ \s0 -> return ((), insertGf a s0)+ location = PathSpecT $ \s0 -> return (cumulative_tip s0, s0)+ moveBy v = PathSpecT $ \s0 -> return ((), moveTip v s0)++++--------------------------------------------------------------------------------+-- +++-- | @updatePen@ will draw any in-progress path as an open-stroked+-- line before changing the pen properties.+--+class Monad m => PathOpM m where+ line :: u ~ MonUnit (m ()) => Vec2 u -> m ()+ curve :: u ~ MonUnit (m ()) => Vec2 u -> Vec2 u -> Vec2 u -> m ()+ updatePen :: DrawingContextF -> m ()+ cycleSubPath :: DrawStyle -> m ()+ vamp :: u ~ MonUnit (m ()) => Vamp u -> m ()++++instance (Floating u, Ord u, Tolerance u, InterpretUnit u) => + PathOpM (PathSpec u) where+ line v1 = PathSpec $ \s0 -> ((), extendPath v1 s0)+ curve v1 v2 v3 = PathSpec $ \s0 -> ((), extendPathC v1 v2 v3 s0)+ updatePen upd = PathSpec $ \s0 -> ((), changePen upd s0)+ cycleSubPath sty = PathSpec $ \s0 -> ((), cycleAP sty s0)+ vamp vp = PathSpec $ \s0 -> ((), appendVamp vp s0)++++instance (Monad m, Floating u, Ord u, Tolerance u, InterpretUnit u) => + PathOpM (PathSpecT u m) where+ line v1 = PathSpecT $ \s0 -> return ((), extendPath v1 s0)+ curve v1 v2 v3 = PathSpecT $ \s0 -> return ((), extendPathC v1 v2 v3 s0)+ updatePen upd = PathSpecT $ \s0 -> return ((), changePen upd s0)+ cycleSubPath sty = PathSpecT $ \s0 -> return ((), cycleAP sty s0)+ vamp vp = PathSpecT $ \s0 -> return ((), appendVamp vp s0)++++--------------------------------------------------------------------------------+-- operations++++{-++setIncline :: Radian -> PathSpec u ()+setIncline ang = sets_ upd+ where+ upd = (\s -> s { current_incline = ang })++-}++--------------------------------------------------------------------------------+-- Derived operators+++++pen_colour :: PathOpM m+ => RGBi -> m ()+pen_colour rgb = updatePen (stroke_colour rgb)++pen_width :: PathOpM m + => Double -> m ()+pen_width d = updatePen (set_line_width d)+++lines :: (PathOpM m, u ~ MonUnit (m ())) => [Vec2 u] -> m ()+lines = mapM_ line+++--+-- Note - these names are not consistent with Displacement in +-- Wumpus-Basic.+--++hline :: (PathOpM m, Num u, u ~ MonUnit (m ())) => u -> m ()+hline dx = line (hvec dx)++vline :: (PathOpM m, Num u, u ~ MonUnit (m ())) => u -> m ()+vline dy = line (vvec dy)+++aline :: (PathOpM m, Floating u, u ~ MonUnit (m ())) => Radian -> u -> m ()+aline ang d = line (avec ang d)
− src/Wumpus/Drawing/Paths/Base/RelBuilder.hs
@@ -1,520 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Drawing.Paths.Base.RelBuilder--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Build relative paths monadically.------ \*\* WARNING \*\* this module is an experiment, and may --- change significantly or even be dropped from future revisions.--- -----------------------------------------------------------------------------------module Wumpus.Drawing.Paths.Base.RelBuilder- ( -- RelBuild- , runRelBuild- , execRelBuild- , evalRelBuild- , execPivot--- , tip - , line- , curve- , move-- , insert- , vamp- , cycle-- , setIncline- , pivot-- -- * Derived operators- , pen_colour- , pen_width-- , hline- , vline- , aline-- , hmove- , vmove- , amove-- , line_up- , line_down- , line_left- , line_right-- , line_up_left- , line_up_right- , line_down_left- , line_down_right-- , line_north- , line_south- , line_east- , line_west- , line_northeast- , line_northwest- , line_southeast- , line_southwest-- , move_up- , move_down- , move_left- , move_right-- , move_up_left- , move_up_right- , move_down_left- , move_down_right-- , move_north- , move_south- , move_east- , move_west- , move_northeast- , move_northwest- , move_southeast- , move_southwest-- ) where---- import qualified Wumpus.Drawing.Paths.Base.AbsPath as A-import Wumpus.Drawing.Paths.Base.BuildCommon-import Wumpus.Drawing.Paths.Base.RelPath-import qualified Wumpus.Drawing.Paths.Base.RelPath as R---import Wumpus.Basic.Kernel -- package: wumpus-basic--import Wumpus.Core -- package: wumpus-core---import Data.VectorSpace -- package: vector-space--import Control.Applicative-import Data.Monoid-import Prelude hiding ( null, log, cycle )---data St u = St - { cumulative_disp :: Vec2 u- , cumulative_path :: RelPath u- , current_incline :: Radian- , active_path :: (Vec2 u, RelPath u)- , pen_dc_modifier :: DrawingContextF- , pivot_position :: Vec2 u- }--type instance DUnit (St u) = u--type Log u = BuildLog (LocGraphic u)---- --- Don\'t want to write pen trace along with the insert commands --- as some renderings (fill) should ignore the the pen trace.----- | Evaluation is two States - a vector for cummulative --- displacement and a cummulative path - plus one Writer - a trace --- of TikZ-like @insert@ commands.----data RelBuild u a = RelBuild { getRelBuild :: St u -> (a, St u, Log u) }--type instance DUnit (RelBuild u a) = u-------------------------------------------------------------------------------------- instances----instance Functor (RelBuild u) where- fmap f mf = RelBuild $ \s0 -> let (a, s1, w) = getRelBuild mf s0- in (f a, s1, w)---instance Applicative (RelBuild u) where- pure a = RelBuild $ \s0 -> (a, s0, mempty)- mf <*> ma = RelBuild $ \s0 -> - let (f,s1,w1) = getRelBuild mf s0- (a,s2,w2) = getRelBuild ma s1- in (f a, s2, w1 `mappend` w2)--instance Monad (RelBuild u) where- return a = RelBuild $ \s0 -> (a, s0, mempty)- ma >>= k = RelBuild $ \s0 -> - let (a,s1,w1) = getRelBuild ma s0- (b,s2,w2) = (getRelBuild . k) a s1- in (b, s2, w1 `mappend` w2)----zeroSt :: Num u => St u-zeroSt = St { cumulative_disp = V2 0 0 - , cumulative_path = mempty- , current_incline = 0- , active_path = (V2 0 0, mempty)- , pen_dc_modifier = id- , pivot_position = V2 0 0- }---runBuildMonad :: (Floating u, InterpretUnit u)- => RelBuild u a -> (a, St u, LocGraphic u)-runBuildMonad mf = post $ getRelBuild mf zeroSt- where- post (a,st,log) = (a, st, pen `oplus` ins)- where- (v1,sub_last) = active_path st- cf = pen_dc_modifier st- log_last = logSubPath PATH_OPEN cf v1 sub_last- log2 = log `mappend` log_last- (pen,ins) = extractTrace emptyLocGraphic log2----- | Note - runAbsBuild drops the monadic answer and returns the--- constructed path and a trace of the inserts and sub-paths.----runRelBuild :: (Floating u, InterpretUnit u)- => RelBuild u a -> (RelPath u, LocGraphic u)-runRelBuild mf = post $ runBuildMonad mf- where- post (_,st,gf) = (cumulative_path st,gf)----- | Run an 'RelBuild' - return the LocGraphic formed by the pen --- trace and the insert trace, /forget/ the outline of the path.--- -execRelBuild :: (Floating u, InterpretUnit u)- => RelBuild u a -> LocGraphic u-execRelBuild mf = snd $ runRelBuild mf------ | Run an 'RelBuild' - return the outline of the path, /forget/--- the LocGraphic formed by the pen trace and the insert trace.--- -evalRelBuild :: (Floating u, InterpretUnit u)- => RelBuild u a -> RelPath u-evalRelBuild mf = fst $ runRelBuild mf---execPivot :: (Floating u, InterpretUnit u)- => RelBuild u a -> LocGraphic u-execPivot mf = post $ runBuildMonad mf- where- post (_,st,gf) = let v1 = pivot_position st- in moveStart (displaceVec $ vreverse v1) gf-----logSubPath :: InterpretUnit u - => PathEnd -> DrawingContextF -> Vec2 u -> RelPath u -> Log u -logSubPath spe upd v1 subp - | R.null subp = mempty- | otherwise = pen1 gf- where- drawF = if spe == PATH_OPEN then openStroke else closedStroke- gf = promoteR1 $ \pt -> - toPrimPath (displaceVec v1 pt) subp >>= \pp -> - localize upd (drawF pp)---tellSubClosed :: InterpretUnit u - => DrawingContextF -> Vec2 u -> RelPath u -> RelBuild u ()-tellSubClosed upd v1 subp = - RelBuild $ \s0 -> ((), s0, logSubPath PATH_CLOSED upd v1 subp)--tellSubOpen :: InterpretUnit u - => DrawingContextF -> Vec2 u -> RelPath u -> RelBuild u ()-tellSubOpen upd v1 subp = - RelBuild $ \s0 -> ((), s0, logSubPath PATH_OPEN upd v1 subp)---tellInsert :: LocGraphic u -> RelBuild u ()-tellInsert g1 = - RelBuild $ \s0 -> ((),s0, insert1 g1)---sets_ :: (St u -> St u) -> RelBuild u ()-sets_ f = RelBuild $ \s0 -> ((), f s0, mempty)---gets :: (St u -> a) -> RelBuild u a-gets f = RelBuild $ \s0 -> (f s0, s0, mempty)--------------------------------------------------------------------------------------- operations--tip :: RelBuild u (Vec2 u)-tip = gets cumulative_disp------ | Helper - extend the path.----extendPath :: Num u - => (Vec2 u -> RelPath u -> RelPath u) -> Vec2 u -> RelBuild u ()-extendPath fn v1 = sets_ upd- where- upd = (\s v0 i j -> s { cumulative_disp = v0 ^+^ v1- , cumulative_path = fn v0 i- , active_path = bimapR (fn v0) j })- <*> cumulative_disp <*> cumulative_path <*> active_path------- Note - is the @r@ prefix of @rlineto@ redundant considering--- RelBuild can only support relative operations anyway.------ @lineto@ or probably better just @line@ would be shorter and--- the derivatives @hline@, @vline@ would inherit an obvious --- naming scheme.------line :: Floating u => Vec2 u -> RelBuild u ()-line v1 = extendPath (\_ acc -> snocLineTo acc v1) v1------curve :: Floating u => Vec2 u -> Vec2 u -> Vec2 u -> RelBuild u ()-curve v1 v2 v3 = extendPath (\_ acc -> snocCurveTo acc v1 v2 v3) v3------- | 'rmoveto' is a pen up.----move :: (Floating u, InterpretUnit u) => Vec2 u -> RelBuild u ()-move v1 = - gets active_path >>= \(v0,ans) -> - gets pen_dc_modifier >>= \cf -> - tellSubOpen cf v0 ans >> sets_ upd - where- upd = (\s v0 i -> s { cumulative_disp = v0 ^+^ v1- , cumulative_path = snocLineTo i v1- , active_path = (v0 ^+^ v1, mempty) })- <*> cumulative_disp <*> cumulative_path------insert :: Num u => LocGraphic u -> RelBuild u ()-insert gf = gets cumulative_disp >>= \v -> - tellInsert (moveStart (displaceVec v) gf)---penCtxUpdate :: (Floating u, InterpretUnit u) - => DrawingContextF -> RelBuild u ()-penCtxUpdate cf = move (V2 0 0) >> sets_ upd- where- upd = (\s f -> s { pen_dc_modifier = cf . f }) <*> pen_dc_modifier------- Note - vamps should be a data type then we can have libraries --- of them.--vamp :: (Floating u, Ord u, Tolerance u, InterpretUnit u) - => Vamp u -> RelBuild u ()-vamp (Vamp vnext vstart upd relp path_end) = - gets cumulative_disp >>= \v0 -> - gets pen_dc_modifier >>= \cf ->- move vnext >> drawF (upd . cf) (v0 ^+^ vstart) relp- where- drawF = if path_end == PATH_OPEN then tellSubOpen else tellSubClosed- --cycle :: (Floating u, InterpretUnit u) => RelBuild u ()-cycle = - gets cumulative_disp >>= \v1 -> - gets pen_dc_modifier >>= \cf ->- gets active_path >>= \(start,acc) -> - tellSubClosed cf start (snocLineTo acc start) >> - sets_ (\s -> s { active_path = (v1, mempty)})---setIncline :: Radian -> RelBuild u ()-setIncline ang = sets_ upd- where- upd = (\s -> s { current_incline = ang })---pivot :: RelBuild u ()-pivot = sets_ upd- where- upd = (\s i -> s { pivot_position = i }) <*> cumulative_disp-------------------------------------------------------------------------------------- Derived operators---pen_colour :: (Floating u, InterpretUnit u) - => RGBi -> RelBuild u ()-pen_colour rgb = penCtxUpdate (stroke_colour rgb)--pen_width :: (Floating u, InterpretUnit u) - => Double -> RelBuild u ()-pen_width d = penCtxUpdate (set_line_width d)----hline :: Floating u => u -> RelBuild u ()-hline dx = line (hvec dx)--vline :: Floating u => u -> RelBuild u ()-vline dy = line (vvec dy)--aline :: Floating u => Radian -> u -> RelBuild u ()-aline ang u = line (avec ang u)--hmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-hmove dx = move (hvec dx)--vmove :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-vmove dy = move (vvec dy)---amove :: (Floating u, InterpretUnit u) => Radian -> u -> RelBuild u ()-amove ang u = move (avec ang u)---line_up :: Floating u => u -> RelBuild u ()-line_up u = line (vvec u)--line_down :: Floating u => u -> RelBuild u ()-line_down u = line (vvec $ negate u)--line_left :: Floating u => u -> RelBuild u ()-line_left u = line (hvec $ negate u)- -line_right :: Floating u => u -> RelBuild u ()-line_right u = line (hvec u)---- | Diagonal lines --line_up_left :: Floating u => u -> RelBuild u ()-line_up_left u = line (vec (-u) u)--line_up_right :: Floating u => u -> RelBuild u ()-line_up_right u = line (vec u u)--line_down_left :: Floating u => u -> RelBuild u ()-line_down_left u = line (vec (-u) (-u))--line_down_right :: Floating u => u -> RelBuild u ()-line_down_right u = line (vec u (-u))----- Cardinal lines--line_north :: Floating u => u -> RelBuild u ()-line_north = vline---line_south :: Floating u => u -> RelBuild u ()-line_south = vline . negate--line_east :: Floating u => u -> RelBuild u ()-line_east = hline--line_west :: Floating u => u -> RelBuild u ()-line_west = hline . negate---line_northeast :: Floating u => u -> RelBuild u ()-line_northeast = line . avec (0.25 * pi)--line_northwest :: Floating u => u -> RelBuild u ()-line_northwest = line . avec (0.75 * pi)--line_southeast :: Floating u => u -> RelBuild u ()-line_southeast = line . avec (1.75 * pi)--line_southwest :: Floating u => u -> RelBuild u ()-line_southwest = line . avec (1.25 * pi)-----move_up :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_up u = move (vvec u)--move_down :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_down u = move (vvec $ negate u)--move_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_left u = move (hvec $ negate u)- -move_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_right u = move (hvec u)------ | Diagonal moves --move_up_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_up_left u = move (vec (-u) u)--move_up_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_up_right u = move (vec u u)--move_down_left :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_down_left u = move (vec (-u) (-u))--move_down_right :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_down_right u = move (vec u (-u))----- Cardinal moves--move_north :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_north = vmove---move_south :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_south = vmove . negate--move_east :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_east = hmove--move_west :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_west = hmove . negate---move_northeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_northeast = move . avec (0.25 * pi)--move_northwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_northwest = move . avec (0.75 * pi)--move_southeast :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_southeast = move . avec (1.75 * pi)--move_southwest :: (Floating u, InterpretUnit u) => u -> RelBuild u ()-move_southwest = move . avec (1.25 * pi)-
src/Wumpus/Drawing/Paths/Base/RelPath.hs view
@@ -41,7 +41,7 @@ -- * Queries , null-+ , length -- * Concat , append@@ -57,8 +57,10 @@ , toPrimPath , toAbsPath- , strokeRelPath + , openRelPath+ , closedRelPath+ ) where @@ -72,12 +74,15 @@ import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace +import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++ import qualified Data.Foldable as F import Data.Monoid import qualified Data.Traversable as T-import Prelude hiding ( null )+import Prelude hiding ( null, length ) @@ -88,7 +93,9 @@ -- Note this type is more limited than AbsPath, it does not -- support /introspective/ operations like @length@ or anchors. ---newtype RelPath u = RelPath { getRelPath :: JoinList (RelPathSeg u) }+data RelPath u = RelPath + { rel_path_len :: u+ , rel_path_segs :: JoinList (RelPathSeg u) } deriving (Eq,Show) type instance DUnit (RelPath u) = u@@ -98,8 +105,16 @@ -- No annotations... -- -data RelPathSeg u = RelLineSeg (Vec2 u)- | RelCurveSeg (Vec2 u) (Vec2 u) (Vec2 u)+data RelPathSeg u = RelLineSeg + { rel_line_len :: u + , rel_line_to :: Vec2 u+ }+ | RelCurveSeg + { rel_curve_len :: u+ , rel_curve_cp1 :: Vec2 u+ , rel_curve_cp2 :: Vec2 u+ , rel_curve_cp3 :: Vec2 u+ } deriving (Eq,Show) @@ -110,17 +125,17 @@ -------------------------------------------------------------------------------- instance Functor RelPath where- fmap f = RelPath . fmap (fmap f) . getRelPath+ fmap f (RelPath len xs) = RelPath (f len) (fmap (fmap f) xs) instance Functor RelPathSeg where- fmap f (RelLineSeg v1) = - RelLineSeg (fmap f v1)+ fmap f (RelLineSeg len v1) = + RelLineSeg (f len) (fmap f v1) - fmap f (RelCurveSeg v1 v2 v3) = - RelCurveSeg (fmap f v1) (fmap f v2) (fmap f v3)+ fmap f (RelCurveSeg len v1 v2 v3) = + RelCurveSeg (f len) (fmap f v1) (fmap f v2) (fmap f v3) -instance Monoid (RelPath u) where+instance Num u => Monoid (RelPath u) where mempty = empty mappend = append @@ -129,25 +144,61 @@ -- Construction +-- | Helper - construct a straight line segment.+-- +lineSegment :: Floating u => Vec2 u -> (u, RelPathSeg u)+lineSegment v1 = + (len, RelLineSeg { rel_line_len = len, rel_line_to = v1 })+ where+ len = vlength v1+++-- | Helper - construct a curve segment.+-- +curveSegment :: (Floating u, Ord u, Tolerance u) + => Vec2 u -> Vec2 u -> Vec2 u -> (u, RelPathSeg u)+curveSegment v1 v2 v3 = (len, cseg)+ where+ p0 = zeroPt+ p1 = p0 .+^ v1+ p2 = p1 .+^ v2+ p3 = p2 .+^ v3+ + len = bezierLength (BezierCurve p0 p1 p2 p3)+ cseg = RelCurveSeg { rel_curve_len = len+ , rel_curve_cp1 = v1+ , rel_curve_cp2 = v2+ , rel_curve_cp3 = v3+ } ++++ -- | An empty relative path is acceptible to Wumpus because -- it is always drawn as a LocGraphic. ---empty :: RelPath u -empty = RelPath mempty+empty :: Num u => RelPath u +empty = RelPath { rel_path_len = 0, rel_path_segs = mempty } -- | Create a relative path from a single straight line. ---line1 :: Vec2 u -> RelPath u-line1 = RelPath . JL.one . RelLineSeg+line1 :: Floating u => Vec2 u -> RelPath u+line1 v = RelPath len (JL.one $ RelLineSeg len v)+ where+ len = vlength v+ -- | Create a relative path from a single Bezier curve. ---curve1 :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u-curve1 v1 v2 v3 = RelPath $ JL.one $ RelCurveSeg v1 v2 v3+curve1 :: Floating u + => Vec2 u -> Vec2 u -> Vec2 u -> RelPath u+curve1 v1 v2 v3 = RelPath len (JL.one $ RelCurveSeg len v1 v2 v3)+ where+ len = vlength $ v1 ^+^ v2 ^+^ v3 -vertexPath :: [Vec2 u] -> RelPath u+vertexPath :: Floating u => [Vec2 u] -> RelPath u vertexPath [] = empty vertexPath (x:xs) = go (line1 x) xs where@@ -156,7 +207,7 @@ -curvedPath :: [Vec2 u] -> RelPath u+curvedPath :: Floating u => [Vec2 u] -> RelPath u curvedPath xs = case xs of (v1:v2:v3:vs) -> go (curve1 v1 v2 v3) vs _ -> empty@@ -173,8 +224,18 @@ -- Queries null :: RelPath u -> Bool-null = JL.null . getRelPath+null = JL.null . rel_path_segs +-- | Length of the Path.+--+-- Length is the length of the path as it is drawn, it is not a +-- count of the number or path segments.+--+-- Length is cached so this operation is cheap - though this puts +-- a tax on the build operations. +-- +length :: RelPath u -> u+length = rel_path_len --------------------------------------------------------------------------------@@ -184,23 +245,35 @@ -append :: RelPath u -> RelPath u -> RelPath u-append (RelPath se0) (RelPath se1) = RelPath $ se0 `join` se1+append :: Num u => RelPath u -> RelPath u -> RelPath u+append (RelPath la ssa) (RelPath lb ssb) = RelPath (la + lb) $ ssa `join` ssb -consLineTo :: Vec2 u -> RelPath u -> RelPath u -consLineTo v1 (RelPath se) = RelPath $ JL.cons (RelLineSeg v1) se+consLineTo :: Floating u + => Vec2 u -> RelPath u -> RelPath u +consLineTo v1 (RelPath len se) = RelPath (len + vl) $ JL.cons s se+ where+ (vl,s) = lineSegment v1 -snocLineTo :: RelPath u -> Vec2 u -> RelPath u-snocLineTo (RelPath se) v1 = RelPath $ JL.snoc se (RelLineSeg v1)+snocLineTo :: Floating u + => RelPath u -> Vec2 u -> RelPath u+snocLineTo (RelPath len se) v1 = RelPath (len + vl) $ JL.snoc se s+ where+ (vl,s) = lineSegment v1 -consCurveTo :: Vec2 u -> Vec2 u -> Vec2 u -> RelPath u -> RelPath u -consCurveTo v1 v2 v3 (RelPath se) = RelPath $ JL.cons (RelCurveSeg v1 v2 v3) se+consCurveTo :: (Floating u, Ord u, Tolerance u) + => Vec2 u -> Vec2 u -> Vec2 u -> RelPath u -> RelPath u +consCurveTo v1 v2 v3 (RelPath len se) = RelPath (len + cl) $ JL.cons s se+ where+ (cl,s) = curveSegment v1 v2 v3 -snocCurveTo :: RelPath u -> Vec2 u -> Vec2 u -> Vec2 u -> RelPath u-snocCurveTo (RelPath se) v1 v2 v3 = RelPath $ JL.snoc se (RelCurveSeg v1 v2 v3)+snocCurveTo :: (Floating u, Ord u, Tolerance u) + => RelPath u -> Vec2 u -> Vec2 u -> Vec2 u -> RelPath u+snocCurveTo (RelPath len se) v1 v2 v3 = RelPath (len + cl) $ JL.snoc se s+ where+ (cl,s) = curveSegment v1 v2 v3 @@ -209,45 +282,46 @@ -------------------------------------------------------------------------------- -- Conversion -fromPathAlgVertices :: Num u => PathAlg u -> (Vec2 u, RelPath u)+fromPathAlgVertices :: Floating u => PathAlg u -> (Vec2 u, RelPath u) fromPathAlgVertices = bimap fn vertexPath . runPathAlgVec where fn = maybe (V2 0 0) id -fromPathAlgCurves :: Num u => PathAlg u -> (Vec2 u, RelPath u)+fromPathAlgCurves :: Floating u => PathAlg u -> (Vec2 u, RelPath u) fromPathAlgCurves = bimap fn curvedPath . runPathAlgVec where fn = maybe (V2 0 0) id -toPrimPath :: InterpretUnit u => Point2 u -> RelPath u -> Query PrimPath-toPrimPath start (RelPath segs) = +toPrimPath :: InterpretUnit u => Point2 u -> RelPath u -> Query u PrimPath+toPrimPath start (RelPath _ segs) = uconvertCtxF start >>= \dstart -> T.mapM uconvertCtxF segs >>= \dsegs -> return $ relPrimPath dstart $ F.foldr fn [] dsegs where- fn (RelLineSeg v1) ac = relLineTo v1 : ac- fn (RelCurveSeg v1 v2 v3) ac = relCurveTo v1 v2 v3 : ac+ fn (RelLineSeg _ v1) ac = relLineTo v1 : ac+ fn (RelCurveSeg _ v1 v2 v3) ac = relCurveTo v1 v2 v3 : ac + toAbsPath :: (Floating u, Ord u, Tolerance u) => Point2 u -> RelPath u -> AbsPath u-toAbsPath start (RelPath segs) = step1 start $ viewl segs+toAbsPath start (RelPath _ segs) = step1 start $ viewl segs where step1 p0 EmptyL = Abs.empty p0 - step1 p0 (RelLineSeg v1 :< se) = + step1 p0 (RelLineSeg _ v1 :< se) = let (pth,end) = aline p0 v1 in step2 end pth (viewl se) - step1 p0 (RelCurveSeg v1 v2 v3 :< se) = + step1 p0 (RelCurveSeg _ v1 v2 v3 :< se) = let (pth,end) = acurve p0 v1 v2 v3 in step2 end pth (viewl se) step2 _ acc EmptyL = acc- step2 p0 acc (RelLineSeg v1 :< se) = + step2 p0 acc (RelLineSeg _ v1 :< se) = let (s1,end) = aline p0 v1 in step2 end (acc `Abs.append` s1) (viewl se) - step2 p0 acc (RelCurveSeg v1 v2 v3 :< se) = + step2 p0 acc (RelCurveSeg _ v1 v2 v3 :< se) = let (s1,end) = acurve p0 v1 v2 v3 in step2 end (acc `Abs.append` s1) (viewl se) @@ -262,8 +336,14 @@ -strokeRelPath :: InterpretUnit u => RelPath u -> LocGraphic u-strokeRelPath rp = - promoteR1 $ \start -> toPrimPath start rp >>= openStroke+openRelPath :: InterpretUnit u + => RelPath u -> LocImage u (RelPath u)+openRelPath rp = replaceAns rp $ + promoteLoc $ \start -> zapQuery (toPrimPath start rp) >>= dcOpenPath ++closedRelPath :: InterpretUnit u + => DrawStyle -> RelPath u -> LocImage u (RelPath u)+closedRelPath sty rp = replaceAns rp $ + promoteLoc $ \start -> zapQuery (toPrimPath start rp) >>= dcClosedPath sty
src/Wumpus/Drawing/Paths/Relative.hs view
@@ -17,11 +17,11 @@ module Wumpus.Drawing.Paths.Relative ( - module Wumpus.Drawing.Paths.Base.RelBuilder+ module Wumpus.Drawing.Paths.Base.PathBuilder , module Wumpus.Drawing.Paths.Base.RelPath ) where -import Wumpus.Drawing.Paths.Base.RelBuilder+import Wumpus.Drawing.Paths.Base.PathBuilder import Wumpus.Drawing.Paths.Base.RelPath
src/Wumpus/Drawing/Paths/Vamps.hs view
@@ -10,7 +10,7 @@ -- Stability : highly unstable -- Portability : GHC ----- Shim import module for the Absolute Path modules.+-- Library of vamps (currently small). -- -- --------------------------------------------------------------------------------@@ -18,22 +18,17 @@ module Wumpus.Drawing.Paths.Vamps ( - -- * Re-exported types- Vamp(..)- , PathEnd(..)-- , circleVamp+ squareWE ) where -import Wumpus.Drawing.Paths.Base.BuildCommon+import Wumpus.Drawing.Paths.Base.PathBuilder import Wumpus.Drawing.Paths.Base.RelPath -import Wumpus.Basic.Geometry -- package: wumpus-basic+import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core -import Data.VectorSpace -- package: vector-space -- TODO - library of useful / illustrative vamps (circle, square etc.)@@ -41,16 +36,11 @@ -circleVamp :: (Fractional u, Floating u) => Vec2 u -> Vamp u-circleVamp v0 = Vamp { vamp_move_span = v0- , vamp_move_start = half_v0 ^+^ v1- , vamp_dc_update = id- , vamp_deco_path = path- , vamp_path_end = PATH_CLOSED- }+squareWE :: (Fractional u, Floating u) => u -> Vamp u+squareWE diam = makeVamp (hvec diam) rpath (SUBPATH_CLOSED STROKE) where- radius = 0.5 * vlength v0- half_v0 = 0.5 *^ v0- (v1,path) = fromPathAlgCurves $ circlePathAlg radius+ hdiam = 0.5 * diam+ rpath = vertexPath [ vvec hdiam, hvec diam, vvec (-diam), hvec (-diam) ] - -- Note - circlePathAlg starts from east++-- Drawing a cirle is probably best done with 90deg arcs.
src/Wumpus/Drawing/Shapes/Base.hs view
@@ -82,21 +82,16 @@ , shape_decoration :: LocThetaGraphic u } +type instance DUnit (Shape t u) = u type DShape t = Shape t Double ---- Design note - shapes look like they should be constrained to --- InterpretUnit rather than CtxSize, this allows direct affine --- transformations.---- -------------------------------------------------------------------------------- shapeMap :: (t u -> t' u) -> Shape t u -> Shape t' u-shapeMap f = (\s sf -> s { shape_ans_fun = promoteR2 $ \pt ang -> - fmap f $ apply2R2 sf pt ang }) +shapeMap f = (\s sf -> s { shape_ans_fun = qpromoteLocTheta $ \pt ang -> + fmap f $ qapplyLocTheta sf pt ang }) <*> shape_ans_fun @@ -116,14 +111,14 @@ => LocThetaQuery u (t u) -> LocThetaQuery u (AbsPath u) -> Shape t u makeShape f g = Shape { shape_ans_fun = f , shape_path_fun = g- , shape_decoration = emptyLocThetaGraphic+ , shape_decoration = emptyLocThetaImage } strokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)-strokedShape = shapeToLoc closedStroke+strokedShape = shapeToLoc (dcClosedPath STROKE) -- | Note - this is simplistic double stroking - draw a background @@ -136,59 +131,59 @@ -- Probably Wumpus should calculate two paths instead. -- dblStrokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)-dblStrokedShape sh = decorateR1 back fore +dblStrokedShape sh = decorate back fore where- img = shapeToLoc closedStroke sh+ img = shapeToLoc (dcClosedPath STROKE) sh back = getLineWidth >>= \lw -> localize (set_line_width $ lw * 3.0) img- fore = pushR1 ignoreAns $ localize (stroke_colour white) img+ fore = ignoreAns $ localize (stroke_colour white) img filledShape :: InterpretUnit u => Shape t u -> LocImage u (t u)-filledShape = shapeToLoc filledPath+filledShape = shapeToLoc (dcClosedPath FILL) borderedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)-borderedShape = shapeToLoc borderedPath+borderedShape = shapeToLoc (dcClosedPath FILL_STROKE) shapeToLoc :: InterpretUnit u => (PrimPath -> Graphic u) -> Shape t u -> LocImage u (t u)-shapeToLoc drawF sh = promoteR1 $ \pt -> - apply2R2 (shape_ans_fun sh) pt 0 >>= \a -> - apply2R2 (shape_path_fun sh) pt 0 >>= \spath -> +shapeToLoc drawF sh = promoteLoc $ \pt -> + zapLocThetaQuery (shape_ans_fun sh) pt 0 >>= \a -> + zapLocThetaQuery (shape_path_fun sh) pt 0 >>= \spath -> let g2 = atIncline (shape_decoration sh) pt 0 - in intoImage (pure a) (decorateR0 g2 $ toPrimPath spath >>= drawF)+ in replaceAns a (decorate g2 $ zapQuery (toPrimPath spath) >>= drawF) rstrokedShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u)-rstrokedShape = shapeToLocTheta closedStroke+rstrokedShape = shapeToLocTheta (dcClosedPath STROKE) rfilledShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u)-rfilledShape = shapeToLocTheta filledPath+rfilledShape = shapeToLocTheta (dcClosedPath FILL) rborderedShape :: InterpretUnit u => Shape t u -> LocThetaImage u (t u)-rborderedShape = shapeToLocTheta borderedPath+rborderedShape = shapeToLocTheta (dcClosedPath FILL_STROKE) shapeToLocTheta :: InterpretUnit u => (PrimPath -> Graphic u) -> Shape t u -> LocThetaImage u (t u)-shapeToLocTheta drawF sh = promoteR2 $ \pt theta -> - apply2R2 (shape_ans_fun sh) pt theta >>= \a -> - apply2R2 (shape_path_fun sh) pt theta >>= \spath -> +shapeToLocTheta drawF sh = promoteLocTheta $ \pt theta -> + zapLocThetaQuery (shape_ans_fun sh) pt theta >>= \a -> + zapLocThetaQuery (shape_path_fun sh) pt theta >>= \spath -> let g2 = atIncline (shape_decoration sh) pt theta- in intoImage (pure a) (decorateR0 g2 $ toPrimPath spath >>= drawF)+ in replaceAns a $ decorate g2 (zapQuery (toPrimPath spath) >>= drawF) -- | Draw the shape path with round corners. -- roundCornerShapePath :: (Real u, Floating u, InterpretUnit u, Tolerance u)- => u -> [Point2 u] -> Query (AbsPath u)+ => u -> [Point2 u] -> Query u (AbsPath u) roundCornerShapePath sz xs = if sz `tEQ` 0 then return (vertexPath xs) else return (roundTrail sz xs) @@ -203,8 +198,8 @@ -- updatePathAngle :: (Radian -> Radian) -> Shape t u -> Shape t u updatePathAngle f = - (\s i -> s { shape_path_fun = promoteR2 $ \pt ang -> - apply2R2 i pt (mvTheta ang) })+ (\s fi -> s { shape_path_fun = qpromoteLocTheta $ \pt ang -> + qapplyLocTheta fi pt (mvTheta ang) }) <*> shape_path_fun where mvTheta = circularModulo . f
src/Wumpus/Drawing/Shapes/Circle.hs view
@@ -120,7 +120,7 @@ mkCircle :: InterpretUnit u => u -> LocThetaQuery u (Circle u)-mkCircle radius = promoteR2 $ \ctr theta -> +mkCircle radius = qpromoteLocTheta $ \ctr theta -> pure $ Circle { circ_ctm = makeShapeCTM ctr theta , circ_radius = radius }@@ -130,7 +130,7 @@ -- mkCirclePath :: (Floating u, Ord u, InterpretUnit u, Tolerance u) => u -> LocThetaQuery u (AbsPath u)-mkCirclePath radius = promoteR2 $ \ctr _ -> +mkCirclePath radius = qpromoteLocTheta $ \ctr _ -> pure $ curvePath $ bezierCircle radius ctr
src/Wumpus/Drawing/Shapes/Diamond.hs view
@@ -145,7 +145,7 @@ mkDiamond :: InterpretUnit u => u -> u -> LocThetaQuery u (Diamond u)-mkDiamond hw hh = promoteR2 $ \ctr theta -> +mkDiamond hw hh = qpromoteLocTheta $ \ctr theta -> pure $ Diamond { dia_ctm = makeShapeCTM ctr theta , dia_hw = hw , dia_hh = hh @@ -154,9 +154,9 @@ mkDiamondPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> u -> LocThetaQuery u (AbsPath u)-mkDiamondPath rnd hw hh = promoteR2 $ \ctr theta ->- let ps = map (rotateAbout theta ctr) $ diamondCoordPath hw hh ctr- in roundCornerShapePath rnd ps+mkDiamondPath rnd hw hh = qpromoteLocTheta $ \ctr theta -> + let ps = runPathAlgPoint ctr $ diamondPathAlg hw hh+ in roundCornerShapePath rnd $ map (rotateAbout theta ctr) ps
src/Wumpus/Drawing/Shapes/Ellipse.hs view
@@ -139,7 +139,7 @@ mkEllipse :: InterpretUnit u => u -> u -> LocThetaQuery u (Ellipse u)-mkEllipse rx ry = promoteR2 $ \ctr theta -> +mkEllipse rx ry = qpromoteLocTheta $ \ctr theta -> pure $ Ellipse { ell_ctm = makeShapeCTM ctr theta , ell_rx = rx , ell_ry = ry @@ -148,7 +148,7 @@ mkEllipsePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> LocThetaQuery u (AbsPath u)-mkEllipsePath rx ry = promoteR2 $ \pt theta -> +mkEllipsePath rx ry = qpromoteLocTheta $ \pt theta -> let xs = map (rotateAbout theta pt) $ bezierEllipse rx ry pt in return $ curvePath xs
src/Wumpus/Drawing/Shapes/Parallelogram.hs view
@@ -30,13 +30,12 @@ import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Geometry.Intersection-import Wumpus.Basic.Geometry.Paths+import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core +import Data.VectorSpace -- package: vector-space import Control.Applicative @@ -53,34 +52,17 @@ , pll_base_width :: !u , pll_height :: !u , pll_base_l_ang :: Radian- , pll_syn_props :: SyntheticProps u } type instance DUnit (Parallelogram u) = u --- | Note (center) is a line dropped from the center of the--- paralleogram.--- --- > base_minor is the (center) to left corner.--- > base_major is the (center) to right corner.----data SyntheticProps u = SyntheticProps- { pll_base_minor :: u- , pll_base_major :: u- } -type instance DUnit (SyntheticProps u) = u-- type DParallelogram = Parallelogram Double instance Functor Parallelogram where- fmap f (Parallelogram ctm bw h lang props) = - Parallelogram (fmap f ctm) (f bw) (f h) lang (fmap f props)--instance Functor SyntheticProps where- fmap f (SyntheticProps bmin bmaj) = SyntheticProps (f bmin) (f bmaj)+ fmap f (Parallelogram ctm bw h lang) = + Parallelogram (fmap f ctm) (f bw) (f h) lang @@ -112,32 +94,43 @@ -- * base_major -> Vec ) * parallelogram -> Point @ -- runDisplaceCenter :: (Real u, Floating u)- => (u -> u -> u -> u -> Vec2 u) -> Parallelogram u -> Anchor u+ => (u -> u -> Radian -> Vec2 u) -> Parallelogram u -> Anchor u runDisplaceCenter fn (Parallelogram { pll_ctm = ctm , pll_base_width = bw- , pll_height = h - , pll_syn_props = syn }) = - projectFromCtr (fn (0.5 * bw) (0.5 * h) - (pll_base_minor syn) (pll_base_major syn)) ctm+ , pll_height = h + , pll_base_l_ang = lang }) =+ projectFromCtr (fn (0.5 * bw) (0.5 * h) lang) ctm instance (Real u, Floating u) => CenterAnchor (Parallelogram u) where- center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0+ center = runDisplaceCenter $ \_ _ _ -> V2 0 0 ++-- | WARNING - WRONG...+ -- top anchors swap the base minor and major... --+ instance (Real u, Floating u) => TopCornerAnchor (Parallelogram u) where- topLeftCorner = runDisplaceCenter $ \_ hh _ bmaj -> V2 (-bmaj) hh- topRightCorner = runDisplaceCenter $ \_ hh bmin _ -> V2 bmin hh+ topLeftCorner = runDisplaceCenter $ \hw hh lang -> + let hypo = hh / (fromRadian $ sin lang) in hvec (-hw) ^+^ avec lang hypo + topRightCorner = runDisplaceCenter $ \hw hh lang ->+ let hypo = hh / (fromRadian $ sin lang) in hvec hw ^+^ avec lang hypo+ instance (Real u, Floating u) => BottomCornerAnchor (Parallelogram u) where- bottomLeftCorner = runDisplaceCenter $ \_ hh bmin _ -> V2 (-bmin) (-hh)- bottomRightCorner = runDisplaceCenter $ \_ hh _ bmaj -> V2 bmaj (-hh)+ bottomLeftCorner = runDisplaceCenter $ \hw hh lang ->+ let hypo = hh / (fromRadian $ sin lang) in hvec (-hw) ^+^ avec lang (-hypo) + bottomRightCorner = runDisplaceCenter $ \hw hh lang -> + let hypo = hh / (fromRadian $ sin lang) in hvec hw ^+^ avec lang (-hypo)+++ instance (Real u, Floating u) => SideMidpointAnchor (Parallelogram u) where sideMidpoint n a = step (n `mod` 4) @@ -151,10 +144,10 @@ instance (Real u, Floating u) => CardinalAnchor (Parallelogram u) where- north = runDisplaceCenter $ \_ hh _ _ -> V2 0 hh- south = runDisplaceCenter $ \_ hh _ _ -> V2 0 (-hh)- east = runDisplaceCenter $ \hw _ _ _ -> V2 hw 0- west = runDisplaceCenter $ \hw _ _ _ -> V2 (-hw) 0+ north = runDisplaceCenter $ \_ hh _ -> V2 0 hh+ south = runDisplaceCenter $ \_ hh _ -> V2 0 (-hh)+ east = runDisplaceCenter $ \hw _ _ -> V2 hw 0+ west = runDisplaceCenter $ \hw _ _ -> V2 (-hw) 0 instance (Real u, Floating u, InterpretUnit u, Tolerance u) => @@ -171,17 +164,23 @@ radialAnchor = pllRadialAnchor --- TODO - update this to a quadrant function...+-- | Note - it is not worth changing this to a quadrantAlg. --+-- There are pathological parallelograms that the current +-- QuadrantAlg code cannot handle, and a better abstraction is+-- needed (rather than better implementation of QuadrantAlg).+-- pllRadialAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) => Radian -> Parallelogram u -> Anchor u-pllRadialAnchor theta (Parallelogram { pll_ctm = ctm- , pll_height = h- , pll_syn_props = syn }) =+pllRadialAnchor theta (Parallelogram { pll_ctm = ctm+ , pll_base_width = bw+ , pll_height = h+ , pll_base_l_ang = lang }) = post $ findIntersect zeroPt theta $ polygonLineSegments ps where - ps = pllPoints (pll_base_minor syn) (pll_base_major syn) h- post = \ans -> case ans of + ps = runVertices4 zeroPt $ parallelogramVertices bw h lang++ post = \ans -> case ans of Nothing -> projectFromCtr (V2 0 0) ctm Just (P2 x y) -> projectFromCtr (V2 x y) ctm @@ -196,10 +195,7 @@ parallelogram :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Shape Parallelogram u parallelogram bw h lang =- let props = synthesizeProps bw h lang - in makeShape (mkParallelogram bw h lang props) - (mkParallelogramPath 0 (pll_base_minor props) - (pll_base_major props) h)+ makeShape (mkParallelogram bw h lang) (mkParallelogramPath 0 bw h lang) -- | 'zparallelogram' : @ base_width * height -> Parallelogram @@@ -216,64 +212,23 @@ mkParallelogram :: (Real u, Fractional u, InterpretUnit u, Tolerance u) - => u -> u -> Radian -> SyntheticProps u - -> LocThetaQuery u (Parallelogram u)-mkParallelogram bw h lang props = promoteR2 $ \ctr theta -> + => u -> u -> Radian -> LocThetaQuery u (Parallelogram u)+mkParallelogram bw h lang = qpromoteLocTheta $ \ctr theta -> pure $ Parallelogram { pll_ctm = makeShapeCTM ctr theta , pll_base_width = bw , pll_height = h , pll_base_l_ang = lang- , pll_syn_props = props } --- Note - expects ang value 0 < ang < 180, though does not check...--- -synthesizeProps :: Fractional u => u -> u -> Radian -> SyntheticProps u-synthesizeProps bw h lang - | lang == 0.5*pi = let hw = 0.5 * bw in SyntheticProps hw hw- | lang > 0.5*pi = less_ninety- | otherwise = grtr_ninety- where- less_ninety = let extw = h / (fromRadian $ tan lang)- half_rect_width = 0.5 * (bw + extw)- in SyntheticProps half_rect_width (half_rect_width - extw) - grtr_ninety = let extw = h / (fromRadian $ tan (pi-lang))- half_rect_width = 0.5 * (bw + extw)- in SyntheticProps (half_rect_width - extw) half_rect_width - -- mkParallelogramPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> u -> u -> LocThetaQuery u (AbsPath u)-mkParallelogramPath rnd bw_minor bw_major h = promoteR2 $ \ctr theta -> - let xs = pllPath bw_minor bw_major h ctr+ => u -> u -> u -> Radian -> LocThetaQuery u (AbsPath u)+mkParallelogramPath rnd bw h lang = qpromoteLocTheta $ \ctr theta -> + let xs = runVertices4 ctr $ parallelogramVertices bw h lang in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs ---pllPath :: (Real u, Floating u) - => u -> u -> u -> LocCoordPath u-pllPath bw_minor bw_major h (P2 x y) = [ bl, br, tr, tl ]- where- hh = 0.5 * h- bl = P2 (x - bw_minor) (y - hh)- br = P2 (x + bw_major) (y - hh)- tl = P2 (x - bw_major) (y + hh) -- topleft subtracts major- tr = P2 (x + bw_minor) (y + hh) -- topright adds minor---pllPoints :: (Real u, Floating u) - => u -> u -> u -> [Point2 u]-pllPoints bw_minor bw_major h = [ bl, br, tr, tl ]- where- hh = 0.5 * h - bl = P2 (-bw_minor) (-hh) - br = P2 bw_major (-hh)- tl = P2 (-bw_major) hh- tr = P2 bw_minor hh
src/Wumpus/Drawing/Shapes/Rectangle.hs view
@@ -30,8 +30,7 @@ import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Paths -- package: wumpus-basic-import Wumpus.Basic.Geometry.Quadrant+import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core@@ -153,7 +152,7 @@ mkRectangle :: InterpretUnit u => u -> u -> LocThetaQuery u (Rectangle u)-mkRectangle hw hh = promoteR2 $ \ctr theta -> +mkRectangle hw hh = qpromoteLocTheta $ \ctr theta -> pure $ Rectangle { rect_ctm = makeShapeCTM ctr theta , rect_hw = hw , rect_hh = hh@@ -162,9 +161,8 @@ mkRectPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> u -> LocThetaQuery u (AbsPath u)-mkRectPath rnd hw hh = promoteR2 $ \ctr theta -> - let btm_left = displace (-hw) (-hh) ctr- xs = rectangleCoordPath (2*hw) (2*hh) btm_left+mkRectPath rnd hw hh = qpromoteLocTheta $ \ctr theta -> + let xs = runVertices4 ctr $ rectangleVertices hw hh in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs
src/Wumpus/Drawing/Shapes/Semicircle.hs view
@@ -46,15 +46,15 @@ data Semicircle u = Semicircle { sc_ctm :: ShapeCTM u , sc_radius :: !u - , sc_syn_props :: SyntheticProps u } type instance DUnit (Semicircle u) = u --- | rect_width is the width of the (greater) enclosing rectangle.-data SyntheticProps u = SyntheticProps- { sc_ctr_minor :: u- , sc_ctr_major :: u+-- | Height minor and major.+--+data SyntheticProps u = SP+ { sc_hminor :: u+ , sc_hmajor :: u } type instance DUnit (SyntheticProps u) = u@@ -64,12 +64,26 @@ instance Functor Semicircle where- fmap f (Semicircle ctm r props) = Semicircle (fmap f ctm) (f r) (fmap f props)+ fmap f (Semicircle ctm r) = Semicircle (fmap f ctm) (f r) -instance Functor SyntheticProps where- fmap f (SyntheticProps cmin cmaj) = SyntheticProps (f cmin) (f cmaj) +-- | Use the formula:+--+-- > 4r+-- > ---+-- > 3pi+--+-- to get the yminor.+--+synthesizeProps :: Floating u => u -> SyntheticProps u+synthesizeProps radius = + SP { sc_hminor = hminor, sc_hmajor = hmajor }+ where+ hminor = (4 * radius) / (3 * pi)+ hmajor = radius - hminor++ -------------------------------------------------------------------------------- -- Affine trans @@ -100,10 +114,12 @@ runDisplaceCenter :: (Real u, Floating u) => (u -> u -> u -> Vec2 u) -> Semicircle u -> Anchor u runDisplaceCenter fn (Semicircle { sc_ctm = ctm- , sc_radius = radius- , sc_syn_props = syn }) = - projectFromCtr (fn radius (sc_ctr_minor syn) (sc_ctr_major syn)) ctm-+ , sc_radius = radius }) = + projectFromCtr (fn radius hminor hmajor) ctm+ where+ props = synthesizeProps radius + hminor = sc_hminor props+ hmajor = sc_hmajor props instance (Real u, Floating u) => CenterAnchor (Semicircle u) where@@ -151,22 +167,28 @@ -- helpers +-- | Semicircle does not fit into a QuadrantAlg easily.+--+-- So all the work has to be done here.+-- scRadialVec :: (Real u, Floating u, Ord u, Tolerance u) => Radian -> u -> u -> u -> Vec2 u-scRadialVec theta radius hminor _ = go theta+scRadialVec theta radius hminor _ = go (circularModulo theta) where (lang,rang) = baselineRange radius hminor (bctr, br, _, bl) = constructionPoints radius hminor- plane = makePlane zeroPt theta+ plane = inclinedLine zeroPt theta base_line = LineSegment bl br left_curve = mkCurve radius half_pi bctr right_curve = mkCurve radius 0 bctr post = maybe (V2 0 0) (\(P2 x y) -> V2 x y)- go a | lang <= a && a <= rang = post $ interLinesegLine base_line plane - | half_pi <= a && a < lang = post $ interCurveLine left_curve plane- | otherwise = post $ interCurveLine right_curve plane+ go a + | lang <= a && a <= rang = post $ interLinesegLine base_line plane + | half_pi <= a && a < lang = post $ interCurveLine left_curve plane+ | otherwise = post $ interCurveLine right_curve plane + mkCurve :: Floating u => u -> Radian -> Point2 u -> BezierCurve u mkCurve radius theta ctr = BezierCurve p0 p1 p2 p3 where@@ -186,7 +208,7 @@ bctr = P2 0 (-hminor) br = bctr .+^ hvec radius apx = bctr .+^ vvec radius- bl = bctr .-^ hvec radius+ bl = bctr .+^ hvec (-radius) @@ -212,26 +234,16 @@ => u -> Shape Semicircle u semicircle radius = let props = synthesizeProps radius- in makeShape (mkSemicircle radius props) - (mkSemicirclePath radius (sc_ctr_minor props))+ in makeShape (mkSemicircle radius) + (mkSemicirclePath radius (sc_hminor props)) -synthesizeProps :: Floating u => u -> SyntheticProps u-synthesizeProps radius = - SyntheticProps { sc_ctr_minor = cminor- , sc_ctr_major = cmajor- }- where- cminor = (4 * radius) / (3 * pi)- cmajor = radius - cminor - mkSemicircle :: InterpretUnit u- => u -> SyntheticProps u -> LocThetaQuery u (Semicircle u)-mkSemicircle radius props = promoteR2 $ \ctr theta -> - pure $ Semicircle { sc_ctm = makeShapeCTM ctr theta+ => u -> LocThetaQuery u (Semicircle u)+mkSemicircle radius = qpromoteLocTheta $ \ctr theta -> + pure $ Semicircle { sc_ctm = makeShapeCTM ctr theta , sc_radius = radius- , sc_syn_props = props } @@ -241,7 +253,7 @@ -- mkSemicirclePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> LocThetaQuery u (AbsPath u)-mkSemicirclePath radius cminor = promoteR2 $ \pt theta ->- let ctr = displacePerpendicular (-cminor) theta pt+mkSemicirclePath radius cminor = qpromoteLocTheta $ \pt theta ->+ let ctr = dispPerpendicular (-cminor) theta pt in pure $ curvePath $ bezierArcPoints pi radius theta ctr
src/Wumpus/Drawing/Shapes/Semiellipse.hs view
@@ -46,15 +46,14 @@ { se_ctm :: ShapeCTM u , se_rx :: !u , se_ry :: !u- , se_syn_props :: SyntheticProps u } type instance DUnit (Semiellipse u) = u --- | rect_width is the width of the (greater) enclosing rectangle.-data SyntheticProps u = SyntheticProps- { se_ry_minor :: u- , se_ry_major :: u++data SyntheticProps u = SP+ { se_hminor :: u+ , se_hmajor :: u } type instance DUnit (SyntheticProps u) = u@@ -62,12 +61,18 @@ type DSemiellipse = Semiellipse Double instance Functor Semiellipse where- fmap f (Semiellipse ctm rx ry props) = - Semiellipse (fmap f ctm) (f rx) (f ry) (fmap f props)+ fmap f (Semiellipse ctm rx ry) = Semiellipse (fmap f ctm) (f rx) (f ry) -instance Functor SyntheticProps where- fmap f (SyntheticProps rymin rymaj) = SyntheticProps (f rymin) (f rymaj) ++synthesizeProps :: Floating u => u -> SyntheticProps u+synthesizeProps ry = + SP { se_hminor = ry_minor, se_hmajor = ry_major }+ where+ ry_minor = (4 * ry) / (3 * pi)+ ry_major = ry - ry_minor++ -------------------------------------------------------------------------------- -- Affine trans @@ -101,9 +106,12 @@ => (u -> u -> u -> u -> Vec2 u) -> Semiellipse u -> Anchor u runDisplaceCenter fn (Semiellipse { se_ctm = ctm , se_rx = rx- , se_ry = ry- , se_syn_props = syn }) = - projectFromCtr (fn rx ry (se_ry_minor syn) (se_ry_major syn)) ctm+ , se_ry = ry }) = + projectFromCtr (fn rx ry hminor hmajor) ctm+ where+ props = synthesizeProps ry + hminor = se_hminor props+ hmajor = se_hmajor props @@ -149,7 +157,7 @@ where (lang,rang) = baselineRange rx hminor (bctr, br, _, bl) = constructionPoints rx ry hminor- plane = makePlane zeroPt theta+ plane = inclinedLine zeroPt theta base_line = LineSegment bl br (right_curve,left_curve) = bezierSemiellipse rx ry bctr post = maybe (V2 0 0) (\(P2 x y) -> V2 x y)@@ -200,34 +208,24 @@ => u -> u -> Shape Semiellipse u semiellipse rx ry = let props = synthesizeProps ry- in makeShape (mkSemiellipse rx ry props) - (mkSemiellipsePath rx ry (se_ry_minor props))+ in makeShape (mkSemiellipse rx ry) + (mkSemiellipsePath rx ry (se_hminor props)) -synthesizeProps :: Floating u => u -> SyntheticProps u-synthesizeProps ry = - SyntheticProps { se_ry_minor = ry_minor- , se_ry_major = ry_major- }- where- ry_minor = (4 * ry) / (3 * pi)- ry_major = ry - ry_minor --mkSemiellipse :: u -> u -> SyntheticProps u -> LocThetaQuery u (Semiellipse u)-mkSemiellipse rx ry props = promoteR2 $ \ctr theta -> +mkSemiellipse :: u -> u -> LocThetaQuery u (Semiellipse u)+mkSemiellipse rx ry = qpromoteLocTheta $ \ctr theta -> pure $ Semiellipse { se_ctm = makeShapeCTM ctr theta , se_rx = rx , se_ry = ry- , se_syn_props = props } mkSemiellipsePath :: (Real u, Floating u, Tolerance u) => u -> u -> u -> LocThetaQuery u (AbsPath u)-mkSemiellipsePath rx ry cminor = promoteR2 $ \pt theta ->- let ctr = displacePerpendicular (-cminor) theta pt+mkSemiellipsePath rx ry hminor = qpromoteLocTheta $ \pt theta ->+ let ctr = dispPerpendicular (-hminor) theta pt xs = bezierSemiellipsePoints rx ry ctr in return $ curvePath $ map (rotateAbout theta ctr) xs
src/Wumpus/Drawing/Shapes/Trapezium.hs view
@@ -11,10 +11,7 @@ -- Stability : highly unstable -- Portability : GHC ----- Trapezium.------ Note cardinal anchors correspond directly to the compass --- positions.+-- Isoceles Trapezium. -- -------------------------------------------------------------------------------- @@ -24,7 +21,6 @@ Trapezium , DTrapezium , trapezium- , ztrapezium ) where@@ -38,7 +34,6 @@ import Wumpus.Core -- package: wumpus-core -import Data.VectorSpace -- package: vector-space import Control.Applicative @@ -53,9 +48,8 @@ data Trapezium u = Trapezium { tz_ctm :: ShapeCTM u , tz_base_width :: !u+ , tz_top_width :: !u , tz_height :: !u- , tz_base_l_ang :: Radian- , tz_base_r_ang :: Radian } type instance DUnit (Trapezium u) = u@@ -63,8 +57,7 @@ type DTrapezium = Trapezium Double instance Functor Trapezium where- fmap f (Trapezium ctm bw h lang rang) = - Trapezium (fmap f ctm) (f bw) (f h) lang rang+ fmap f (Trapezium ctm bw tw h) = Trapezium (fmap f ctm) (f bw) (f tw) (f h) -------------------------------------------------------------------------------- -- Affine trans@@ -89,43 +82,40 @@ -------------------------------------------------------------------------------- -- Anchors ++ -- | 'runDisplaceCenter' : @ ( half_base_width --- * half_height--- * left_base_ang --- * right_base_ang -> Vec ) * trapzium -> Point @+-- * half_top_width+-- * half_height -> Vec ) * trapezium -> Point @ -- runDisplaceCenter :: (Real u, Floating u)- => (u -> u -> Radian -> Radian -> Vec2 u) + => (u -> u -> u -> Vec2 u) -> Trapezium u -> Anchor u runDisplaceCenter fn (Trapezium { tz_ctm = ctm , tz_base_width = bw- , tz_height = h- , tz_base_l_ang = lang- , tz_base_r_ang = rang }) =- projectFromCtr (fn (0.5 * bw) (0.5 * h) lang rang) ctm+ , tz_top_width = tw+ , tz_height = h }) =+ projectFromCtr (fn (0.5 * bw) (0.5 * tw) (0.5 * h)) ctm instance (Real u, Floating u) => CenterAnchor (Trapezium u) where- center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0+ center = runDisplaceCenter $ \_ _ _ -> V2 0 0 instance (Real u, Floating u) => BottomCornerAnchor (Trapezium u) where- bottomLeftCorner = runDisplaceCenter $ \hbw hh _ _ -> V2 (-hbw) (-hh)- bottomRightCorner = runDisplaceCenter $ \hbw hh _ _ -> V2 hbw (-hh)+ bottomLeftCorner = runDisplaceCenter $ \hbw _ hh -> V2 (-hbw) (-hh)+ bottomRightCorner = runDisplaceCenter $ \hbw _ hh -> V2 hbw (-hh) +++ instance (Real u, Floating u) => TopCornerAnchor (Trapezium u) where- topLeftCorner = runDisplaceCenter $ \hbw hh lang _ -> - let vbase = V2 (-hbw) (-hh)- vup = leftSideVec (2*hh) lang - in vbase ^+^ vup- topRightCorner = runDisplaceCenter $ \hbw hh _ rang ->- let vbase = V2 hbw (-hh)- vup = rightSideVec (2*hh) rang- in vbase ^+^ vup+ topLeftCorner = runDisplaceCenter $ \_ htw hh -> V2 (-htw) hh+ topRightCorner = runDisplaceCenter $ \_ htw hh -> V2 htw hh instance (Real u, Floating u, Tolerance u) => @@ -141,8 +131,8 @@ instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Trapezium u) where- north = runDisplaceCenter $ \_ hh _ _ -> V2 0 hh- south = runDisplaceCenter $ \_ hh _ _ -> V2 0 (-hh)+ north = runDisplaceCenter $ \_ _ hh -> V2 0 hh+ south = runDisplaceCenter $ \_ _ hh -> V2 0 (-hh) east = tzRadialAnchor 0 west = tzRadialAnchor pi @@ -160,18 +150,16 @@ RadialAnchor (Trapezium u) where radialAnchor = tzRadialAnchor --- TODO - update this to a quadrant function...---+-- tzRadialAnchor :: (Real u, Floating u, Tolerance u) => Radian -> Trapezium u -> Anchor u tzRadialAnchor theta (Trapezium { tz_ctm = ctm , tz_base_width = bw- , tz_height = h- , tz_base_l_ang = lang- , tz_base_r_ang = rang }) =+ , tz_top_width = tw+ , tz_height = h }) = post $ findIntersect zeroPt theta $ polygonLineSegments ps where - ps = tzPoints bw h lang rang+ ps = runVertices4 zeroPt $ isoscelesTrapeziumVertices bw tw h post = \ans -> case ans of Nothing -> projectFromCtr (V2 0 0) ctm Just (P2 x y) -> projectFromCtr (V2 x y) ctm@@ -186,98 +174,30 @@ -- -- trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> Radian -> Radian -> Shape Trapezium u-trapezium bw h lang rang = - makeShape (mkTrapezium bw h lang rang) (mkTrapeziumPath 0 bw h lang rang)+ => u -> u -> u -> Shape Trapezium u+trapezium bw tw h = + makeShape (mkTrapezium bw tw h) (mkTrapeziumPath 0 bw tw h) --- | 'ztrapezium' : @ base_width * height -> Trapezium @-------ztrapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> Shape Trapezium u-ztrapezium bw h = trapezium bw h ang ang- where- ang = d2r (60::Double) -------------------------------------------------------------------------------- mkTrapezium :: (Real u, Fractional u, InterpretUnit u) - => u -> u -> Radian -> Radian -> LocThetaQuery u (Trapezium u)-mkTrapezium bw h lang rang = promoteR2 $ \ctr theta -> + => u -> u -> u -> LocThetaQuery u (Trapezium u)+mkTrapezium bw tw h = qpromoteLocTheta $ \ctr theta -> pure $ Trapezium { tz_ctm = makeShapeCTM ctr theta , tz_base_width = bw+ , tz_top_width = tw , tz_height = h- , tz_base_l_ang = lang- , tz_base_r_ang = rang } mkTrapeziumPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> u -> Radian -> Radian - -> LocThetaQuery u (AbsPath u)-mkTrapeziumPath rnd bw h lang rang = promoteR2 $ \ctr theta -> - let xs = tzPath bw h lang rang ctr + => u -> u -> u -> u -> LocThetaQuery u (AbsPath u)+mkTrapeziumPath rnd bw tw h = qpromoteLocTheta $ \ctr theta -> + let xs = runVertices4 ctr $ isoscelesTrapeziumVertices bw tw h in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs --tzPath :: (Real u, Floating u) - => u -> u -> Radian -> Radian -> LocCoordPath u-tzPath bw h lang rang (P2 x y) = [ bl, br, tr, tl ]- where- half_base = 0.5 * bw- hh = 0.5 * h- br = P2 (x + half_base ) (y - hh)- bl = P2 (x - half_base ) (y - hh)- tr = displaceVec (rightSideVec h rang) br- tl = displaceVec (leftSideVec h lang) bl---tzPoints :: (Real u, Floating u) - => u -> u -> Radian -> Radian -> [Point2 u]-tzPoints bw h lang rang = [ bl, br, tr, tl ]- where- half_base = 0.5 * bw- hh = 0.5 * h- bl = P2 (-half_base) (-hh)- br = P2 half_base (-hh)- tr = displaceVec (rightSideVec h rang) br- tl = displaceVec (leftSideVec h lang) bl------ | Calculate the vector that produces the upper-left point given--- the lower-left point.------ Note - expects ang value 0 < ang < 180, though does not check...--- -leftSideVec :: Floating u => u -> Radian -> Vec2 u-leftSideVec h lang | lang < 0.5*pi = less_ninety- | lang == 0.5*pi = vvec h- | otherwise = grtr_ninety- where- less_ninety = let dist = h / (fromRadian $ sin lang) in avec lang dist- grtr_ninety = let theta = lang - (0.5*pi) - dist = h / (fromRadian $ cos theta) - in avec lang dist------- | Calculate the vector that produces the upper-right point given--- the lower-right point.------ Note - expects ang value 0 < ang < 180, though does not check...--- -rightSideVec :: Floating u => u -> Radian -> Vec2 u-rightSideVec h rang | rang < 0.5*pi = less_ninety- | rang == 0.5*pi = vvec h- | otherwise = grtr_ninety- where- less_ninety = let dist = h / (fromRadian $ sin rang) in avec (pi - rang) dist- grtr_ninety = let theta = rang - (0.5*pi) - dist = h / (fromRadian $ cos theta) - in avec (pi - rang) dist
src/Wumpus/Drawing/Shapes/Triangle.hs view
@@ -27,9 +27,7 @@ import Wumpus.Drawing.Paths.Absolute import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Geometry.Quadrant-import Wumpus.Basic.Geometry.Paths+import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core@@ -48,7 +46,6 @@ { tri_ctm :: ShapeCTM u , tri_base_width :: !u , tri_height :: !u- , tri_syn_props :: SyntheticProps u } type instance DUnit (Triangle u) = u@@ -60,19 +57,28 @@ , tri_apex_ang :: Radian } -type instance DUnit (SyntheticProps u) = u - type DTriangle = Triangle Double instance Functor Triangle where- fmap f (Triangle ctm bw h props) = - Triangle (fmap f ctm) (f bw) (f h) (fmap f props)+ fmap f (Triangle ctm bw h) = Triangle (fmap f ctm) (f bw) (f h) -instance Functor SyntheticProps where- fmap f (SyntheticProps hmin hmaj ang1 ang2) = - SyntheticProps (f hmin) (f hmaj) ang1 ang2 +synthesizeProps :: (Real u, Fractional u) => u -> u -> SyntheticProps u+synthesizeProps bw h = + SyntheticProps { tri_hmajor = hmajor+ , tri_hminor = hminor+ , tri_base_ang = base_ang+ , tri_apex_ang = apex_ang+ }+ where+ half_base = 0.5 * bw + hminor = h / 3+ hmajor = 2 * hminor + base_ang = atan $ toRadian (h / half_base)+ apex_ang = 2 * ((pi/4) - base_ang)++ -------------------------------------------------------------------------------- -- Affine trans @@ -103,13 +109,14 @@ runDisplaceCenter :: (Real u, Floating u) => (u -> u -> u -> Radian -> Vec2 u) -> Triangle u -> Anchor u runDisplaceCenter fn (Triangle { tri_ctm = ctm- , tri_base_width = bw- , tri_syn_props = syn }) = + , tri_base_width = bw + , tri_height = h }) = projectFromCtr (fn (0.5*bw) hminor hmajor base_ang) ctm where- hminor = tri_hminor syn - hmajor = tri_hmajor syn- base_ang = tri_base_ang syn+ props = synthesizeProps bw h+ hminor = tri_hminor props + hmajor = tri_hmajor props+ base_ang = tri_base_ang props @@ -187,52 +194,38 @@ let props = synthesizeProps bw h hminor = tri_hminor props hmajor = tri_hmajor props- in makeShape (mkTriangle bw h props) (mkTrianglePath 0 bw hminor hmajor)+ in makeShape (mkTriangle bw h) (mkTrianglePath 0 bw hminor hmajor) mkTriangle :: (Real u, Fractional u, InterpretUnit u) - => u -> u -> SyntheticProps u -> LocThetaQuery u (Triangle u)-mkTriangle bw h props = promoteR2 $ \ctrd theta -> + => u -> u -> LocThetaQuery u (Triangle u)+mkTriangle bw h = qpromoteLocTheta $ \ctrd theta -> pure $ Triangle { tri_ctm = makeShapeCTM ctrd theta , tri_base_width = bw , tri_height = h - , tri_syn_props = props } -synthesizeProps :: (Real u, Fractional u) => u -> u -> SyntheticProps u-synthesizeProps bw h = - SyntheticProps { tri_hmajor = hmajor- , tri_hminor = hminor- , tri_base_ang = base_ang- , tri_apex_ang = apex_ang- }- where- half_base = 0.5 * bw - hminor = h / 3- hmajor = 2 * hminor - base_ang = atan $ toRadian (h / half_base)- apex_ang = 2 * ((pi/4) - base_ang) mkTrianglePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> u -> u -> LocThetaQuery u (AbsPath u)-mkTrianglePath rnd bw hminor hmajor = promoteR2 $ \ctr theta -> - let xs = trianglePath bw hminor hmajor ctr+mkTrianglePath rnd bw hminor hmajor = qpromoteLocTheta $ \ctr theta -> + let xs = runVertices3 ctr $ trianglePath bw hminor hmajor in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs trianglePath :: (Real u, Floating u) - => u -> u -> u -> LocCoordPath u-trianglePath bw hminor hmajor (P2 x y) = [br, apx, bl]+ => u -> u -> u -> Vertices3 u+trianglePath bw hminor hmajor = (br, apx, bl) where half_base = 0.5 * bw- br = P2 (x + half_base ) (y - hminor)- apx = P2 x (y + hmajor)- bl = P2 (x - half_base ) (y - hminor)+ br = V2 half_base (-hminor)+ apx = V2 0 hmajor+ bl = V2 (-half_base) (-hminor)
src/Wumpus/Drawing/Text/Base/Common.hs view
@@ -46,19 +46,19 @@ posTextWithMargins :: (Fractional u, InterpretUnit u) - => PosObject u -> BoundedLocRectGraphic u-posTextWithMargins obj = + => PosObject u -> (RectAddress -> LocImage u (BoundingBox u))+posTextWithMargins obj = \raddr -> textMargin >>= \(xsep,ysep) -> let body = extendPosObject xsep xsep ysep ysep obj- in runPosObjectR2 body+ in runPosObject raddr body -- | Single line text, returning its advance vector. ---advtext :: InterpretUnit u => EscapedText -> AdvGraphic u+advtext :: InterpretUnit u => EscapedText -> LocImage u (Vec2 u) advtext esc = textVector esc >>= body where- body v = pushR1 (replaceAns v) $ escTextLine esc+ body v = replaceAns v $ dcEscapedlabel esc textVector :: (DrawingCtxM m, InterpretUnit u)
src/Wumpus/Drawing/Text/Base/DocTextZero.hs view
@@ -83,7 +83,7 @@ | Mono (WidthQuery u) [EscapedChar] | AElab (AElaborateF u) (Doc u) -type WidthQuery u = Query (AdvanceVec u)+type WidthQuery u = Query u (AdvanceVec u) type TextContextF u = TextContext u -> TextContext u @@ -94,7 +94,7 @@ -- | TextFrame is the result Graphic made from rendering multiple -- lines of DocText. ---type TextFrame u = BoundedLocRectGraphic u+type TextFrame u = RectAddress -> LocImage u (BoundingBox u) -- NOTE - should the API use @em@ for fill, padding etc.?@@ -248,10 +248,11 @@ render :: (Real u, Floating u, InterpretUnit u) - => FontFamily -> Doc u -> BoundedLocRectGraphic u -render ff doc = localize (set_font $ regularWeight ff) $+ => FontFamily -> Doc u -> (RectAddress -> LocImage u (BoundingBox u))+render ff doc = \raddr -> localize (set_font $ regularWeight ff) $ textlineSpace >>= \sep -> - posTextWithMargins $ runEvalM (initTextCtx sep ff) (interpret doc) + let po = runEvalM (initTextCtx sep ff) (interpret doc) + in posTextWithMargins po raddr data TextContext u = TextContext@@ -319,16 +320,17 @@ valignSpace va <$> lineSpace <*> interpret a <*> interpret b interpret (Fill va w a) = ppad va w <$> interpret a-interpret (DLocal upd a) = localizePO upd <$> interpret a+interpret (DLocal upd a) = localPosObject upd <$> interpret a interpret (TLocal upd a) = local upd (interpret a) interpret (Mono q1 xs) = interpMono q1 xs-interpret (AElab fn a) = aelaboratePO fn <$> interpret a+interpret (AElab fn a) = decoPosObject fn ANTERIOR <$> interpret a interpEmpty :: InterpretUnit u => EvalM u (PosObject u)-interpEmpty = return $ makePosObject (pure $ Orientation 0 0 0 0) emptyLocGraphic+interpEmpty = + return $ makePosObject (pure $ Orientation 0 0 0 0) emptyLocImage @@ -341,7 +343,7 @@ interpText :: (Fractional u, InterpretUnit u) => EscapedText -> EvalM u (PosObject u) interpText esc = interpretLeaf $- makePosObject (textOrientationZero esc) (escTextLine esc)+ makePosObject (textOrientationZero esc) (dcEscapedlabel esc) @@ -352,38 +354,40 @@ -- interpSpace :: InterpretUnit u => EvalM u (PosObject u)-interpSpace = return $ makePosObject qy1 emptyLocGraphic+interpSpace = return $ makePosObject qy1 emptyLocImage where qy1 = charOrientationZero $ CharEscInt $ ord ' ' ppad :: (Fractional u, Ord u) - => VAlign -> u -> PosObject u -> PosObject u-ppad VLeft = padLeftPO-ppad VCenter = padHorizontalPO-ppad VRight = padRightPO+ => VAlign -> u -> PosObject u -> PosObject u+ppad VLeft du = mapOrientation (padXMinor du)+ppad VCenter du = mapOrientation (padHEven $ 0.5 * du)+ppad VRight du = mapOrientation (padXMajor du) interpMono :: (Fractional u, InterpretUnit u)- => Query (AdvanceVec u) -> [EscapedChar] + => Query u (AdvanceVec u) -> [EscapedChar] -> EvalM u (PosObject u)-interpMono qy1 chs = interpretLeaf $- makeBindPosObject qy hkernOrientationZero hkernLine+interpMono avq chs = + interpretLeaf $ makePosObject (qChars >>= hkernOrientationZero) + (promoteLoc $ \pt -> + zapQuery qChars >>= \ks -> hkernLine ks `at` pt) where- qy = (\v1 -> monoSpace (advanceH v1) chs ) <$> qy1 -+ qChars = (\v1 -> monoSpace (advanceH v1) chs) <$> avq + interpretLeaf :: (Fractional u, InterpretUnit u) => PosObject u -> EvalM u (PosObject u) interpretLeaf po = - (\f1 f2 sty -> f1 $ f2 $ localizePO sty po) + (\f1 f2 sty -> f1 $ f2 $ localPosObject sty po) <$> (fmap (condE drawUnderline) $ asks text_underline) <*> (fmap (condE drawStrikethrough) $ asks text_strikethrough) <*> textstyle where- condE f b = if b then elaboratePO f else id+ condE f b = if b then decoPosObject f SUPERIOR else id textstyle :: EvalM u DrawingContextF textstyle = @@ -413,7 +417,7 @@ drawStrikethrough :: (Fractional u, InterpretUnit u) => Orientation u -> LocGraphic u drawStrikethrough (Orientation xmin xmaj _ ymaj) = - linestyle $ moveStart (displaceVec $ vec (-xmin) vpos) hline + linestyle $ moveStart (vec (-xmin) vpos) hline where vpos = 0.45 * ymaj hline = locStraightLine (hvec $ xmin + xmaj)@@ -423,7 +427,7 @@ drawUnderline :: (Fractional u, InterpretUnit u) => Orientation u -> LocGraphic u drawUnderline (Orientation xmin xmaj ymin _) = - linestyle $ moveStart (displaceVec $ vec (-xmin) vpos) hline + linestyle $ moveStart (vec (-xmin) vpos) hline where vpos = negate $ 0.45 * ymin hline = locStraightLine (hvec $ xmin + xmaj)@@ -447,7 +451,7 @@ hdy = 0.5 * dy in localize (fill_colour rgb) $ moveStart (mkVec hdx hdy) (mkRect hdx hdy) where- mkVec dx dy = displaceVec $ vec (negate $ xmin+dx) (negate $ ymin+dy)+ mkVec dx dy = vec (negate $ xmin+dx) (negate $ ymin+dy) mkRect dx dy = let w = dx + xmin + xmaj + dx h = dy + ymin + ymaj + dy- in filledRectangle w h+ in dcRectangle FILL w h
src/Wumpus/Drawing/Text/Base/Label.hs view
@@ -19,6 +19,7 @@ ( locImageLabel+ , label_center_of , label_left_of , label_right_of@@ -30,6 +31,14 @@ , label_atstart_of , label_atend_of + , centerRelative+ , right_of+ , left_of+ , above_right_of+ , below_right_of+ , above_left_of+ , below_left_of+ ) where @@ -40,16 +49,20 @@ import Wumpus.Core -- package: wumpus-core -+type BoundedLocRectGraphic u = RectAddress -> LocImage u (BoundingBox u) locImageLabel :: Floating u - => (a -> Anchor u) -> RectAddress - -> BoundedLocRectGraphic u -> LocImage u a -> LocImage u a-locImageLabel fn rpos lbl obj = promoteR1 $ \pt -> - elaborateR0 (obj `at` pt) (\a -> graphic_ $ atStartAddr lbl (fn a) rpos)+ => (a -> Anchor u) + -> RectAddress + -> (RectAddress -> LocImage u (BoundingBox u)) + -> LocImage u a + -> LocImage u a+locImageLabel fn rpos mklabel obj = promoteLoc $ \pt -> + elaborate (obj `at` pt) (\a -> ignoreAns $ mklabel rpos `at` fn a) + label_center_of :: (Floating u, CenterAnchor a, u ~ DUnit a) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a label_center_of = locImageLabel center CENTER@@ -83,7 +96,7 @@ -> Image u (AbsPath u) -> Image u (AbsPath u) connectorPathLabel fn rpos lbl img = - elaborateR0 img (\a -> graphic_ $ atStartAddr lbl (fn a) rpos)+ elaborate img (\a -> ignoreAns $ lbl rpos `at` (fn a)) label_midway_of :: (Real u, Floating u) @@ -105,6 +118,77 @@ -> BoundedLocRectGraphic u -> Image u (AbsPath u) -> Image u (AbsPath u) label_atend_of = connectorPathLabel atend_+++++-- | Absolute units.+-- +centerRelative :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => (Int,Int) -> a -> Query u (Anchor u)+centerRelative coord a = + snapmove coord >>= \v -> return $ displace v (center a)++-- TODO - These are really for Anchors.+--+-- Should the have a separate module or be rolled into the same+-- module as the classes?+--++-- | Value is 1 snap unit right.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query u (Anchor u)+right_of = centerRelative (1,0)++-- | Value is 1 snap move left.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query u (Anchor u)+left_of = centerRelative ((-1),0)++-- | Value is 1 snap move up, 1 snap move right.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +above_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query u (Anchor u)+above_right_of = centerRelative (1,1)++-- | Value is 1 snap move below, 1 snap move right.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +below_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query u (Anchor u)+below_right_of = centerRelative (1, (-1))++-- | Value is 1 snap move up, 1 snap move left.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +above_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query u (Anchor u)+above_left_of = centerRelative ((-1),1)++-- | Value is 1 snap move down, 1 snap move left.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +below_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query u (Anchor u)+below_left_of = centerRelative ((-1),(-1))+
src/Wumpus/Drawing/Text/Base/PosChar.hs view
@@ -47,7 +47,7 @@ -- -- While it may be adequate, it does need another prefix. ---type LocRectChar u = BoundedLocRectGraphic u+type LocRectChar u = RectAddress -> LocImage u (BoundingBox u) @@ -58,7 +58,7 @@ escCharLabel :: (Floating u, InterpretUnit u) => EscapedChar -> LocRectChar u-escCharLabel esc = runPosObjectR2 (makePosChar esc) +escCharLabel esc = \raddr -> runPosObject raddr (makePosChar esc) makePosChar :: InterpretUnit u @@ -67,7 +67,7 @@ escText1 :: InterpretUnit u => EscapedChar -> LocGraphic u-escText1 ch = escTextLine $ wrapEscChar ch+escText1 ch = dcEscapedlabel $ wrapEscChar ch
src/Wumpus/Drawing/Text/Base/RotTextZero.hs view
@@ -47,8 +47,8 @@ import Control.Applicative -type LocRectTextLine u = BoundedLocRectGraphic u-type LocTextLine u = BoundedLocGraphic u+type LocRectTextLine u = RectAddress -> LocImage u (BoundingBox u)+type LocTextLine u = LocImage u (BoundingBox u) type TextObject u = PosObject u @@ -63,16 +63,16 @@ bllTextline :: (Floating u, InterpretUnit u) => String -> LocTextLine u-bllTextline ss = startAddr (textline ss) BLL+bllTextline ss = textline ss BLL blcTextline :: (Floating u, InterpretUnit u) => String -> LocTextLine u-blcTextline ss = startAddr (textline ss) BLC+blcTextline ss = textline ss BLC ccTextline :: (Floating u, InterpretUnit u) => String -> LocTextLine u-ccTextline ss = startAddr (textline ss) CENTER+ccTextline ss = textline ss CENTER multiAlignLeft :: (Real u, Floating u, InterpretUnit u) @@ -93,9 +93,10 @@ renderMultiLine :: (Real u, Floating u, InterpretUnit u) => VAlign -> [TextObject u] -> LocRectTextLine u-renderMultiLine va docs = body >>= posTextWithMargins+renderMultiLine va docs = \raddr -> + body >>= \ans -> posTextWithMargins ans raddr where- body = (\dy -> alignColumnSep va dy $ reverse docs) <$> textlineSpace+ body = (\dy -> alignColumnSep va dy docs) <$> textlineSpace makeTextObject :: InterpretUnit u => String -> TextObject u@@ -104,7 +105,7 @@ makeEscTextObject :: InterpretUnit u => EscapedText -> TextObject u makeEscTextObject esc = - makePosObject (textOrientationZero esc) (escTextLine esc)+ makePosObject (textOrientationZero esc) (dcEscapedlabel esc) -- Note inclided text will (probably) have to construct with the @@ -115,29 +116,32 @@ => Radian -> String -> LocRectTextLine u rtextline ang ss = rescTextline ang (escapeString ss) --- Is rotated text better with no margin?+ rescTextline :: (Real u, Floating u, Ord u, InterpretUnit u) => Radian -> EscapedText -> LocRectTextLine u-rescTextline ang esc = runPosObjectR2 $ makePosObject ortt body+rescTextline ang esc = \raddr -> runPosObject raddr $ makePosObject ortt body where ortt = fmap (rotOrientation ang) $ textOrientationZero esc- body = incline (rescTextLine esc) ang+ body = incline (dcREscapedlabel esc) ang ++ -- | Rotate an Orientation about its locus. -- rotOrientation :: (Real u, Floating u, Ord u) => Radian -> Orientation u -> Orientation u-rotOrientation ang (Orientation xmin xmaj ymin ymaj) = +rotOrientation ang (Orientation { or_x_minor = xmin+ , or_x_major = xmaj+ , or_y_minor = ymin+ , or_y_major = ymaj }) = orthoOrientation bl br tl tr where- bl = rotateCorner ang $ P2 (-xmin) (-ymin)- br = rotateCorner ang $ P2 xmaj (-ymaj)- tr = rotateCorner ang $ P2 xmaj ymaj- tl = rotateCorner ang $ P2 (-xmin) ymaj+ bl = rotateAbout ang zeroPt $ P2 (-xmin) (-ymin)+ br = rotateAbout ang zeroPt $ P2 xmaj (-ymin)+ tr = rotateAbout ang zeroPt $ P2 xmaj ymaj+ tl = rotateAbout ang zeroPt $ P2 (-xmin) ymaj --- | This is not necessarily correct...--- orthoOrientation :: (Num u, Ord u) => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Orientation u@@ -149,227 +153,9 @@ } -rotateCorner :: (Real u, Floating u) => Radian -> Point2 u -> Point2 u-rotateCorner ang pt = displaceVec v2 zeroPt- where- v1 = pvec zeroPt pt - theta = vdirection v1- hyp = vlength v1- v2 = avec (ang+theta) hyp- min4 :: Ord u => u -> u -> u -> u -> u min4 a b c d = min (min a b) (min c d) max4 :: Ord u => u -> u -> u -> u -> u max4 a b c d = max (max a b) (max c d) --{---type RotText u = PosThetaImage BoundingBox u-------------------------- | One line of multiline text----data OnelineText u = OnelineText - { text_content :: EscapedText- , oneline_adv :: AdvanceVec u- }----type OnelineGraphicF u = u -> OnelineText u -> LocThetaGraphic u-----rotTextStart :: PosThetaImage u a -> RectPosition -> Radian -> LocImage u a-rotTextStart = startPosRot---textbox :: (Real u, Floating u, InterpretUnit u) - => String -> PosImage BoundingBox u-textbox ss = multiAlignCenter ss `ptRot` 0----rtextbox :: (Real u, Floating u, InterpretUnit u) - => String -> PosThetaImage BoundingBox u-rtextbox ss = multiAlignCenter ss----- multi line text allows rotation --multiAlignLeft :: (Real u, Floating u, InterpretUnit u) - => String -> PosThetaImage BoundingBox u-multiAlignLeft ss = - drawMultiline onelineALeft (map escapeString $ lines ss)--multiAlignCenter :: (Real u, Floating u, InterpretUnit u) - => String -> PosThetaImage BoundingBox u-multiAlignCenter ss = - drawMultiline onelineACenter (map escapeString $ lines ss)--multiAlignRight :: (Real u, Floating u, InterpretUnit u) - => String -> RotText u-multiAlignRight ss = - drawMultiline onelineARight (map escapeString $ lines ss)---textAlignLeft :: (Real u, Floating u, InterpretUnit u) - => String -> LocImage BoundingBox u-textAlignLeft ss = startPosRot (multiAlignLeft ss) CENTER 0--textAlignCenter :: (Real u, Floating u, InterpretUnit u) - => String -> LocImage BoundingBox u-textAlignCenter ss = startPosRot (multiAlignCenter ss) CENTER 0 --textAlignRight :: (Real u, Floating u, InterpretUnit u) - => String -> LocImage BoundingBox u-textAlignRight ss = startPosRot (multiAlignRight ss) CENTER 0------drawMultiline :: (Real u, Floating u, InterpretUnit u) - => OnelineGraphicF u -> [EscapedText] - -> PosThetaImage BoundingBox u-drawMultiline _ [] = lift1R3 emptyBoundedLocGraphic-drawMultiline drawF xs = promoteR3 $ \start rpos ang ->- linesToInterims xs >>= \(max_w, ones) ->- borderedRotTextPos ang line_count max_w >>= \opos -> - let gf = multilineGraphic drawF max_w ang ones- bbf = orthoBB max_w line_count ang- img = intoLocImage bbf gf- posG = makePosImage opos img- in atStartPos posG start rpos - where- line_count = length xs---multilineGraphic :: (Floating u, InterpretUnit u)- => OnelineGraphicF u - -> u - -> Radian - -> [OnelineText u]- -> LocGraphic u-multilineGraphic drawF max_w ang xs = - lift0R1 (centerSpineDisps (length xs) ang) >>= \(disp_top, disp_next) ->- let gs = map (\a -> rot (drawF max_w a) ang) xs- in ignoreAns $ moveStart disp_top $ chainDisplace disp_next gs---- | Draw left-aligned text. Effictively this is:------ > Leftwards for the half the max vector--- >--- > Down to the baseline from the center.----onelineALeft :: (Real u, Floating u, InterpretUnit u) - => OnelineGraphicF u -onelineALeft width otext = promoteR2 $ \ctr theta -> - centerToBaseline >>= \down -> - let pt = move down theta ctr - in atRot (rescTextLine $ text_content otext) pt theta- where- vec1 = hvec $ negate $ 0.5 * width- move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang----- | Draw center-aligned text. Effictively this is:------ > Leftwards for the half the width vector--- >--- > Down to the baseline from the center.------ The max_adv is ignored.----onelineACenter :: (Real u, Floating u, InterpretUnit u) - => OnelineGraphicF u-onelineACenter _ otext = promoteR2 $ \ctr theta -> - centerToBaseline >>= \down -> - let pt = move down theta ctr - in atRot (rescTextLine $ text_content otext) pt theta- where- vec1 = negateV $ 0.5 *^ oneline_adv otext- move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang----- | Draw right-aligned text. Effictively this is:------ > Rightwards for the half the max width--- >--- > Leftwards for the width vector--- >--- > Down to the baseline from the center.----onelineARight :: (Real u, Floating u, InterpretUnit u) - => OnelineGraphicF u-onelineARight max_w otext = promoteR2 $ \ctr theta -> - centerToBaseline >>= \down -> - let pt = move down theta ctr - in atRot (rescTextLine $ text_content otext) pt theta- where- vec1 = hvec (0.5 * max_w) ^-^ oneline_adv otext- move down = \ang -> thetaSouthwards down ang . displaceOrtho vec1 ang-------- Note - for multiline text, the bounding box (of one line) is --- always the same size regardless of the alignment of the textlines.------- | Its easy to find top-left and top-right, then bottom-left is --- the vector from top-right to center added to the center. --- Likewise bottom-right is the vector from top-left-to center --- added to the center. Visually this construction forms a bow of --- two triangles meeting at the (rectangle) center.--orthoBB :: (Real u, Floating u, InterpretUnit u) - => u -> Int -> Radian -> LocQuery u (BoundingBox u)-orthoBB w line_count theta = promoteR1 $ \ctr ->- fmap (0.5*) verticalSpan >>= \hh1 ->- textMargin >>= \(xsep,ysep) -> - centerSpineDisps line_count theta >>= \(disp_top,_) ->- let top_ctr = disp_top ctr- hw = 0.5 * w- tr = displaceOrtho (V2 (hw+xsep) (hh1+ysep)) theta top_ctr- tl = displaceOrtho (V2 (negate $ hw+xsep) (hh1+ysep)) theta top_ctr- bl = ctr .+^ pvec tr ctr - br = ctr .+^ pvec tl ctr- in return $ traceBoundary [tr,tl,bl,br]------ Note - displaceOrtho would be more convenient if it wasn\'t a --- vector.---------------------------------------------------------------------------------------- This isn't worth the complexity to get down to one traversal...---- | Turn the input list of lines of 'EscapedText' into --- 'OnelineText' and return the result list twinned with the --- largest width.----linesToInterims :: (InterpretUnit u, Ord u) - => [EscapedText] -> Query (u, [OnelineText u])-linesToInterims = fmap post . mapM onelineEscText- where- post xs = let vmax = foldr fn 0 xs in (vmax,xs)- fn (OnelineText _ av) wmax = max (advanceH av) wmax-----onelineEscText :: InterpretUnit u => EscapedText -> Query (OnelineText u)-onelineEscText esc = fmap (OnelineText esc) $ textVector esc----}
src/Wumpus/Drawing/VersionNumber.hs view
@@ -23,7 +23,7 @@ -- | Version number ----- > (0,3,0)+-- > (0,4,0) -- wumpus_drawing_version :: (Int,Int,Int)-wumpus_drawing_version = (0,3,0)+wumpus_drawing_version = (0,4,0)
wumpus-drawing.cabal view
@@ -1,5 +1,5 @@ name: wumpus-drawing-version: 0.3.0+version: 0.4.0 license: BSD3 license-file: LICENSE copyright: Stephen Tetley <stephen.tetley@gmail.com>@@ -38,47 +38,20 @@ . Changelog: .- v0.2.0 to v0.3.0:+ v0.3.0 to v0.4.0: .- * Moved Turtle and Grids into the @Wumpus.Drawing.Extras@- name-space. Modules here are considered sketches.+ * Simplified Trapezium shape so it only produces isosceles+ Trapeziums. .- * Re-implemented arrowheads and connectors.+ * Added Basis modules. These are \"mid-level\" modules similar + to ones in @Wumpus.Basic.Kernel.Objects@, however they are + considered less general so there are put here where they can + be imported individually (and so not pollute the namespace). .- * Re-implemented monadic path construction. This is now - essentially \"turtle drawing\" with a path trace.+ * Removed the Turtle modules. The new @LocTrace@ and @RefTrace@ + modules supercede the Turtle modules. .- * Removed chains - a simplified implementation is now - provided by Wumpus-Basic. .- * Re-implemented and expanded Text. - .- v0.1.0 to v0.2.0:- .- * Added new Shapes.- .- * Move Geometry modules to Wumpus-Basic.- .- * Re-implemented Chains.- .- * Re-implemented LR-Text. Added CatText.- .- v0.1.0:- .- * Initial release - this is a split from @Wumpus-Basic@ making - the (very prototypical - read sub-alpha, unstable...) modules - in the @Drawing@ hierarchy a separate package.- .- * Simplified Chains - chains are now regular lists (though often- infinite). Drawings are made with chains using new zip-like- functions.- .- * Re-worked Shapes.- .- * Re-worked Arrow and Arrow Tip types.- .- * Re-worked ConnectorPaths.- . build-type: Simple stability: highly unstable cabal-version: >= 1.2@@ -101,19 +74,22 @@ demo/SingleChar.hs, demo/SingleLine.hs, demo/SampleShapes.hs,- demo/Symbols.hs,- demo/TableChains.hs+ demo/Symbols.hs library hs-source-dirs: src build-depends: base < 5, containers >= 0.3 && <= 0.6, vector-space >= 0.6 && < 1.0,- wumpus-core >= 0.50.0 && < 0.51.0,- wumpus-basic == 0.17.0+ wumpus-core >= 0.51.0 && < 0.52.0,+ wumpus-basic == 0.18.0 exposed-modules:+ Wumpus.Drawing.Basis.DrawingPrimitives,+ Wumpus.Drawing.Basis.TraceGraphic,+ Wumpus.Drawing.Basis.LocTrace,+ Wumpus.Drawing.Basis.RefTrace, Wumpus.Drawing.Colour.SVGColours, Wumpus.Drawing.Colour.X11Colours, Wumpus.Drawing.Connectors,@@ -121,18 +97,15 @@ Wumpus.Drawing.Connectors.Base, Wumpus.Drawing.Connectors.BoxConnectors, Wumpus.Drawing.Connectors.ConnectorPaths,- Wumpus.Drawing.Connectors.Loop, Wumpus.Drawing.Dots.AnchorDots,- Wumpus.Drawing.Dots.Marks,+ Wumpus.Drawing.Dots.SimpleDots, Wumpus.Drawing.Extras.Axes,+ Wumpus.Drawing.Extras.Clip, Wumpus.Drawing.Extras.Grids,- Wumpus.Drawing.Extras.Turtle.TurtleClass,- Wumpus.Drawing.Extras.Turtle.TurtleMonad,+ Wumpus.Drawing.Extras.Loop, Wumpus.Drawing.Paths.Absolute,- Wumpus.Drawing.Paths.Base.AbsBuilder, Wumpus.Drawing.Paths.Base.AbsPath,- Wumpus.Drawing.Paths.Base.BuildCommon,- Wumpus.Drawing.Paths.Base.RelBuilder,+ Wumpus.Drawing.Paths.Base.PathBuilder, Wumpus.Drawing.Paths.Base.RelPath, Wumpus.Drawing.Paths.Relative, Wumpus.Drawing.Paths.Vamps,