wumpus-drawing 0.7.0 → 0.9.0
raw patch · 50 files changed
+2855/−1493 lines, 50 filesdep ~wumpus-basicPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: wumpus-basic
API changes (from Hackage documentation)
- Wumpus.Drawing.Basis.DrawingPrimitives: (<>) :: Monoid a => a -> a -> a
- Wumpus.Drawing.Basis.DrawingPrimitives: arc :: (Floating u, InterpretUnit u) => u -> Radian -> LocThetaGraphic u
- Wumpus.Drawing.Basis.DrawingPrimitives: cStraightLines :: InterpretUnit u => DrawMode -> [Point2 u] -> Graphic u
- Wumpus.Drawing.Basis.DrawingPrimitives: oStraightLines :: InterpretUnit u => [Point2 u] -> Graphic u
- Wumpus.Drawing.Basis.Symbols: left_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
- Wumpus.Drawing.Basis.Symbols: left_triangle :: (Fractional u, InterpretUnit u) => u -> LocGraphic u
- Wumpus.Drawing.Basis.Symbols: ocircle :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Drawing.Basis.Symbols: right_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
- Wumpus.Drawing.Basis.Symbols: right_triangle :: (Fractional u, InterpretUnit u) => u -> LocGraphic u
- Wumpus.Drawing.Connectors.Base: leftArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> ConnectorPathQuery u -> ArrowConnector u
- Wumpus.Drawing.Connectors.Base: leftRightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> ArrowTip -> ConnectorPathQuery u -> ArrowConnector u
- Wumpus.Drawing.Connectors.Base: rightArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> ConnectorPathQuery u -> ArrowConnector u
- Wumpus.Drawing.Connectors.Base: rightArrowPath :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> AbsPath u -> Image u (AbsPath u)
- Wumpus.Drawing.Connectors.Base: uniformArrow :: (Real u, Floating u, InterpretUnit u) => ArrowTip -> ConnectorPathQuery u -> ArrowConnector u
- Wumpus.Drawing.Connectors.BoxConnectors: connbox :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorBox u
- Wumpus.Drawing.Connectors.BoxConnectors: conntube :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorBox u
- Wumpus.Drawing.Connectors.ConnectorPaths: connabar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connaloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connarc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connaright :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connbbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connbloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connbright :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: conndiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: conndiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connhbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connhdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connhdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connhrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connline :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connrrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connrrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connvbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connvdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connvdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- Wumpus.Drawing.Connectors.ConnectorPaths: connvrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorProps -> ConnectorPathQuery u
- 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: directionL :: (Real u, Floating u) => AbsPath u -> Radian
- Wumpus.Drawing.Paths.Base: directionR :: (Real u, Floating u) => AbsPath u -> Radian
- Wumpus.Drawing.Paths.Base: drawPath :: InterpretUnit u => PathMode -> AbsPath u -> Image u (AbsPath u)
- Wumpus.Drawing.Paths.Base: drawPath_ :: InterpretUnit u => PathMode -> AbsPath u -> Graphic u
- Wumpus.Drawing.Paths.Base: placedTrailPath :: (Floating u, Ord u, Tolerance u) => Point2 u -> PlacedTrail u -> AbsPath u
- Wumpus.Drawing.Shapes.Diamond: instance (Real u, Floating u) => RadialAnchor (Diamond u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, Tolerance u) => RadialAnchor (InvSemicircle u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, Tolerance u) => RadialAnchor (InvSemiellipse u)
- Wumpus.Drawing.Shapes.InvTriangle: instance (Real u, Floating u) => CardinalAnchor2 (InvTriangle u)
- Wumpus.Drawing.Shapes.InvTriangle: instance (Real u, Floating u) => RadialAnchor (InvTriangle u)
- Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u) => CardinalAnchor (Parallelogram u)
- Wumpus.Drawing.Shapes.Rectangle: instance (Real u, Floating u) => CardinalAnchor2 (Rectangle u)
- Wumpus.Drawing.Shapes.Rectangle: instance (Real u, Floating u) => RadialAnchor (Rectangle u)
- Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Semicircle u)
- Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, Tolerance u) => RadialAnchor (Semicircle u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Semiellipse u)
- Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, Tolerance u) => RadialAnchor (Semiellipse u)
- Wumpus.Drawing.Shapes.Triangle: instance (Real u, Floating u) => CardinalAnchor2 (Triangle u)
- Wumpus.Drawing.Shapes.Triangle: instance (Real u, Floating u) => RadialAnchor (Triangle u)
+ Wumpus.Drawing.Basis.BezierCurve: BezierCurve :: !Point2 u -> !Point2 u -> !Point2 u -> !Point2 u -> BezierCurve u
+ Wumpus.Drawing.Basis.BezierCurve: bezierLength :: (Floating u, Ord u, Tolerance u) => BezierCurve u -> u
+ Wumpus.Drawing.Basis.BezierCurve: data BezierCurve u
+ Wumpus.Drawing.Basis.BezierCurve: instance (Ord u, Tolerance u) => Eq (BezierCurve u)
+ Wumpus.Drawing.Basis.BezierCurve: instance (Ord u, Tolerance u) => Ord (BezierCurve u)
+ Wumpus.Drawing.Basis.BezierCurve: instance Show u => Show (BezierCurve u)
+ Wumpus.Drawing.Basis.BezierCurve: subdivide :: Fractional u => BezierCurve u -> (BezierCurve u, BezierCurve u)
+ Wumpus.Drawing.Basis.BezierCurve: subdividet :: Real u => u -> BezierCurve u -> (BezierCurve u, BezierCurve u)
+ Wumpus.Drawing.Basis.BezierCurve: vbezierCurve :: Num u => Vec2 u -> Vec2 u -> Vec2 u -> Point2 u -> BezierCurve u
+ Wumpus.Drawing.Basis.Geometry: affineComb :: Real u => u -> Point2 u -> Point2 u -> Point2 u
+ Wumpus.Drawing.Basis.Geometry: midpoint :: Fractional u => Point2 u -> Point2 u -> Point2 u
+ Wumpus.Drawing.Basis.InclineTrails: incline_barb :: (Real u, Floating u) => Radian -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_chamf_rect :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_circle :: (Real u, Floating u) => Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_diamond :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_ellipse :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_rect :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_square :: (Real u, Floating u) => Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_triangle :: (Real u, Floating u) => Radian -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: incline_tube :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_diagh :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_diagv :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_hdiag :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_hdiagh :: (Real u, Floating u) => u -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_hright :: Num u => Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_hrr :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_ortho_hbar :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_ortho_vbar :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_perp_bar :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_perp_bar2 :: (Real u, Floating u) => ClockDirection -> u -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_rect_loop :: (Real u, Floating u) => ClockDirection -> u -> u -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_rrh :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_rrv :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_vdiag :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_vdiagv :: (Real u, Floating u) => u -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_vflam :: (Real u, Floating u) => ClockDirection -> u -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_vright :: Num u => Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: trail_vrr :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: vbowCurve :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: vrectCurve :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: vtrapCurve :: (Real u, Floating u) => ClockDirection -> u -> Radian -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: vtriCurve :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.InclineTrails: vwedgeCurve :: (Real u, Floating u) => ClockDirection -> u -> Vec2 u -> CatTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: circle_trail :: (Real u, Floating u) => u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: diamond_trail :: (Real u, Floating u) => u -> u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: ellipse_trail :: (Real u, Floating u) => u -> u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: isosceles_triangle_trail :: (Real u, Floating u) => u -> u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: parallelogram_trail :: Floating u => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rcircle_trail :: (Real u, Floating u) => u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rdiamond_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rectangle_trail :: (Real u, Floating u) => u -> u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rellipse_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: risosceles_triangle_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rparallelogram_trail :: Floating u => u -> u -> Radian -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rrectangle_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rsemicircle_trail :: (Real u, Floating u) => u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rsemiellipse_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: rtrapezium_trail :: Floating u => u -> u -> Radian -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: semicircle_trail :: (Real u, Floating u) => u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: semiellipse_trail :: (Real u, Floating u) => u -> u -> AnaTrail u
+ Wumpus.Drawing.Basis.ShapeTrails: trapezium_trail :: Floating u => u -> u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Basis.Symbols: fcircle :: InterpretUnit u => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fleft_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fleft_triangle :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fright_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fright_triangle :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fscircle :: InterpretUnit u => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fsleft_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fsleft_triangle :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fsquare :: (Fractional u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fsright_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fsright_triangle :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: fssquare :: (Fractional u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: scircle :: InterpretUnit u => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: sleft_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: sleft_triangle :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: sright_slice :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: sright_triangle :: (Real u, Floating u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Basis.Symbols: ssquare :: (Fractional u, InterpretUnit u) => u -> LocGraphic u
+ Wumpus.Drawing.Connectors.Base: ConnectorConfig :: Maybe ArrowTip -> Maybe ArrowTip -> ConnectorPathSpec u -> ConnectorConfig u
+ Wumpus.Drawing.Connectors.Base: ConnectorPathSpec :: (ConnectorProps -> ConnectorPathQuery u) -> ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.Base: arrowDecoratePath :: (Real u, Floating u, InterpretUnit u) => Maybe ArrowTip -> Maybe ArrowTip -> (AbsPath u) -> Image u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: conn_arrowl :: ConnectorConfig u -> Maybe ArrowTip
+ Wumpus.Drawing.Connectors.Base: conn_arrowr :: ConnectorConfig u -> Maybe ArrowTip
+ Wumpus.Drawing.Connectors.Base: conn_path_spec :: ConnectorConfig u -> ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.Base: data ConnectorConfig u
+ Wumpus.Drawing.Connectors.Base: getConnectorPathSpec :: ConnectorPathSpec u -> ConnectorProps -> ConnectorPathQuery u
+ Wumpus.Drawing.Connectors.Base: leftArrowConnector :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorPathSpec u -> ArrowTip -> ConnectorImage u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: newtype ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.Base: renderConnectorConfig :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorConfig u -> ConnectorImage u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: rightArrowConnector :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorPathSpec u -> ArrowTip -> ConnectorImage u (AbsPath u)
+ Wumpus.Drawing.Connectors.Base: type SpacingProjection u = ConnectorProps -> Point2 u -> Point2 u -> Query u (Point2 u)
+ Wumpus.Drawing.Connectors.Base: uniformArrowConnector :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorPathSpec u -> ArrowTip -> ConnectorImage u (AbsPath u)
+ Wumpus.Drawing.Connectors.BoxConnectors: ConnectorBoxSpec :: (ConnectorProps -> ConnectorBox u) -> ConnectorBoxSpec u
+ Wumpus.Drawing.Connectors.BoxConnectors: conn_box :: (Real u, Floating u, InterpretUnit u) => ConnectorBoxSpec u
+ Wumpus.Drawing.Connectors.BoxConnectors: conn_chamf_box :: (Real u, Floating u, InterpretUnit u) => ConnectorBoxSpec u
+ Wumpus.Drawing.Connectors.BoxConnectors: conn_tube :: (Real u, Floating u, InterpretUnit u) => ConnectorBoxSpec u
+ Wumpus.Drawing.Connectors.BoxConnectors: getConnectorBoxSpec :: ConnectorBoxSpec u -> ConnectorProps -> ConnectorBox u
+ Wumpus.Drawing.Connectors.BoxConnectors: newtype ConnectorBoxSpec u
+ Wumpus.Drawing.Connectors.BoxConnectors: renderConnectorBoxSpec :: (Real u, Floating u, InterpretUnit u) => ConnectorProps -> ConnectorBoxSpec u -> ConnectorBox u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_diagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_diagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_hbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_hdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_hdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_hrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_rrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_rrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_vbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_vdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_vdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conn_vrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_arc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_bar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_flam :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_loop :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_orthohbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_orthovbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: conna_right :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_arc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_bar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_flam :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_loop :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_orthohbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_orthovbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorPaths: connb_right :: (Real u, Floating u, Tolerance u, InterpretUnit u) => ConnectorPathSpec u
+ Wumpus.Drawing.Connectors.ConnectorProps: connectorLegs :: (DrawingCtxM m, InterpretUnit u) => ConnectorProps -> m (u, u)
+ Wumpus.Drawing.Extras.Loop: loopPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> Point2 u -> Radian -> AbsPath u
+ Wumpus.Drawing.Extras.Loop: loopTrail :: (Real u, Floating u) => u -> Radian -> AnaTrail u
+ Wumpus.Drawing.Paths.Base: anaTrailPath :: (Floating u, Ord u, Tolerance u) => Point2 u -> AnaTrail u -> AbsPath u
+ Wumpus.Drawing.Paths.Base: deBezier :: Floating u => AbsPath u -> AbsPath u
+ Wumpus.Drawing.Paths.Base: inclinationL :: (Real u, Floating u) => AbsPath u -> Radian
+ Wumpus.Drawing.Paths.Base: inclinationR :: (Real u, Floating u) => AbsPath u -> Radian
+ Wumpus.Drawing.Paths.Base: instance (Floating u, Ord u, Tolerance u) => Scale (AbsPath u)
+ Wumpus.Drawing.Paths.Base: instance (Floating u, Ord u, Tolerance u) => Scale (AbsPathSeg u)
+ Wumpus.Drawing.Paths.Base: instance (Real u, Floating u, Ord u, Tolerance u) => Rotate (AbsPath u)
+ Wumpus.Drawing.Paths.Base: instance (Real u, Floating u, Ord u, Tolerance u) => RotateAbout (AbsPath u)
+ Wumpus.Drawing.Paths.Base: instance Num u => Translate (AbsPathSeg u)
+ Wumpus.Drawing.Paths.Base: pathAllPoints :: Num u => AbsPath u -> [Point2 u]
+ Wumpus.Drawing.Paths.Base: pathMajorPoints :: Num u => AbsPath u -> [Point2 u]
+ Wumpus.Drawing.Paths.Base: renderPath :: InterpretUnit u => PathMode -> AbsPath u -> Image u (AbsPath u)
+ Wumpus.Drawing.Paths.Base: renderPath_ :: InterpretUnit u => PathMode -> AbsPath u -> Graphic u
+ Wumpus.Drawing.Paths.Illustrate: path_as_control_box :: (Floating u, InterpretUnit u) => AbsPath u -> Graphic u
+ Wumpus.Drawing.Paths.Illustrate: path_with_control_points :: (Floating u, InterpretUnit u) => AbsPath u -> Graphic u
+ Wumpus.Drawing.Paths.Intersection: Line :: (Point2 u) -> (Point2 u) -> Line u
+ Wumpus.Drawing.Paths.Intersection: Ray :: (Point2 u) -> (Point2 u) -> Ray u
+ Wumpus.Drawing.Paths.Intersection: data Line u
+ Wumpus.Drawing.Paths.Intersection: data Ray u
+ Wumpus.Drawing.Paths.Intersection: inclinedLine :: Floating u => Point2 u -> Radian -> Line u
+ Wumpus.Drawing.Paths.Intersection: inclinedRay :: Floating u => Point2 u -> Radian -> Ray u
+ Wumpus.Drawing.Paths.Intersection: instance (Ord u, Tolerance u) => Eq (Line u)
+ Wumpus.Drawing.Paths.Intersection: instance (Ord u, Tolerance u) => Eq (Ray u)
+ Wumpus.Drawing.Paths.Intersection: instance Eq u => Eq (LineEquation u)
+ Wumpus.Drawing.Paths.Intersection: instance Eq u => Eq (Matrix2'2 u)
+ Wumpus.Drawing.Paths.Intersection: instance Show u => Show (Line u)
+ Wumpus.Drawing.Paths.Intersection: instance Show u => Show (LineEquation u)
+ Wumpus.Drawing.Paths.Intersection: instance Show u => Show (Ray u)
+ Wumpus.Drawing.Paths.Intersection: isoscelesTriangleRadialIntersect :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Maybe (Vec2 u)
+ Wumpus.Drawing.Paths.Intersection: lineLineIntersection :: (Fractional u, Ord u, Tolerance u) => Line u -> Line u -> Maybe (Point2 u)
+ Wumpus.Drawing.Paths.Intersection: linePathIntersection :: (Real u, Floating u, Ord u, Tolerance u) => Line u -> AbsPath u -> Maybe (Point2 u)
+ Wumpus.Drawing.Paths.Intersection: linePathSegmentIntersection :: (Real u, Floating u, Ord u, Tolerance u) => Line u -> PathSegment u -> Maybe (Point2 u)
+ Wumpus.Drawing.Paths.Intersection: rayPathIntersection :: (Real u, Floating u, Ord u, Tolerance u) => Ray u -> AbsPath u -> Maybe (Point2 u)
+ Wumpus.Drawing.Paths.Intersection: rayPathSegmentIntersection :: (Real u, Floating u, Ord u, Tolerance u) => Ray u -> PathSegment u -> Maybe (Point2 u)
+ Wumpus.Drawing.Paths.Intersection: rectangleRadialIntersect :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Maybe (Vec2 u)
+ Wumpus.Drawing.Paths.Intersection: vectorLine :: Num u => Vec2 u -> Point2 u -> Line u
+ Wumpus.Drawing.Shapes.Base: ctmLocale :: ShapeCTM u -> (Point2 u, Radian)
+ Wumpus.Drawing.Shapes.Diamond: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Diamond u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemicircle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (InvSemicircle u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvSemiellipse: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (InvSemiellipse u)
+ Wumpus.Drawing.Shapes.InvTriangle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (InvTriangle u)
+ Wumpus.Drawing.Shapes.InvTriangle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (InvTriangle u)
+ Wumpus.Drawing.Shapes.Parallelogram: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor (Parallelogram u)
+ Wumpus.Drawing.Shapes.Rectangle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Rectangle u)
+ Wumpus.Drawing.Shapes.Rectangle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Rectangle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Semicircle u)
+ Wumpus.Drawing.Shapes.Semicircle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Semicircle u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Semiellipse u)
+ Wumpus.Drawing.Shapes.Semiellipse: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Semiellipse u)
+ Wumpus.Drawing.Shapes.Triangle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Triangle u)
+ Wumpus.Drawing.Shapes.Triangle: instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Triangle u)
- Wumpus.Drawing.Connectors.Base: ArrowTip :: (Double -> En) -> En -> LocThetaGraphic En -> ArrowTip
+ Wumpus.Drawing.Connectors.Base: ArrowTip :: En -> En -> LocThetaGraphic En -> ArrowTip
- Wumpus.Drawing.Connectors.Base: retract_distance :: ArrowTip -> Double -> En
+ Wumpus.Drawing.Connectors.Base: retract_distance :: ArrowTip -> En
- Wumpus.Drawing.Dots.AnchorDots: dotChar :: (Floating u, Real u, InterpretUnit u) => Char -> DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotChar :: (Floating u, Real u, InterpretUnit u, Tolerance u) => Char -> DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotSquare :: (Floating u, Real u, InterpretUnit u) => DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotSquare :: (Floating u, Real u, InterpretUnit u, Tolerance u) => DotLocImage u
- Wumpus.Drawing.Dots.AnchorDots: dotText :: (Floating u, Real u, InterpretUnit u) => String -> DotLocImage u
+ Wumpus.Drawing.Dots.AnchorDots: dotText :: (Floating u, Real u, InterpretUnit u, Tolerance u) => String -> DotLocImage u
- Wumpus.Drawing.Extras.Axes: horizontalLabels :: (Num a, Fractional u, InterpretUnit u) => RectAddress -> [a] -> LocGraphic u
+ Wumpus.Drawing.Extras.Axes: horizontalLabels :: (Num a, Show a, Fractional u, InterpretUnit u) => RectAddress -> [a] -> LocGraphic u
- Wumpus.Drawing.Extras.Axes: orthontAxes :: (Real u, Floating u, InterpretUnit u) => (Int, Int) -> (Int, Int) -> LocGraphic u
+ Wumpus.Drawing.Extras.Axes: orthontAxes :: (Real u, Floating u, InterpretUnit u, Tolerance u) => (Int, Int) -> (Int, Int) -> LocGraphic u
- Wumpus.Drawing.Extras.Axes: verticalLabels :: (Num a, Fractional u, InterpretUnit u) => RectAddress -> [a] -> LocGraphic u
+ Wumpus.Drawing.Extras.Axes: verticalLabels :: (Num a, Show a, Fractional u, InterpretUnit u) => RectAddress -> [a] -> LocGraphic u
- Wumpus.Drawing.Shapes.Trapezium: trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> u -> Shape Trapezium u
+ Wumpus.Drawing.Shapes.Trapezium: trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Shape Trapezium 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_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: 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_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: 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: centerRelative :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) => (Int, Int) -> a -> Query u (Anchor u)
- Wumpus.Drawing.Text.Base.Label: label_above :: (InterpretUnit u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_above :: (InterpretUnit u, CardinalAnchor a, u ~ DUnit a) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
- Wumpus.Drawing.Text.Base.Label: label_below :: (InterpretUnit u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_below :: (InterpretUnit u, CardinalAnchor a, u ~ DUnit a) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
- Wumpus.Drawing.Text.Base.Label: label_center_of :: (InterpretUnit u, CenterAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_center_of :: (InterpretUnit u, CenterAnchor a, u ~ DUnit a) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
- Wumpus.Drawing.Text.Base.Label: label_left_of :: (InterpretUnit u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_left_of :: (InterpretUnit u, CardinalAnchor a, u ~ DUnit a) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
- Wumpus.Drawing.Text.Base.Label: label_right_of :: (InterpretUnit u, CardinalAnchor a, u ~ (DUnit a)) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
+ Wumpus.Drawing.Text.Base.Label: label_right_of :: (InterpretUnit u, CardinalAnchor a, u ~ DUnit a) => BoundedLocRectGraphic u -> LocImage u a -> LocImage u a
- 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: 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.Text.Base.Label: right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) => a -> Query u (Anchor u)
Files
- demo/ArrowCircuit.hs +29/−16
- demo/Arrowheads.hs +8/−7
- demo/Automata.hs +11/−9
- demo/ClipPic.hs +1/−1
- demo/ColourCharts.hs +2/−2
- demo/Connectors.hs +49/−32
- demo/DotPic.hs +2/−2
- demo/FeatureModel.hs +9/−9
- demo/FontPic.hs +1/−1
- demo/PetriNet.hs +28/−17
- demo/SampleShapes.hs +10/−12
- demo/Symbols.hs +22/−9
- src/Wumpus/Drawing/Basis/BezierCurve.hs +137/−0
- src/Wumpus/Drawing/Basis/DrawingPrimitives.hs +6/−39
- src/Wumpus/Drawing/Basis/Geometry.hs +51/−0
- src/Wumpus/Drawing/Basis/InclineTrails.hs +499/−0
- src/Wumpus/Drawing/Basis/ShapeTrails.hs +213/−0
- src/Wumpus/Drawing/Basis/Symbols.hs +256/−52
- src/Wumpus/Drawing/Connectors.hs +0/−2
- src/Wumpus/Drawing/Connectors/Arrowheads.hs +129/−166
- src/Wumpus/Drawing/Connectors/Base.hs +96/−121
- src/Wumpus/Drawing/Connectors/BoxConnectors.hs +57/−52
- src/Wumpus/Drawing/Connectors/ConnectorPaths.hs +272/−354
- src/Wumpus/Drawing/Connectors/ConnectorProps.hs +10/−0
- src/Wumpus/Drawing/Dots/AnchorDots.hs +27/−36
- src/Wumpus/Drawing/Dots/SimpleDots.hs +12/−15
- src/Wumpus/Drawing/Extras/Axes.hs +13/−12
- src/Wumpus/Drawing/Extras/Loop.hs +24/−26
- src/Wumpus/Drawing/Paths/Base.hs +171/−35
- src/Wumpus/Drawing/Paths/Illustrate.hs +61/−0
- src/Wumpus/Drawing/Paths/Intersection.hs +318/−0
- src/Wumpus/Drawing/Paths/PathBuilder.hs +10/−10
- src/Wumpus/Drawing/Paths/Vamps.hs +1/−1
- src/Wumpus/Drawing/Shapes/Base.hs +7/−3
- src/Wumpus/Drawing/Shapes/Diamond.hs +18/−13
- src/Wumpus/Drawing/Shapes/Ellipse.hs +3/−3
- src/Wumpus/Drawing/Shapes/InvSemicircle.hs +2/−2
- src/Wumpus/Drawing/Shapes/InvSemiellipse.hs +3/−3
- src/Wumpus/Drawing/Shapes/InvTriangle.hs +4/−4
- src/Wumpus/Drawing/Shapes/Parallelogram.hs +55/−50
- src/Wumpus/Drawing/Shapes/Rectangle.hs +13/−13
- src/Wumpus/Drawing/Shapes/Semicircle.hs +33/−99
- src/Wumpus/Drawing/Shapes/Semiellipse.hs +29/−122
- src/Wumpus/Drawing/Shapes/Trapezium.hs +72/−55
- src/Wumpus/Drawing/Shapes/Triangle.hs +42/−70
- src/Wumpus/Drawing/Text/Base/DocTextZero.hs +5/−5
- src/Wumpus/Drawing/Text/Base/Label.hs +2/−2
- src/Wumpus/Drawing/Text/DocSymbols.hs +4/−4
- src/Wumpus/Drawing/VersionNumber.hs +3/−3
- wumpus-drawing.cabal +25/−4
demo/ArrowCircuit.hs view
@@ -65,12 +65,12 @@ atext a3 "+1" a4 <- drawi $ (strokedShape $ rectangle 66 30) `at` P2 120 0 atext a4 "DELAY 0"- connWith connline (east a1) ((.+^ hvec 76) $ east a1)- connWith connline (east a2) ((.+^ hvec 180) $ east a2)- connWith connline ((.+^ vvec 40) $ north a2) (north a2)- connWith connline ((.+^ vvec 16) $ north a3) (north a3) - connWith connaright (south a3) (east a4)- connWith connabar (west a4) (southwest a2)+ connWith conn_line (east a1) ((.+^ hvec 76) $ east a1)+ connWith conn_line (east a2) ((.+^ hvec 180) $ east a2)+ connWith conn_line ((.+^ vvec 40) $ north a2) (north a2)+ connWith conn_line ((.+^ vvec 16) $ north a3) (north a3) + connWith conna_right (south a3) (east a4)+ connWith conna_orthovbar (west a4) (southwest a2) ptext (P2 40 10) "next" ptext (P2 152 100) "reset" ptext (P2 252 72) "output"@@ -79,9 +79,9 @@ -- Note - need a variant of /bar/ that draws UDLR only. connWith :: ( Real u, Floating u, InterpretUnit u ) - => ConnectorPathQuery u -> Anchor u -> Anchor u -> TraceDrawing u ()+ => ArrowConnector u -> Anchor u -> Anchor u -> TraceDrawing u () connWith con a0 a1 = localize double_point_size $ - drawc a0 a1 (rightArrow tri45 con)+ drawc a0 a1 (ignoreAns con) atext :: ( CenterAnchor (t u), u ~ DUnit (t u)@@ -110,15 +110,28 @@ -- Cf. Parsec\'s Token module... -connline :: (Real u, Floating u, InterpretUnit u) => ConnectorPathQuery u-connline = C.connline default_connector_props+conn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conn_line =+ renderConnectorConfig default_connector_props $ makeSglArrConn C.conn_line -connabar :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorPathQuery u-connabar = C.connabar default_connector_props+conna_orthovbar :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conna_orthovbar = + renderConnectorConfig default_connector_props $ + makeSglArrConn C.conna_orthovbar -connaright :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorPathQuery u-connaright = C.connaright default_connector_props+conna_right :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conna_right = + renderConnectorConfig default_connector_props $ makeSglArrConn C.conna_right ++makeSglArrConn :: ConnectorPathSpec u -> ConnectorConfig u+makeSglArrConn cspec = + ConnectorConfig+ { conn_arrowl = Nothing+ , conn_arrowr = Just tri45+ , conn_path_spec = cspec+ }
demo/Arrowheads.hs view
@@ -37,7 +37,7 @@ arrow_drawing :: CtxPicture arrow_drawing = - drawTracing $ localize dotted_line $ tableGraphic arrtable+ drawTracing $ localize line_thick $ tableGraphic arrtable arrtable :: [(String, ArrowTip)] arrtable = @@ -77,8 +77,7 @@ tableGraphic :: [(String, ArrowTip)] -> TraceDrawing Double () tableGraphic tips = - drawl start $ runTableColumnwise 18 (180,24) - $ sequenceChain $ map arrowGraphic tips+ drawl start $ distribColumnwiseTable 18 (180,24) $ map arrowGraphic tips where start = P2 0 480 @@ -94,13 +93,15 @@ arrowGraphic (name, utip) = aconn `mappend` lbl where aconn = ignoreAns $ promoteLoc $ \pt ->- connect (uniformArrow utip connline) pt (displace (hvec 60) pt)+ connect (mkConn_line utip) pt (displace (hvec 60) pt) lbl = ignoreAns $ promoteLoc $ \pt -> textline WW name `at` (displace (hvec 66) pt) --- Cf. Parsec\'s Token module... -connline :: (Real u, Floating u, InterpretUnit u) => ConnectorPathQuery u-connline = C.connline default_connector_props+mkConn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowTip -> ArrowConnector u+mkConn_line = rightArrowConnector default_connector_props C.conn_line++
demo/Automata.hs view
@@ -79,20 +79,19 @@ -straightconn :: ( Real u, Floating u, InterpretUnit u+straightconn :: ( Real u, Floating u, InterpretUnit u, Tolerance u , u ~ DUnit a, u ~ DUnit b , CenterAnchor a, RadialAnchor a , CenterAnchor b, RadialAnchor b ) => a -> b -> Image u (AbsPath u) straightconn a b =- let (p0,p1) = radialConnectorPoints a b- in connect (rightArrow tri45 connline) p0 p1+ let (p0,p1) = radialConnectorPoints a b in connect conn_line p0 p1 -astraightconn :: ( Real u, Floating u, InterpretUnit u)+astraightconn :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Anchor u -> Anchor u -> Image u (AbsPath u)-astraightconn p0 p1 = connect (rightArrow tri45 connline) p0 p1+astraightconn p0 p1 = connect conn_line p0 p1 -- Note - there is a problem with @rightArrow@ as @loop@@@ -101,8 +100,7 @@ arrloop :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Anchor u -> Anchor u -> Image u (AbsPath u) arrloop ctr p1 = - liftQuery (loop zradius ctr zincl) >>= \absp -> - rightArrowPath tri45 absp + rightArrowPath $ loopPath zradius ctr zincl where v1 = pvec ctr p1 zradius = vlength v1@@ -111,9 +109,13 @@ -- Cf. Parsec\'s Token module... -connline :: (Real u, Floating u, InterpretUnit u) => ConnectorPathQuery u-connline = C.connline default_connector_props+conn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conn_line = rightArrowConnector default_connector_props C.conn_line tri45 +rightArrowPath :: (Real u, Floating u, InterpretUnit u)+ => AbsPath u -> Image u (AbsPath u)+rightArrowPath = arrowDecoratePath Nothing (Just tri45)
demo/ClipPic.hs view
@@ -68,7 +68,7 @@ background rgb = promoteLoc $ \_ -> ignoreAns $ localize (text_colour rgb) $ ihh `at` P2 0 288 where- ihh = runTableColumnwise 18 (86,16) $ mapM chain1 $ replicate 112 iheartHaskell+ ihh = distribColumnwiseTable 18 (86,16) $ replicate 112 iheartHaskell -- | This is one for Wumpus-Basic - the set of combinators to
demo/ColourCharts.hs view
@@ -43,9 +43,9 @@ makeDrawing row_count xs = drawTracing $ tableGraphic row_count xs tableGraphic :: Int -> [(String,RGBi)] -> TraceDrawing Double ()-tableGraphic row_count xs = draw $ (runChain chn (mapM chain1 gs)) `at` pt+tableGraphic row_count xs = + drawl pt $ distribColumnwiseTable row_count (152,11) gs where- chn = tableColumnwiseScm row_count (152,11) pt = displace (vvec $ fromIntegral $ 11 * row_count) zeroPt gs = map (uncurry colourSample) xs
demo/Connectors.hs view
@@ -38,39 +38,47 @@ conn_pic = drawTracing $ tableGraphic conntable -conntable :: [(String, ConnectorPathQuery Double)]+conntable :: [(String, ConnectorPathSpec Double)] conntable = - [ ("connline", C.connline props)- , ("connarc", C.connarc props)- , ("connhdiagh", C.connhdiagh props)- , ("connvdiagv", C.connvdiagv props)- , ("conndiagh", C.conndiagh props)- , ("conndiagv", C.conndiagv props)- , ("connhdiag", C.connhdiag props)- , ("connvdiag", C.connvdiag props)- , ("connabar", C.connabar props)- , ("connbbar", C.connbbar props)- , ("connaright", C.connaright props)- , ("connbright", C.connbright props)- , ("connhrr", C.connhrr props)- , ("connrrh", C.connrrh props)- , ("connvrr", C.connvrr props)- , ("connrrv", C.connrrv props)- , ("connaloop", C.connaloop props)- , ("connbloop", C.connbloop props)- , ("connhbezier", C.connhbezier props)- , ("connvbezier", C.connvbezier props)+ [ ("conn_line", C.conn_line)+ , ("conna_arc", C.conna_arc)+ , ("connb_arc", C.connb_arc)+ , ("conn_hdiagh", C.conn_hdiagh)+ , ("conn_vdiagv", C.conn_vdiagv)+ , ("conn_diagh", C.conn_diagh)+ , ("conn_diagv", C.conn_diagv)+ , ("conn_hdiag", C.conn_hdiag)+ , ("conn_vdiag", C.conn_vdiag)+ , ("conna_bar", C.conna_bar)+ , ("connb_bar", C.connb_bar)+ , ("conna_flam", C.conna_flam)+ , ("connb_flam", C.connb_flam)+ , ("conna_orthohbar", C.conna_orthohbar)+ , ("connb_orthohbar", C.connb_orthohbar)+ , ("conna_orthovbar", C.conna_orthovbar)+ , ("connb_orthovbar", C.connb_orthovbar)+ , ("conna_right", C.conna_right)+ , ("connb_right", C.connb_right)+ , ("conn_hrr", C.conn_hrr )+ , ("conn_rrh", C.conn_rrh)+ , ("conn_vrr", C.conn_vrr)+ , ("conn_rrv", C.conn_rrv)+ , ("conna_loop", C.conna_loop)+ , ("connb_loop", C.connb_loop)+ , ("conn_hbezier", C.conn_hbezier)+ , ("conn_vbezier", C.conn_vbezier) ]- where- props = default_connector_props { conn_dst_arm = 2- , conn_src_space = 0.5- , conn_dst_space = 0.5 } +props :: ConnectorProps+props = default_connector_props { conn_src_arm = 1+ , conn_dst_arm = 1.5+ , conn_src_space = 0.5+ , conn_dst_space = 0.5 } -tableGraphic :: [(String, ConnectorPathQuery Double)] -> TraceDrawing Double ()++tableGraphic :: [(String, ConnectorPathSpec Double)] -> TraceDrawing Double () tableGraphic conns = - drawl start $ ignoreAns $ runTableColumnwise 8 (180,64)- $ mapM (chain1 . makeConnDrawing) conns+ drawl start $ distribColumnwiseTable 6 (200,80) $ map makeConnDrawing conns where start = P2 0 520 @@ -80,15 +88,24 @@ -makeConnDrawing :: (String, ConnectorPathQuery Double) -> DLocGraphic +makeConnDrawing :: (String, ConnectorPathSpec Double) -> DLocGraphic makeConnDrawing (ss,conn) = - promoteLoc $ \p0 -> fn p0 (displace (vec 60 40) p0) + promoteLoc $ \p0 -> fn p0 (displace (vec 72 42) p0) where fn p0 p1 = mconcat [disk p0, disk p1, dcon p0 p1, lbl p1] disk pt = localize (fill_colour red) $ dcDisk DRAW_FILL 2 `at` pt- dcon p0 p1 = ignoreAns $ connect (uniformArrow curveTip conn) p0 p1+ dcon p0 p1 = ignoreAns $ connect biarrow p0 p1 - lbl pt = ignoreAns $ textline WW ss `at` (displace (hvec 10) pt)+ lbl pt = ignoreAns $ textline WW ss `at` (displace (V2 10 (-10)) pt) + biarrow = renderConnectorConfig props conf+ ++ conf = ConnectorConfig { conn_arrowl = Just curveTip+ , conn_arrowr = Just curveTip+ , conn_path_spec = conn+ }++
demo/DotPic.hs view
@@ -72,8 +72,8 @@ tableGraphic :: [(String, DotLocImage Double)] -> TraceDrawing Double () tableGraphic imgs = - drawl pt $ runTableColumnwise row_count (180,36) - $ mapM (chain1 . makeDotDrawing) imgs+ drawl pt $ distribColumnwiseTable row_count (180,36) + $ map makeDotDrawing imgs where row_count = 18 pt = displace (vvec $ fromIntegral $ 36 * row_count) zeroPt
demo/FeatureModel.hs view
@@ -87,35 +87,35 @@ widebox = makeBox 60 -connWith :: ( Real u, Floating u, InterpretUnit u ) +connWith :: ( Real u, Floating u, InterpretUnit u, Tolerance 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 (mkConn_line arrh) p0 p1 infixr 4 `cmandatory`, `coptional`, `cmandatory_`, `coptional_` -cmandatory :: ( Real u, Floating u, InterpretUnit u ) +cmandatory :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Box u -> Box u -> TraceDrawing u (AbsPath u) cmandatory = connWith diskTip -coptional :: ( Real u, Floating u, InterpretUnit u ) +coptional :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Box u -> Box u -> TraceDrawing u (AbsPath u) coptional = connWith odiskTip -cmandatory_ :: ( Real u, Floating u, InterpretUnit u ) +cmandatory_ :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Box u -> Box u -> TraceDrawing u () cmandatory_ p0 p1 = connWith diskTip p0 p1 >> return () -coptional_ :: ( Real u, Floating u, InterpretUnit u ) +coptional_ :: ( Real u, Floating u, InterpretUnit u, Tolerance u) => Box u -> Box u -> TraceDrawing u () coptional_ p0 p1 = connWith odiskTip p0 p1 >> return () --- Cf. Parsec\'s Token module... -connline :: (Real u, Floating u, InterpretUnit u) => ConnectorPathQuery u-connline = C.connline default_connector_props+mkConn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowTip -> ArrowConnector u+mkConn_line = rightArrowConnector default_connector_props C.conn_line
demo/FontPic.hs view
@@ -82,7 +82,7 @@ fontDrawing xs = drawTracing $ drawl start $ runChain_ chn_alg $ mapM (chain1 . uncurry fontGraphic) xs where- chn_alg = tableColumnwiseScm 4 (2,180)+ chn_alg = columnwiseTableScheme 4 (2,180) start = P2 0 (4*180)
demo/PetriNet.hs view
@@ -99,22 +99,29 @@ +makeSglArrConn :: ConnectorPathSpec u -> ConnectorConfig u+makeSglArrConn cspec = + ConnectorConfig+ { conn_arrowl = Nothing+ , conn_arrowr = Just tri45+ , conn_path_spec = cspec+ } straightconn :: ConnectorGraphic Double-straightconn = ignoreAns $ rightArrow tri45 connline+straightconn = ignoreAns conn_line connectorC :: ConnectorGraphic Double-connectorC = ignoreAns $ rightArrow tri45 connbbar+connectorC = ignoreAns conna_bar connectorC' :: ConnectorGraphic Double-connectorC' = ignoreAns $ rightArrow tri45 connabar+connectorC' = ignoreAns connb_bar connectorD :: ConnectorGraphic Double-connectorD = ignoreAns $ rightArrow tri45 connarc+connectorD = ignoreAns conna_arc connectorD' :: ConnectorGraphic Double-connectorD' = ignoreAns $ rightArrow tri45 connarc+connectorD' = ignoreAns connb_arc lblParensParens :: DLocGraphic@@ -140,21 +147,25 @@ , conn_dst_arm = 2 , conn_arc_ang = negate $ pi / 12 }) -connline :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => ConnectorPathQuery u-connline = C.connline conn_props+conn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conn_line = renderConnectorConfig conn_props $ makeSglArrConn C.conn_line -connabar :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => ConnectorPathQuery u-connabar = C.connabar conn_props+conna_bar :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conna_bar = renderConnectorConfig conn_props $ makeSglArrConn C.conna_bar -connbbar :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => ConnectorPathQuery u-connbbar = C.connbbar conn_props+connb_bar :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+connb_bar = renderConnectorConfig conn_props $ makeSglArrConn C.connb_bar -connarc :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => ConnectorPathQuery u-connarc = C.connarc conn_props+conna_arc :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conna_arc = renderConnectorConfig conn_props $ makeSglArrConn C.conna_arc++connb_arc :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+connb_arc = renderConnectorConfig conn_props $ makeSglArrConn C.connb_arc
demo/SampleShapes.hs view
@@ -68,7 +68,7 @@ , shapePic (apexAnchor >=> bottomCorners) $ semiellipse 100 150) , ( "trapezium" , shapePic (bottomCorners >=> topCorners >=> midPoints 4) $ - trapezium 300 200 150)+ trapezium 300 180 ang60) , ( "triangle" , shapePic (apexAnchor >=> bottomCorners >=> midPoints 3) $ triangle 300 150 )@@ -137,7 +137,7 @@ => (t Double -> DTraceDrawing a) -> DShape t -> String -> CtxPicture shapePic mf sh name = udrawTracing (0::Double) $ do a1 <- localize shapeSty $ drawi $ - uniformScale 2 $ rotate05 $ shape `at` (P2 100 0)+ uniformScale 2 $ {- rotate05 $ -} shape `at` (P2 100 0) draw $ label NORTH "(center)" `at` center a1 draw $ label NORTH "(north)" `at` north a1 draw $ label SOUTH "(south)" `at` south a1@@ -147,22 +147,20 @@ draw $ label NORTH_WEST "(northwest)" `at` northwest a1 draw $ label SOUTH_EAST "(southeast)" `at` southeast a1 draw $ label SOUTH_WEST "(southwest)" `at` southwest a1- draw $ label EAST "(10 deg)" `at` radialAnchor deg10 a1- draw $ label NORTH_WEST "(110 deg)" `at` radialAnchor deg110 a1- draw $ label WEST "(190 deg)" `at` radialAnchor deg190 a1- draw $ label NORTH "(250 deg)" `at` radialAnchor deg250 a1+ draw $ label EAST "(10 deg)" `at` radialAnchor (d2r 10) a1+ draw $ label NORTH_WEST "(110 deg)" `at` radialAnchor (d2r 110) a1+ draw $ label WEST "(190 deg)" `at` radialAnchor (d2r 190) a1+ draw $ label NORTH "(250 deg)" `at` radialAnchor (d2r 250) a1+ draw $ label WEST "(200 deg)" `at` radialAnchor (d2r 200) a1++-- draw $ label WEST "(0 deg)" `at` radialAnchor (d2r 0) a1+ draw $ label NORTH "(224.5 deg)" `at` radialAnchor (d2r 225.5) a1 _ <- mf a1 return () where shape = strokedShape $ setDecoration textF sh textF = promoteLocTheta $ \pt _ -> ignoreAns (multilineText VALIGN_CENTER CENTER name) `at` pt-- deg10 = d2r (10::Double)- deg110 = d2r (110::Double)- deg190 = d2r (190::Double)- deg250 = d2r (250::Double)-
demo/Symbols.hs view
@@ -2,7 +2,6 @@ module Symbols where -import Wumpus.Drawing.Basis.DrawingPrimitives import Wumpus.Drawing.Basis.Symbols import Wumpus.Drawing.Colour.SVGColours import Wumpus.Drawing.Text.DirectionZero@@ -13,6 +12,7 @@ import Wumpus.Core -- package: wumpus-core +import Data.Monoid import System.Directory @@ -30,7 +30,7 @@ makeCtx :: FontLoadResult -> DrawingContext-makeCtx = set_font times_roman . metricsContext 14+makeCtx = fill_colour khaki . set_font times_roman . metricsContext 14 symb_pic :: CtxPicture symb_pic = drawTracing $ tableGraphic symbtable@@ -38,17 +38,30 @@ symbtable :: [(String, LocGraphic Double)] symbtable = - [ ("ocircle", ocircle 8) + [ ("scircle", scircle 8) + , ("fcircle", fcircle 8) + , ("fscircle", fscircle 8) + , ("ssquare", ssquare 8) + , ("fsquare", fsquare 8) + , ("fssquare", fssquare 8) + , ("sleft_slice", sleft_slice 14)+ , ("fleft_slice", fleft_slice 14)+ , ("fsleft_slice", fsleft_slice 14)+ , ("sright_slice", sright_slice 14)+ , ("fright_slice", fright_slice 14)+ , ("fsright_slice", fsright_slice 14)+ , ("sleft_triangle", sleft_triangle 14)+ , ("fleft_triangle", fleft_triangle 14)+ , ("fsleft_triangle", fsleft_triangle 14)+ , ("sright_triangle", sright_triangle 14)+ , ("fright_triangle", fright_triangle 14)+ , ("fsright_triangle", fsright_triangle 14) , ("ochar", ochar $ CharLiteral 'a') , ("ochar - bad", ochar $ CharLiteral 'g') , ("ocharDescender", ocharDescender $ CharLiteral 'g') , ("ocharUpright", ocharUpright $ CharLiteral '8') , ("ocharUpright - bad", ocharUpright $ CharLiteral 'a') , ("ocurrency", ocurrency 8)- , ("left_slice", left_slice 14)- , ("right_slice", right_slice 14)- , ("left_triangle", left_triangle 14)- , ("right_triangle", right_triangle 14) , ("hbar", hbar 14) , ("vbar", vbar 14) , ("dbl_hbar", dbl_hbar 14)@@ -58,8 +71,8 @@ tableGraphic :: [(String, LocGraphic Double)] -> TraceDrawing Double () tableGraphic symbs = - drawl start $ ignoreAns $ runTableColumnwise 8 (180,24)- $ mapM (chain1 . makeSymbDrawing) symbs+ drawl start $ ignoreAns $ distribColumnwiseTable 14 (180,24)+ $ map makeSymbDrawing symbs where start = P2 0 520
+ src/Wumpus/Drawing/Basis/BezierCurve.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.BezierCurve+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Datatype for cubic Bezier curve.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.BezierCurve+ ( ++ BezierCurve(..)+ , vbezierCurve+ , subdivide+ , subdividet++ , bezierLength++ ) where+++import Wumpus.Drawing.Basis.Geometry+++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+++--------------------------------------------------------------------------------++++-- | A Strict cubic Bezier curve.+--+data BezierCurve u = BezierCurve !(Point2 u) !(Point2 u) !(Point2 u) !(Point2 u)+ deriving (Eq,Ord,Show)++type instance DUnit (BezierCurve u) = u++++vbezierCurve :: Num u + => Vec2 u -> Vec2 u -> Vec2 u -> Point2 u -> BezierCurve u+vbezierCurve v1 v2 v3 p0 = BezierCurve p0 p1 p2 p3+ where+ p1 = p0 .+^ v1+ p2 = p1 .+^ v2+ p3 = p2 .+^ v3++++-- | Curve subdivision via de Casteljau\'s algorithm.+--+subdivide :: Fractional u + => BezierCurve u -> (BezierCurve u, BezierCurve u)+subdivide (BezierCurve p0 p1 p2 p3) =+ (BezierCurve p0 p01 p012 p0123, BezierCurve p0123 p123 p23 p3)+ where+ p01 = midpoint p0 p1+ p12 = midpoint p1 p2+ p23 = midpoint p2 p3+ p012 = midpoint p01 p12+ p123 = midpoint p12 p23+ p0123 = midpoint p012 p123+++-- | subdivide with an affine weight along the line...+--+subdividet :: Real u+ => u -> BezierCurve u -> (BezierCurve u, BezierCurve u)+subdividet t (BezierCurve p0 p1 p2 p3) = + (BezierCurve p0 p01 p012 p0123, BezierCurve p0123 p123 p23 p3)+ where+ p01 = affineComb t p0 p1+ p12 = affineComb t p1 p2+ p23 = affineComb t p2 p3+ p012 = affineComb t p01 p12+ p123 = affineComb t p12 p23+ p0123 = affineComb t p012 p123+++--------------------------------------------------------------------------------++-- | 'bezierLength' : @ start_point * control_1 * control_2 * +-- end_point -> Length @ +--+-- Find the length of a Bezier curve. The result is an +-- approximation, with the /tolerance/ is 0.1 of a point. This+-- seems good enough for drawing (potentially the tolerance could +-- be larger still). +--+-- The result is found through repeated subdivision so the +-- calculation is potentially costly.+--+bezierLength :: (Floating u, Ord u, Tolerance u)+ => BezierCurve u -> u+bezierLength = gravesenLength length_tolerance ++++-- | Jens Gravesen\'s bezier arc-length approximation. +--+-- Note this implementation is parametrized on error tolerance.+--+gravesenLength :: (Floating u, Ord u) => u -> BezierCurve u -> u+gravesenLength err_tol crv = step crv + where+ step c = let l1 = ctrlPolyLength c+ l0 = cordLength c+ in if l1-l0 > err_tol+ then let (a,b) = subdivide c in step a + step b+ else 0.5*l0 + 0.5*l1++-- | Length of the tree lines spanning the control points.+--+ctrlPolyLength :: Floating u => BezierCurve u -> u+ctrlPolyLength (BezierCurve p0 p1 p2 p3) = len p0 p1 + len p1 p2 + len p2 p3+ where+ len pa pb = vlength $ pvec pa pb+++-- | Length of the cord - start point to end point.+--+cordLength :: Floating u => BezierCurve u -> u+cordLength (BezierCurve p0 _ _ p3) = vlength $ pvec p0 p3++
src/Wumpus/Drawing/Basis/DrawingPrimitives.hs view
@@ -4,7 +4,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Basis.DrawingPrimitives--- Copyright : (c) Stephen Tetley 2011+-- Copyright : (c) Stephen Tetley 2011-2012 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -27,34 +27,27 @@ module Wumpus.Drawing.Basis.DrawingPrimitives ( - -- * Monoid mappend- (<>) -- * Lines - , horizontalLine+ horizontalLine , verticalLine , pivotLine - , oStraightLines- , cStraightLines - -- * Rectangles , blRectangle , ctrRectangle - -- * Arc and wedge- , arc+ -- * Wedge , wedge ) where -import Wumpus.Basic.Geometry -- package: wumpus-basic-import Wumpus.Basic.Kernel+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core @@ -63,18 +56,7 @@ import Data.Monoid -infixr 6 <> ---- | Alias for mappend in Monoid.------ > <> (infixr 6)--- -(<>) :: Monoid a => a -> a -> a-(<>) = mappend--- -------------------------------------------------------------------------------- -- Lines @@ -102,17 +84,8 @@ straightLine (pt .+^ avec (ang+pi) lu) (pt .+^ avec ang ru) --- | Draw an open path formed from straight line segments.----oStraightLines :: InterpretUnit u => [Point2 u] -> Graphic u-oStraightLines ps = liftQuery (vertexPP ps) >>= dcOpenPath --- | Draw an closed path formed from straight line segments.----cStraightLines :: InterpretUnit u => DrawMode -> [Point2 u] -> Graphic u-cStraightLines mode ps = liftQuery (vertexPP ps) >>= dcClosedPath mode - -------------------------------------------------------------------------------- -- Rectangles @@ -141,12 +114,6 @@ -- 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 liftQuery (curvePP ps) >>= dcOpenPath -- | wedge : mode * radius * apex_angle -- @@ -158,8 +125,8 @@ let half_ang = 0.5 * ang line_in = catline $ avec (inclin + half_ang) radius line_out = catline $ avec (inclin - half_ang) (-radius)- w_arc = circularArcCW ang radius (inclin - half_pi)+ w_arc = circularArc CW ang radius (inclin - half_pi) ct = line_in `mappend` w_arc `mappend` line_out- in supplyLoc pt $ drawCatTrail (closedMode mode) ct+ in supplyLoc pt $ renderCatTrail (closedMode mode) ct
+ src/Wumpus/Drawing/Basis/Geometry.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.Geometry+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Misc geometric operations.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.Geometry+ ( ++ midpoint+ , affineComb++ ) where+++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++--------------------------------------------------------------------------------++++--------------------------------------------------------------------------------+--+++-- | Affine combination...+--+affineComb :: Real u => u -> Point2 u -> Point2 u -> Point2 u+affineComb t p1 p2 = p1 .+^ t *^ (p2 .-. p1)+++-- | 'midpoint' : @ start_point * end_point -> Midpoint @+-- +-- Mid-point on the line formed between the two supplied points.+--+midpoint :: Fractional u => Point2 u -> Point2 u -> Point2 u+midpoint p0 p1 = p0 .+^ v1 ^/ 2 where v1 = p1 .-. p0
+ src/Wumpus/Drawing/Basis/InclineTrails.hs view
@@ -0,0 +1,499 @@+{-# OPTIONS -Wall #-}+++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.InclineTrails+-- Copyright : (c) Stephen Tetley 2011-2012+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.InclineTrails+ (++ incline_circle+ , incline_ellipse+ , incline_square+ , incline_rect+ , incline_diamond+ , incline_triangle+ , incline_barb+ , incline_tube+ , incline_chamf_rect++ , trail_diagh+ , trail_diagv+ , trail_hdiag+ , trail_vdiag++ , trail_hdiagh+ , trail_vdiagv++ , trail_perp_bar+ , trail_perp_bar2++ , trail_vflam+ , trail_ortho_hbar+ , trail_ortho_vbar++ , trail_hright+ , trail_vright++ , trail_hrr+ , trail_vrr+ , trail_rrh+ , trail_rrv++ , trail_rect_loop++ , vtriCurve+ , vrectCurve+ , vtrapCurve+ , vbowCurve+ , vwedgeCurve++ )+ where+++import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space++import Data.Monoid+++-- Shapes...++incline_circle :: (Real u, Floating u) => Vec2 u -> AnaTrail u+incline_circle v1 = + anaCatTrail zeroVec (semicircleTrail CW v1 <> semicircleTrail CW rv1)+ where+ rv1 = vreverse v1++incline_ellipse :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u+incline_ellipse ry v1 = + anaCatTrail zeroVec (semiellipseTrail CW ry v1 <> semiellipseTrail CW ry rv1)+ where+ rv1 = vreverse v1++++incline_square :: (Real u, Floating u) => Vec2 u -> AnaTrail u+incline_square v1 = incline_rect (vlength v1) v1+++incline_rect :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u+incline_rect h v1 = + anaCatTrail (theta_down (0.5 * h) ang) catt+ where+ len = vlength v1+ ang = vdirection v1+ catt = mconcat [ trail_theta_right len ang+ , trail_theta_up h ang + , trail_theta_left len ang + , trail_theta_down h ang + ]+ +incline_diamond :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u+incline_diamond h v1 = anaCatTrail zeroVec catt+ where+ hw = 0.5 * vlength v1+ hh = 0.5 * h+ ang = vdirection v1+ catt = mconcat [ orthoCatTrail hw (-hh) ang+ , orthoCatTrail hw hh ang + , orthoCatTrail (-hw) hh ang + , orthoCatTrail (-hw) (-hh) ang + ]++-- | Note - vector represents midpoint of the baseline to the +-- tip. Angle is the ang of the tip.+--+-- This trail is primarily for drawing arrowheads.+-- +incline_triangle :: (Real u, Floating u) => Radian -> Vec2 u -> AnaTrail u+incline_triangle tip_ang v1 = + anaCatTrail (theta_up opposite theta) catt+ where+ half_ang = 0.5 * tip_ang+ theta = vdirection v1+ h = vlength v1+ opposite = h * (fromRadian $ tan half_ang)++ catt = mconcat [ trail_theta_adj_grazing h half_ang theta+ , trail_theta_bkwd_adj_grazing h half_ang theta+ , trail_theta_up (2 * opposite) theta+ ]+++-- | Note - vector represents midpoint of the baseline to the +-- tip. Angle is the ang of the tip.+--+-- This trail is primarily for drawing arrowheads. The resulting +-- path is /open/. +-- +incline_barb :: (Real u, Floating u) => Radian -> Vec2 u -> AnaTrail u+incline_barb tip_ang v1 = + anaCatTrail (theta_up opposite theta) catt+ where+ half_ang = 0.5 * tip_ang+ theta = vdirection v1+ h = vlength v1+ opposite = h * (fromRadian $ tan half_ang)++ catt = mconcat [ trail_theta_adj_grazing h half_ang theta+ , trail_theta_bkwd_adj_grazing h half_ang theta+ ]+++-- | @v1@ is the /interior/ vector.+--+incline_tube :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u+incline_tube h v1 = + anaCatTrail (theta_down_right hh ang) $ mconcat $+ [ trail_theta_right base_len ang+ , semicircleTrail CCW vup+ , trail_theta_left base_len ang+ , semicircleTrail CCW vdown+ ]+ where+ hh = 0.5 * h+ ang = vdirection v1 + base_len = vlength v1 - h+ vup = avec (ang + half_pi) h+ vdown = avec (ang - half_pi) h+++incline_chamf_rect :: (Real u, Floating u) => u -> Vec2 u -> AnaTrail u+incline_chamf_rect h v1 = + anaCatTrail zeroVec $ mconcat $+ [ trail_theta_down_right hh ang+ , trail_theta_right base_len ang+ , trail_theta_up_right hh ang+ , trail_theta_up_left hh ang+ , trail_theta_left base_len ang+ , trail_theta_down_left hh ang+ ]+ where+ hh = 0.5 * h+ ang = vdirection v1 + base_len = vlength v1 - h++-- | Diagonal-horizontal trail.+--+-- > --@+-- > /+-- > o+-- +trail_diagh :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u+trail_diagh leg v1 = + let h = vector_y v1+ mid = (abs $ vector_x v1) - leg+ in case horizontalDirection $ vdirection v1 of+ RIGHTWARDS -> orthoCatTrail mid h 0 <> trail_right leg+ _ -> orthoCatTrail (-mid) h 0 <> trail_left leg++trail_diagv :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u+trail_diagv leg v1 = + let w = vector_x v1+ mid = (abs $ vector_y v1) - leg+ in case verticalDirection $ vdirection v1 of+ UPWARDS -> orthoCatTrail w mid 0 <> trail_up leg+ _ -> orthoCatTrail w (-mid) 0 <> trail_down leg+++trail_hdiag :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u+trail_hdiag leg v1 = + let h = vector_y v1+ mid = (abs $ vector_x v1) - leg+ in case horizontalDirection $ vdirection v1 of+ RIGHTWARDS -> trail_right leg <> orthoCatTrail mid h 0+ _ -> trail_left leg <> orthoCatTrail (-mid) h 0+++trail_vdiag :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u+trail_vdiag leg v1 = + let w = vector_x v1+ mid = (abs $ vector_y v1) - leg+ in case verticalDirection $ vdirection v1 of+ UPWARDS -> trail_up leg <> orthoCatTrail w mid 0+ _ -> trail_down leg <> orthoCatTrail w (-mid) 0++++-- | Horizontal-diagonal-horizontal trail.+--+-- > --@+-- > /+-- > o--+-- +--+trail_hdiagh :: (Real u, Floating u) => u -> u -> Vec2 u -> CatTrail u+trail_hdiagh legl legr v1 = + let h = vector_y v1+ mid = (abs $ vector_x v1) - (legl + legr)+ in case horizontalDirection $ vdirection v1 of+ RIGHTWARDS -> mconcat [ trail_right legl+ , orthoCatTrail mid h 0+ , trail_right legr+ ] + _ -> mconcat [ trail_left legl+ , orthoCatTrail (-mid) h 0+ , trail_left legr+ ] ++++trail_vdiagv :: (Real u, Floating u) => u -> u -> Vec2 u -> CatTrail u+trail_vdiagv legl legr v1 = + let w = vector_x v1+ mid = (abs $ vector_y v1) - (legl + legr)+ in case verticalDirection $ vdirection v1 of+ UPWARDS -> mconcat [ trail_up legl+ , orthoCatTrail w mid 0+ , trail_up legr+ ] + _ -> mconcat [ trail_down legl+ , orthoCatTrail w (-mid) 0+ , trail_down legr+ ] ++-- | Uniform leg size.+--+trail_perp_bar :: (Real u, Floating u) + => ClockDirection -> u -> Vec2 u -> CatTrail u+trail_perp_bar CW h v1 = trail_perp_barCW h v1+trail_perp_bar _ h v1 = trail_perp_barCW (-h) v1+++trail_perp_barCW :: (Real u, Floating u) => u -> Vec2 u -> CatTrail u+trail_perp_barCW h v1 = + trail_theta_up h ang <> catline v1 <> trail_theta_down h ang+ where+ ang = vdirection v1+++-- | Bar connector - independent leg size, legs perpendicular.+--+-- +-- > o @ +-- > | |+-- > '----' +--+-- The bar is drawn /below/ the points.+--+trail_perp_bar2 :: (Real u, Floating u) + => ClockDirection -> u -> u -> Vec2 u -> CatTrail u+trail_perp_bar2 CW h1 h2 v1 = trail_perp_barCW2 h1 h2 v1+trail_perp_bar2 _ h1 h2 v1 = trail_perp_barCW2 (-h1) (-h2) v1+++trail_perp_barCW2 :: (Real u, Floating u) => u -> u -> Vec2 u -> CatTrail u+trail_perp_barCW2 h1 h2 v1 = + trail_theta_up h1 ang + <> orthoCatTrail (vlength v1) (negate $ h1 - h2) ang+ <> trail_theta_down h2 ang+ where+ ang = vdirection v1+++-- | Independent leg size.+--+trail_vflam :: (Real u, Floating u) + => ClockDirection -> u -> u -> Vec2 u -> CatTrail u+trail_vflam CW h1 h2 v1 = trail_vflamCW h1 h2 v1+trail_vflam _ h1 h2 v1 = trail_vflamCW (-h1) (-h2) v1+++trail_vflamCW :: (Real u, Floating u) => u -> u -> Vec2 u -> CatTrail u+trail_vflamCW h1 h2 v1 = + diffLines [ p0, p0 .+^ vvec h1, p1 .+^ vvec h2, p1 ]+ where+ p0 = zeroPt+ p1 = p0 .+^ v1+++-- | Height is minimum leg height. Ortho bar is horizontal.+--+trail_ortho_hbar :: (Real u, Floating u) + => ClockDirection -> u -> Vec2 u -> CatTrail u+trail_ortho_hbar CW h v1 = trail_ortho_hbarCW h v1+trail_ortho_hbar _ h v1 = trail_ortho_hbarCCW h v1+++trail_ortho_hbarCW :: (Real u, Floating u) + => u -> Vec2 u -> CatTrail u+trail_ortho_hbarCW ymin v1@(V2 x y) = case quadrant $ vdirection v1 of+ QUAD_NE -> trail_up ymaj <> trail_right x <> trail_down ymin+ QUAD_SE -> trail_up ymin <> trail_right x <> trail_down ymaj+ QUAD_NW -> trail_down ymin <> trail_left (abs x) <> trail_up ymaj+ QUAD_SW -> trail_down ymaj <> trail_left (abs x) <> trail_up ymin+ where+ ymaj = ymin + abs y+++++trail_ortho_hbarCCW :: (Real u, Floating u) + => u -> Vec2 u -> CatTrail u+trail_ortho_hbarCCW ymin v1@(V2 x y) = case quadrant $ vdirection v1 of+ QUAD_NE -> trail_down ymin <> trail_right x <> trail_up ymaj+ QUAD_SE -> trail_down ymaj <> trail_right x <> trail_up ymin+ QUAD_NW -> trail_up ymaj <> trail_left (abs x) <> trail_down ymin+ QUAD_SW -> trail_up ymin <> trail_left (abs x) <> trail_down ymaj+ where+ ymaj = ymin + abs y+++++-- | Width is minimum leg width. Ortho bar is vertical.+--+trail_ortho_vbar :: (Real u, Floating u) + => ClockDirection -> u -> Vec2 u -> CatTrail u+trail_ortho_vbar CW w v1 = trail_ortho_vbarCW w v1+trail_ortho_vbar _ w v1 = trail_ortho_vbarCCW w v1+++trail_ortho_vbarCW :: (Real u, Floating u) + => u -> Vec2 u -> CatTrail u+trail_ortho_vbarCW xmin v1@(V2 x y) = case quadrant $ vdirection v1 of+ QUAD_NE -> trail_left xmin <> trail_up y <> trail_right xmaj+ QUAD_NW -> trail_left xmaj <> trail_up y <> trail_right xmin+ QUAD_SE -> trail_right xmaj <> trail_down (abs y) <> trail_left xmin+ QUAD_SW -> trail_right xmin <> trail_down (abs y) <> trail_left xmaj+ where+ xmaj = xmin + abs x++++trail_ortho_vbarCCW :: (Real u, Floating u) + => u -> Vec2 u -> CatTrail u+trail_ortho_vbarCCW xmin v1@(V2 x y) = case quadrant $ vdirection v1 of+ QUAD_NE -> trail_right xmaj <> trail_up y <> trail_left xmin+ QUAD_NW -> trail_right xmin <> trail_up y <> trail_left xmaj+ QUAD_SE -> trail_left xmin <> trail_down (abs y) <> trail_right xmaj+ QUAD_SW -> trail_left xmaj <> trail_down (abs y) <> trail_right xmin+ where+ xmaj = xmin + abs x+++trail_hright :: Num u => Vec2 u -> CatTrail u+trail_hright (V2 x y) = trail_right x <> trail_up y+++trail_vright :: Num u => Vec2 u -> CatTrail u+trail_vright (V2 x y) = trail_up y <> trail_right x++trail_hrr :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u+trail_hrr x1 (V2 x y) = + trail_theta_right x1 ang + <> trail_theta_up y ang + <> trail_theta_right (abs x - x1) ang+ where+ ang = if x < 0 then pi else 0++trail_vrr :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u+trail_vrr y1 (V2 x y) = + trail_theta_up y1 ang + <> trail_theta_right x ang + <> trail_theta_up (abs y - y1) ang+ where+ ang = if y < 0 then pi else 0+++trail_rrh :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u+trail_rrh x1 (V2 x y) = + trail_theta_right (abs x - x1) ang + <> trail_theta_up y ang + <> trail_theta_right x1 ang+ where+ ang = if x < 0 then pi else 0++trail_rrv :: (Floating u, Ord u) => u -> Vec2 u -> CatTrail u+trail_rrv y1 (V2 x y) = + trail_theta_up (abs y - y1) ang + <> trail_theta_right x ang + <> trail_theta_up y1 ang+ where+ ang = if y < 0 then pi else 0+++trail_rect_loop :: (Real u, Floating u) + => ClockDirection -> u -> u -> u -> Vec2 u -> CatTrail u+trail_rect_loop CW = trail_rect_loopCW+trail_rect_loop _ = trail_rect_loopCCW++trail_rect_loopCW :: (Real u, Floating u) + => u -> u -> u -> Vec2 u -> CatTrail u+trail_rect_loopCW extl extr h v1 = + trail_theta_left extl ang+ <> trail_theta_up h ang+ <> trail_theta_right (len + extl + extr) ang+ <> trail_theta_down h ang+ <> trail_theta_left extr ang+ where+ ang = vdirection v1+ len = vlength v1++trail_rect_loopCCW :: (Real u, Floating u)+ => u -> u -> u -> Vec2 u -> CatTrail u+trail_rect_loopCCW extl extr h v1 = + trail_theta_left extl ang+ <> trail_theta_down h ang+ <> trail_theta_right (len + extl + extr) ang+ <> trail_theta_up h ang+ <> trail_theta_left extr ang+ where+ ang = vdirection v1+ len = vlength v1+++-- | 'triCurve' formulated with a /base vector/ rather than +-- base-width and angle of inclination.+--+vtriCurve :: (Real u, Floating u) + => ClockDirection -> u -> Vec2 u -> CatTrail u +vtriCurve clk h v1 = triCurve clk (vlength v1) h (vdirection v1)+ ++-- | 'rectCurve' formulated with a /base vector/ rather than +-- base-width and angle of inclination.+--+vrectCurve :: (Real u, Floating u) + => ClockDirection -> u -> Vec2 u -> CatTrail u+vrectCurve clk h v1 = rectCurve clk (vlength v1) h (vdirection v1)+++-- | 'trapCurve' formulated with a /base vector/ rather than +-- base-width and angle of inclination.+--+vtrapCurve :: (Real u, Floating u)+ => ClockDirection -> u -> Radian -> Vec2 u -> CatTrail u+vtrapCurve clk h interior_ang v1 = + trapCurve clk (vlength v1) h interior_ang (vdirection v1)+++-- | 'bowCurve' formulated with a /base vector/ rather than +-- base-width and angle of inclination.+--+vbowCurve :: (Real u, Floating u)+ => ClockDirection -> u -> Vec2 u -> CatTrail u+vbowCurve clk h v1 = bowCurve clk (vlength v1) h (vdirection v1) ++-- | 'wedgeCurve' formulated with a /base vector/ rather than +-- base-width and angle of inclination.+--+vwedgeCurve :: (Real u, Floating u)+ => ClockDirection -> u -> Vec2 u -> CatTrail u+vwedgeCurve clk h v1 = wedgeCurve clk (vlength v1) h (vdirection v1) +
+ src/Wumpus/Drawing/Basis/ShapeTrails.hs view
@@ -0,0 +1,213 @@+{-# OPTIONS -Wall #-}+++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Basis.ShapeTrails+-- Copyright : (c) Stephen Tetley 2011-2012+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Basis.ShapeTrails+ (++ circle_trail+ , rcircle_trail++ , ellipse_trail+ , rellipse_trail++ , rectangle_trail+ , rrectangle_trail++ , diamond_trail+ , rdiamond_trail++ , isosceles_triangle_trail+ , risosceles_triangle_trail++ , semicircle_trail+ , rsemicircle_trail++ , semiellipse_trail+ , rsemiellipse_trail++ , parallelogram_trail+ , rparallelogram_trail++ , trapezium_trail+ , rtrapezium_trail++ )++ where++import Wumpus.Drawing.Basis.InclineTrails++import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core++-- import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++import Data.Monoid+++-- Shapes...++circle_trail :: (Real u, Floating u) => u -> AnaTrail u+circle_trail r = rcircle_trail r 0++rcircle_trail :: (Real u, Floating u) => u -> Radian -> AnaTrail u+rcircle_trail r ang = + modifyAna (\v -> v ^-^ avec ang r) $ incline_circle $ avec ang (2 * r)++++ellipse_trail :: (Real u, Floating u) => u -> u -> AnaTrail u+ellipse_trail rx ry = rellipse_trail rx ry 0++rellipse_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u+rellipse_trail rx ry ang = + modifyAna (\v -> v ^-^ avec ang rx) $ incline_ellipse ry $ avec ang (2 * rx)+++rectangle_trail :: (Real u, Floating u) => u -> u -> AnaTrail u+rectangle_trail w h = rrectangle_trail w h 0+++rrectangle_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u+rrectangle_trail w h ang = + anaCatTrail (orthoVec (negate $ 0.5 * w) (negate $ 0.5 * h) ang) catt+ where+ catt = mconcat [ trail_theta_right w ang+ , trail_theta_up h ang + , trail_theta_left w ang + , trail_theta_down h ang + ]+++diamond_trail :: (Real u, Floating u) => u -> u -> AnaTrail u+diamond_trail w h = rdiamond_trail w h 0 ++rdiamond_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u+rdiamond_trail w h ang = + anaCatTrail (theta_right hw ang) catt+ where+ hw = 0.5 * w+ hh = 0.5 * h+ catt = mconcat [ orthoCatTrail (-hw) hh ang+ , orthoCatTrail (-hw) (-hh) ang + , orthoCatTrail hw (-hh) ang + , orthoCatTrail hw hh ang + ]+++isosceles_triangle_trail :: (Real u, Floating u) => u -> u -> AnaTrail u+isosceles_triangle_trail bw h = risosceles_triangle_trail bw h 0 ++-- | Drawn at the centroid (1/3 * h).+--+risosceles_triangle_trail :: (Real u, Floating u) + => u -> u -> Radian -> AnaTrail u+risosceles_triangle_trail bw h ang = + anaCatTrail (orthoVec (negate hbw) (negate $ h / 3) ang) catt+ where+ hbw = 0.5 * bw+ catt = mconcat [ trail_theta_right bw ang+ , orthoCatTrail (-hbw) h ang+ , orthoCatTrail (-hbw) (-h) ang+ ]+++semicircle_trail :: (Real u, Floating u) => u -> AnaTrail u+semicircle_trail r = rsemicircle_trail r 0++rsemicircle_trail :: (Real u, Floating u) => u -> Radian -> AnaTrail u+rsemicircle_trail r ang = + anaCatTrail (orthoVec (negate r) (negate hminor) ang) catt+ where+ -- hminor is the centroid formula for semicircle+ hminor = (4 * r) / (3 * pi)+ catt = trail_theta_right (2 * r) ang+ <> semicircleTrail CCW (avec ang (negate $ 2 * r) )++++semiellipse_trail :: (Real u, Floating u) => u -> u -> AnaTrail u+semiellipse_trail rx ry = rsemiellipse_trail rx ry 0++rsemiellipse_trail :: (Real u, Floating u) => u -> u -> Radian -> AnaTrail u+rsemiellipse_trail rx ry ang = + anaCatTrail (orthoVec (negate rx) (negate hminor) ang) catt+ where+ -- hminor is the centroid formula for semiellipse+ hminor = (4 * ry) / (3 * pi)+ catt = trail_theta_right (2 * rx) ang+ <> semiellipseTrail CCW ry (avec ang (negate $ 2 * rx) )++-- | Note - bottom left angle must be smaller than 180deg, +-- otherwise a runtime error is thrown.+--+parallelogram_trail :: Floating u => u -> u -> Radian -> AnaTrail u+parallelogram_trail w h bottom_left_ang = + rparallelogram_trail w h bottom_left_ang 0++-- | Note - bottom left angle must be smaller than 180deg, +-- otherwise a runtime error is thrown.+--+rparallelogram_trail :: Floating u => u -> u -> Radian -> Radian -> AnaTrail u+rparallelogram_trail w h bl_ang ang+ | bl_ang >= ang180 = + error "rparallelogram_trail - bottom left angle >= 180."+ | otherwise = anaCatTrail ctr_to_bl catt+ where+ -- Note - base_minor is negative for angles > 90+ base_minor = h / (fromRadian $ tan bl_ang)+ + vbase = theta_right w ang+ vrhs = orthoVec base_minor h ang+ vtop = vreverse vbase+ vlhs = vreverse vrhs+ ctr_to_bl = vreverse $ 0.5 *^ (vbase ^+^ vrhs)+ catt = mconcat $ map catline [ vbase, vrhs, vtop, vlhs ]+++-- | Note - bottom left angle must be smaller than 180deg, +-- otherwise a runtime error is thrown.+--+-- Also, no checking is perfomed on the relation between height+-- and bottom_left ang. Out of range values will draw \"twisted\"+-- trapezoids.+-- +trapezium_trail :: Floating u => u -> u -> Radian -> AnaTrail u+trapezium_trail w h bottom_left_ang = + rtrapezium_trail w h bottom_left_ang 0+++-- | Note - bottom left angle must be smaller than 180deg, +-- otherwise a runtime error is thrown.+--+rtrapezium_trail :: Floating u => u -> u -> Radian -> Radian -> AnaTrail u+rtrapezium_trail bw h bl_ang ang + | bl_ang >= ang180 = error "rtrapezium_trail - bottom left angle >= 180."+ | otherwise = anaCatTrail ctr_to_bl catt+ where+ -- Note - base_minor is negative for angles > 90+ base_minor = h / (fromRadian $ tan bl_ang)+ top_width = bw - (2 * base_minor)+ vbase = theta_right bw ang+ vrhs = orthoVec (-base_minor) h ang+ vtop = theta_left top_width ang+ vlhs = orthoVec (-base_minor) (-h) ang+ ctr_to_bl = orthoVec (negate $ 0.5 * bw) (negate $ 0.5 * h) ang+ catt = mconcat $ map catline [ vbase, vrhs, vtop, vlhs ]++
src/Wumpus/Drawing/Basis/Symbols.hs view
@@ -21,17 +21,35 @@ module Wumpus.Drawing.Basis.Symbols ( - ocircle+ scircle+ , fcircle+ , fscircle+ + , ssquare+ , fsquare+ , fssquare++ , sleft_slice+ , fleft_slice+ , fsleft_slice++ , sright_slice+ , fright_slice+ , fsright_slice++ , sleft_triangle+ , fleft_triangle+ , fsleft_triangle++ , sright_triangle+ , fright_triangle+ , fsright_triangle+ , ochar , ocharUpright , ocharDescender , ocurrency- , left_slice- , right_slice - , left_triangle- , right_triangle- , empty_box , hbar@@ -50,6 +68,8 @@ -- import Data.AffineSpace -- package: vector-space +import Data.Monoid+ -- -- DESIGN NOTE --@@ -57,33 +77,251 @@ -- /data scheme/ (underscore_separators). -- -- Objects here are functions as they take size param, but they--- expected to be redefined elsewhere at fixed size and not used --- in /user code/. +-- expected to be redefined elsewhere (possibly at fixed size) +-- with the re-definitions used in /user code/ rather than these +-- primitives. -- -- Using camelCase here, then under_score in the DocText versions -- adds double the function signatures to the Haddock docs. --+-- Also - should the names encode start pos, or can all start +-- positions be center?+-- +--+-- TikZ uses o to indicated /circled/.+--+-- Using o as a prefix for /open/ i.e. stroked has the problem +-- that there aren\'t any other characters ideographic for filled+-- or filled stroked.+-- +-- scircle+-- fcircle+-- fscircle -ocircle :: InterpretUnit u => u -> LocGraphic u-ocircle radius = dcDisk DRAW_STROKE radius ++-- | Stroked circle.+-- +-- Start pos - center.+--+scircle :: InterpretUnit u => u -> LocGraphic u+scircle radius = dcDisk DRAW_STROKE radius++-- | Filled circle.+-- +-- Start pos - center.+--+fcircle :: InterpretUnit u => u -> LocGraphic u+fcircle radius = dcDisk DRAW_FILL radius++-- | Filled-stroked circle.+-- +-- Start pos - center.+--+fscircle :: InterpretUnit u => u -> LocGraphic u+fscircle radius = dcDisk DRAW_FILL_STROKE radius+++++-- | Stroked square.+-- +-- Start pos - center.+--+ssquare :: (Fractional u, InterpretUnit u) => u -> LocGraphic u+ssquare w = renderAnaTrail CSTROKE $ rectangleTrail w w +++-- | Filled square.+-- +-- Start pos - center.+--+fsquare :: (Fractional u, InterpretUnit u) => u -> LocGraphic u+fsquare w = renderAnaTrail CFILL $ rectangleTrail w w +++-- | Filled-stroked square.+-- +-- Start pos - center.+--+fssquare :: (Fractional u, InterpretUnit u) => u -> LocGraphic u+fssquare w = renderAnaTrail CFILL_STROKE $ rectangleTrail w w ++++-- | Implementation.+--+lslice :: (Real u, Floating u, InterpretUnit u) + => DrawMode -> u -> LocGraphic u+lslice mode radius = moveStart (go_left $ 0.5 * radius) lwedge+ where+ lwedge = supplyIncline 0 $ wedge mode radius quarter_pi++-- | Stroked left slice (wedge).+-- +-- Start pos - ....+--+sleft_slice :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+sleft_slice = lslice DRAW_STROKE+++-- | Filled left slice (wedge).+-- +-- Start pos - ....+--+fleft_slice :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fleft_slice = lslice DRAW_FILL+++-- | Filled-stroked left slice (wedge).+-- +-- Start pos - ....+--+fsleft_slice :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fsleft_slice = lslice DRAW_FILL_STROKE++++-- | Implementation.+--+rslice :: (Real u, Floating u, InterpretUnit u) + => DrawMode -> u -> LocGraphic u+rslice mode radius = moveStart (go_right $ 0.5 * radius) rwedge+ where+ rwedge = supplyIncline pi $ wedge mode radius quarter_pi+++-- | Stroked right slice (wedge).+-- +-- Start pos - ....+--+sright_slice :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+sright_slice = rslice DRAW_STROKE+++-- | Filled right slice (wedge).+-- +-- Start pos - ....+--+fright_slice :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fright_slice = rslice DRAW_FILL+++-- | Filled-stroked right slice (wedge).+-- +-- Start pos - ....+--+fsright_slice :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fsright_slice = rslice DRAW_FILL_STROKE++++-- | Implementation.+--+left_tri :: (Fractional u, InterpretUnit u) + => PathMode -> u -> LocGraphic u+left_tri mode w = + renderAnaTrail mode $ anaCatTrail (go_left $ 0.5 * w)+ $ line_r <> vbase <> line_l+ where+ hh = 0.40 * w+ line_r = catline $ vec w hh+ vbase = catline $ go_down $ 2*hh+ line_l = catline $ vec (-w) hh+++-- | Stroked left triangle.+-- +-- Start pos - ....+--+sleft_triangle :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+sleft_triangle = left_tri CSTROKE+++-- | Filled left triangle.+-- +-- Start pos - ....+--+fleft_triangle :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fleft_triangle = left_tri CFILL+++-- | Filled-stroked left triangle.+-- +-- Start pos - ....+--+fsleft_triangle :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fsleft_triangle = left_tri CFILL_STROKE+++-- | Implementation+--+right_tri :: (Fractional u, InterpretUnit u) + => PathMode -> u -> LocGraphic u+right_tri mode w = + renderAnaTrail mode $ anaCatTrail (go_right $ 0.5 * w)+ $ line_l <> vbase <> line_r+ where+ hh = 0.40 * w+ line_l = catline $ vec (-w) hh+ vbase = catline $ go_down $ 2*hh+ line_r = catline $ vec w hh+++-- | Stroked right triangle.+-- +-- Start pos - ....+--+sright_triangle :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+sright_triangle = right_tri CSTROKE+++-- | Filled right triangle.+-- +-- Start pos - ....+--+fright_triangle :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fright_triangle = right_tri CFILL+++-- | Filled-stroked right triangle.+-- +-- Start pos - ....+--+fsright_triangle :: (Real u, Floating u, InterpretUnit u) + => u -> LocGraphic u+fsright_triangle = right_tri CFILL_STROKE+++ -- | Note this looks horrible for chars with descenders. -- ochar :: (Fractional u, InterpretUnit u) - => EscapedChar -> LocGraphic u+ => EscapedChar -> LocGraphic u ochar esc = char1 <> circ1 where char1 = runPosObject CENTER $ posEscChar esc- circ1 = localize (set_line_width 0.75) $ capHeight >>= \h -> ocircle (0.85 * h)+ circ1 = localize (set_line_width 0.75) $ capHeight >>= \h -> scircle (0.85 * h) ocharUpright :: (Fractional u, InterpretUnit u) => EscapedChar -> LocGraphic u ocharUpright esc = char1 <> circ1 where char1 = runPosObject CENTER $ posEscCharUpright esc- circ1 = localize (set_line_width 0.75) $ capHeight >>= \h -> ocircle (0.85 * h)+ circ1 = localize (set_line_width 0.75) $ capHeight >>= \h -> scircle (0.85 * h) ocharDescender :: (Fractional u, InterpretUnit u) => EscapedChar -> LocGraphic u@@ -91,12 +329,12 @@ where char1 = fmap abs descender >>= \dy -> moveStart (go_up dy) $ runPosObject CENTER $ posEscCharUpright esc- circ1 = localize (set_line_width 0.75) $ capHeight >>= \h -> ocircle (0.85 * h)+ circ1 = localize (set_line_width 0.75) $ capHeight >>= \h -> scircle (0.85 * h) ocurrency :: (Floating u, InterpretUnit u) => u -> LocGraphic u -ocurrency ra = ocircle ra <> lne <> lnw <> lsw <> lse+ocurrency ra = scircle ra <> lne <> lnw <> lsw <> lse where ra3 = 0.33 * ra lne = moveStart (go_north_east ra) $ locStraightLine $ go_north_east ra3@@ -104,52 +342,18 @@ lsw = moveStart (go_south_west ra) $ locStraightLine $ go_south_west ra3 lse = moveStart (go_south_east ra) $ locStraightLine $ go_south_east ra3 -left_slice :: (Real u, Floating u, InterpretUnit u) - => u -> LocGraphic u-left_slice radius = moveStart (go_left $ 0.5 * radius) lwedge- where- lwedge = supplyIncline 0 $ wedge DRAW_STROKE radius quarter_pi -right_slice :: (Real u, Floating u, InterpretUnit u) - => u -> LocGraphic u-right_slice radius = moveStart (go_right $ 0.5 * radius) rwedge- where- rwedge = supplyIncline pi $ wedge DRAW_STROKE radius quarter_pi--left_triangle :: (Fractional u, InterpretUnit u) - => u -> LocGraphic u-left_triangle w = - drawPlacedTrail CSTROKE $ placeCatTrail (go_left $ 0.5 * w)- $ line_r <> vbase <> line_l- where- hh = 0.40 * w- line_r = catline $ vec w hh- vbase = catline $ go_down $ 2*hh- line_l = catline $ vec (-w) hh--right_triangle :: (Fractional u, InterpretUnit u) - => u -> LocGraphic u-right_triangle w = - drawPlacedTrail CSTROKE $ placeCatTrail (go_right $ 0.5 * w)- $ line_l <> vbase <> line_r- where- hh = 0.40 * w- line_l = catline $ vec (-w) hh- vbase = catline $ go_down $ 2*hh- line_r = catline $ vec w hh-- empty_box :: (Fractional u, InterpretUnit u) => u -> LocGraphic u-empty_box w = drawPlacedTrail CSTROKE $ rectangleTrail w w+empty_box w = renderAnaTrail CSTROKE $ rectangleTrail w w hbar :: (Fractional u, InterpretUnit u) => u -> LocGraphic u hbar u = - drawPlacedTrail OSTROKE $ placeCatTrail (go_left $ 0.5 * u) $ trail_right u+ renderAnaTrail OSTROKE $ anaCatTrail (go_left $ 0.5 * u) $ trail_right u vbar :: (Fractional u, InterpretUnit u) => u -> LocGraphic u vbar u = - drawPlacedTrail OSTROKE $ placeCatTrail (go_down $ 0.5 * u) $ trail_up u+ renderAnaTrail OSTROKE $ anaCatTrail (go_down $ 0.5 * u) $ trail_up u dbl_hbar :: (Fractional u, InterpretUnit u) => u -> LocGraphic u dbl_hbar u = line1 <> line2
src/Wumpus/Drawing/Connectors.hs view
@@ -20,12 +20,10 @@ ( module Wumpus.Drawing.Connectors.Arrowheads , module Wumpus.Drawing.Connectors.Base- , module Wumpus.Drawing.Connectors.BoxConnectors , module Wumpus.Drawing.Connectors.ConnectorProps ) where import Wumpus.Drawing.Connectors.Arrowheads import Wumpus.Drawing.Connectors.Base-import Wumpus.Drawing.Connectors.BoxConnectors import Wumpus.Drawing.Connectors.ConnectorProps
src/Wumpus/Drawing/Connectors/Arrowheads.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Connectors.Arrowheads--- Copyright : (c) Stephen Tetley 2011+-- Copyright : (c) Stephen Tetley 2011-2012 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>@@ -12,6 +12,8 @@ -- -- Arrowheads. --+-- \*\* WARNING \*\* - naming scheme due to change.+-- -------------------------------------------------------------------------------- module Wumpus.Drawing.Connectors.Arrowheads@@ -59,104 +61,86 @@ ) where -import Wumpus.Drawing.Basis.DrawingPrimitives+import Wumpus.Drawing.Basis.InclineTrails import Wumpus.Drawing.Connectors.Base import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace -- package: vector-space+-- import Data.AffineSpace -- package: vector-space import Data.VectorSpace +import Data.Monoid --- | Arrow tips are drawn with a sloid line even if the connector++++-- | Arrow tips are drawn with a solid line even if the connector -- line is dashed (tips also override round corners) solid_stroke_tip :: DrawingContextF-solid_stroke_tip = reset_drawing_metrics+solid_stroke_tip = solid_line -- reset_drawing_metrics -type PointGen = Radian -> [Vec2 En] +type TrailGen = Radian -> AnaTrail En -filledTipPath :: PointGen -> LocThetaGraphic En-filledTipPath gen = - localize fill_use_stroke_colour $ promoteLocTheta $ \pt theta ->- cStraightLines DRAW_FILL $ map (pt .+^) $ gen theta +fillTrailTip :: TrailGen -> LocThetaGraphic En+fillTrailTip gen_pt = + localize fill_use_stroke_colour $ promoteLocTheta $ \pt theta ->+ supplyLoc pt $ renderAnaTrail CFILL $ gen_pt theta -closedTipPath :: PointGen -> LocThetaGraphic En-closedTipPath gen = +closedTrailTip :: TrailGen -> LocThetaGraphic En+closedTrailTip gen_pt = localize solid_stroke_tip $ promoteLocTheta $ \pt theta ->- cStraightLines DRAW_STROKE $ map (pt .+^) $ gen theta+ supplyLoc pt $ renderAnaTrail CSTROKE $ gen_pt theta -openTipPath :: PointGen -> LocThetaGraphic En-openTipPath gen = +openTrailTip :: TrailGen -> LocThetaGraphic En+openTrailTip gen_pt = localize solid_stroke_tip $ promoteLocTheta $ \pt theta ->- oStraightLines $ map (pt .+^) $ gen theta+ supplyLoc pt $ renderAnaTrail OSTROKE $ gen_pt theta --- | Return @o-a@ and @o-b@:------ > a--- > .\--- > . \--- > .....o--- > . /--- > ./--- > b----tripointsFromTip :: En -> Radian -> (Radian -> (Vec2 En, Vec2 En))-tripointsFromTip baselen ang = \theta -> - (avec (theta + au) hyp, avec (theta + ad) hyp)- where- half_ang = 0.5 * ang - au = pi - half_ang- ad = half_ang + pi- hyp = baselen / (fromRadian $ cos half_ang) ---- | Return @o-x@ and @o-a@ and @o-b@:------ > a--- > /.--- > / .--- > .. x..o--- > \ .--- > \.--- > b+-- | All three lines are stated. ---revTripointsFromTip :: En -> Radian -> (Radian -> (Vec2 En, Vec2 En, Vec2 En))-revTripointsFromTip baselen ang = \theta -> - (avec theta (-baselen), oa theta, ob theta)- where- half_ang = 0.5 * ang - half_height = baselen * (fromRadian $ tan half_ang)- oa = \theta -> avec (theta + ang90) half_height- ob = \theta -> avec (theta - ang90) half_height---+closedTriTrail :: Radian -> TrailGen+closedTriTrail ang = \theta ->+ modifyAna (\v1 -> v1 ^+^ theta_left 1 theta) $+ incline_triangle ang (avec theta 1) filledTri :: Radian -> ArrowTip filledTri ang = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = filledTipPath spec+ , tip_deco = fillTrailTip $ closedTriTrail ang }- where- spec theta = let (v1,v2) = tripointsFromTip 1 ang theta - in [zeroVec, v1, v2] +--+-- DESIGN NOTE +--+-- Naming scheme should change.+--+-- The \"wumpus way\" of naming seems to be coalescing to favour +-- underscore separated names rather than camelCase for /data/ +-- objects. +--+-- These data objects can still be functions but they are +-- distinguished by drawing differently - roughly speaking+-- the difference between a barb tip and a triangle tip is +-- \"what they draw not what they mean\".+--+ -- | Filled triangle - apex is 90 deg. -- tri90 :: ArrowTip@@ -176,13 +160,10 @@ strokedClosedTri :: Radian -> ArrowTip strokedClosedTri ang = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = closedTipPath spec+ , tip_deco = closedTrailTip $ closedTriTrail ang }- where- spec theta = let (v1,v2) = tripointsFromTip 1 ang theta - in [zeroVec, v1, v2] otri90 :: ArrowTip@@ -195,17 +176,21 @@ otri45 = strokedClosedTri ang45 +-- | All three lines are stated.+--+revClosedTriSpec :: Radian -> TrailGen+revClosedTriSpec ang = \theta -> incline_triangle ang (avec theta (-1))++ filledRevTri :: Radian -> ArrowTip filledRevTri ang = ArrowTip- { retract_distance = const 1+ { retract_distance = 0.5 , tip_half_len = 0.5- , tip_deco = filledTipPath spec+ , tip_deco = fillTrailTip $ revClosedTriSpec ang }- where- spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta - in [v0, v1, v2] + revtri90 :: ArrowTip revtri90 = filledRevTri ang90 @@ -219,15 +204,11 @@ strokedClosedRevTri :: Radian -> ArrowTip strokedClosedRevTri ang = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = closedTipPath spec+ , tip_deco = closedTrailTip $ revClosedTriSpec ang }- where- spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta - in [v0, v1, v2] - orevtri90 :: ArrowTip orevtri90 = strokedClosedRevTri ang90 @@ -238,19 +219,19 @@ orevtri45 = strokedClosedRevTri ang45 +barbSpec :: Radian -> TrailGen+barbSpec ang = \theta -> + modifyAna (\v1 -> v1 ^+^ avec theta (-1)) $ incline_barb ang (avec theta 1) + strokedBarb :: Radian -> ArrowTip strokedBarb ang = ArrowTip- { retract_distance = const 0+ { retract_distance = 0 , tip_half_len = 0.5- , tip_deco = openTipPath spec+ , tip_deco = openTrailTip $ barbSpec ang }- where- spec theta = let (v1,v2) = tripointsFromTip 1 ang theta - in [v1,zeroVec,v2] - barb90 :: ArrowTip barb90 = strokedBarb ang90 @@ -261,17 +242,18 @@ barb45 = strokedBarb ang45 +revBarbSpec :: Radian -> TrailGen+revBarbSpec ang = \theta -> incline_barb ang (avec theta (-1))+ strokedRevBarb :: Radian -> ArrowTip strokedRevBarb ang = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = openTipPath spec+ , tip_deco = openTrailTip $ revBarbSpec ang }- where- spec theta = let (v0,v1,v2) = revTripointsFromTip 1 ang theta - in [v1,v0,v2] + revbarb90 :: ArrowTip revbarb90 = strokedRevBarb ang90 @@ -282,98 +264,87 @@ revbarb45 = strokedRevBarb ang45 +perpSpec :: TrailGen+perpSpec ang = + anaCatTrail (theta_up 0.5 ang) $ trail_theta_down 1 ang perp :: ArrowTip perp = ArrowTip- { retract_distance = const 0+ { retract_distance = 0 , tip_half_len = 0- , tip_deco = openTipPath spec+ , tip_deco = openTrailTip perpSpec }+++bracketSpec :: TrailGen+bracketSpec ang = anaCatTrail (orthoVec (-0.5) 0.5 ang) catt where- spec theta = let oa = avec (theta + ang90) 0.5- ob = avec (theta - ang90) 0.5- in [oa, ob]+ catt = mconcat [ trail_theta_right 0.5 ang+ , trail_theta_down 1.0 ang+ , trail_theta_left 0.5 ang + ] bracket :: ArrowTip bracket = ArrowTip- { retract_distance = const 0+ { retract_distance = 0.0 , tip_half_len = 0.5- , tip_deco = openTipPath spec+ , tip_deco = openTrailTip bracketSpec }- where- spec theta = let oa = avec (theta + ang90) 0.5- ob = avec (theta - ang90) 0.5- dv = avec theta (-0.5)- in [ oa ^+^ dv, oa, ob, ob ^+^ dv ] -+diskBody :: DrawMode -> Radian -> LocGraphic En+diskBody mode theta = + localize fill_use_stroke_colour $ moveStart vback $ dcDisk mode 0.5+ where+ vback = theta_left 0.5 theta diskTip :: ArrowTip diskTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 0.5 , tip_half_len = 0.5- , tip_deco = promoteLocTheta $ \pt theta -> body theta `at` pt+ , tip_deco = promoteLocTheta $ \pt theta -> + diskBody DRAW_FILL theta `at` pt }- where- body :: Radian -> LocGraphic En- body theta = let v1 = avec theta (-0.5)- in localize fill_use_stroke_colour $ - moveStart v1 (dcDisk DRAW_FILL 0.5) odiskTip :: ArrowTip odiskTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = promoteLocTheta $ \pt theta -> body theta `at` pt+ , tip_deco = promoteLocTheta $ \pt theta -> + diskBody DRAW_STROKE theta `at` pt }- where- body :: Radian -> LocGraphic En- body theta = let v1 = avec theta (-0.5)- in localize solid_stroke_tip $ - moveStart v1 (dcDisk DRAW_STROKE 0.5) --- | squareSpec:------ > --- > ,-----a--- > | |--- > ...v.....o--- > | | --- > `-----b+-- | Note - need to draw square East-West rather than West-East+-- hence the base_width is negative. ---squareSpec :: PointGen-squareSpec theta = [ oa ^+^ ov, oa, ob, ob ^+^ ov ]- where- oa = avec (theta + ang90) 0.5- ob = avec (theta - ang90) 0.5- ov = avec theta (-1)- +squareSpec :: TrailGen+squareSpec theta = incline_square $ avec theta (-1) + squareTip :: ArrowTip squareTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = filledTipPath squareSpec+ , tip_deco = fillTrailTip squareSpec }+ osquareTip :: ArrowTip osquareTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = closedTipPath squareSpec+ , tip_deco = closedTrailTip squareSpec } - -- | squareSpec: -- -- > @@ -383,52 +354,46 @@ -- > \ / -- > b ---diamondSpec :: En -> PointGen-diamondSpec width theta = [ ow, oa, zeroVec, ob ]- where- ow = avec theta (-width)- ov = avec theta (negate $ 0.5 * width)- oa = ov ^+^ avec (theta + ang90) 0.5- ob = ov ^+^ avec (theta - ang90) 0.5-+diamondSpec :: En -> TrailGen+diamondSpec w theta = incline_diamond 1 $ avec theta (-w) diamondTip :: ArrowTip diamondTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 0.5 , tip_half_len = 0.5- , tip_deco = filledTipPath (diamondSpec 1)+ , tip_deco = fillTrailTip $ diamondSpec 1 } odiamondTip :: ArrowTip odiamondTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5- , tip_deco = closedTipPath (diamondSpec 1)+ , tip_deco = closedTrailTip $ diamondSpec 1 } diamondWideTip :: ArrowTip diamondWideTip = ArrowTip- { retract_distance = const 2+ { retract_distance = 1.0 , tip_half_len = 1.0- , tip_deco = filledTipPath (diamondSpec 2)+ , tip_deco = fillTrailTip $ diamondSpec 2 } odiamondWideTip :: ArrowTip odiamondWideTip = ArrowTip- { retract_distance = const 2+ { retract_distance = 2.0 , tip_half_len = 1.0- , tip_deco = closedTipPath (diamondSpec 2)+ , tip_deco = closedTrailTip $ diamondSpec 2 } -curveTipTrail :: Radian -> PlacedTrail En-curveTipTrail theta = - placeCatTrail dv $ vectrapCCW v1 <> vectrapCCW v2+curveTipSpec :: TrailGen+curveTipSpec theta = + anaCatTrail dv $ vectrapCCW v1 <> vectrapCCW v2 where dv = orthoVec (-1.0) 0.75 theta -- back and up v1 = orthoVec 1.0 (-0.75) theta -- fwd and down@@ -436,7 +401,7 @@ vectrapCW :: (Real u, Floating u) => Vec2 u -> CatTrail u-vectrapCW v1 = trapcurveCW w h ang45 ang+vectrapCW v1 = trapCurve CW w h quarter_pi ang where w = vlength v1 h = w / 4@@ -444,7 +409,7 @@ vectrapCCW :: (Real u, Floating u) => Vec2 u -> CatTrail u-vectrapCCW v1 = trapcurveCCW w h quarter_pi ang+vectrapCCW v1 = trapCurve CCW w h quarter_pi ang where w = vlength v1 h = w / 4@@ -454,20 +419,19 @@ curveTip :: ArrowTip curveTip = ArrowTip- { retract_distance = const 0+ { retract_distance = 0 , tip_half_len = 0.5 , tip_deco = body } where- body = promoteLocTheta $ \pt theta -> - localize (join_bevel . solid_stroke_tip) $ - supplyLoc pt $ drawPlacedTrail OSTROKE $ curveTipTrail theta+ body = localize (cap_round . join_round . solid_stroke_tip) $ + openTrailTip curveTipSpec -curveTipRevTrail :: Radian -> PlacedTrail En-curveTipRevTrail theta = - placeCatTrail dv $ vectrapCW v1 <> vectrapCW v2+curveTipRevSpec :: TrailGen+curveTipRevSpec theta = + anaCatTrail dv $ vectrapCW v1 <> vectrapCW v2 where dv = orthoVec 0.0 0.75 theta -- just up v1 = orthoVec (-1.0) (-0.75) theta -- back and down@@ -478,13 +442,12 @@ revcurveTip :: ArrowTip revcurveTip = ArrowTip- { retract_distance = const 1+ { retract_distance = 1 , tip_half_len = 0.5 , tip_deco = body } where- body = promoteLocTheta $ \pt theta -> - localize (join_bevel . solid_stroke_tip) $ - supplyLoc pt $ drawPlacedTrail OSTROKE $ curveTipRevTrail theta+ body = localize (cap_round . join_round . solid_stroke_tip) $ + openTrailTip curveTipRevSpec
src/Wumpus/Drawing/Connectors/Base.hs view
@@ -19,19 +19,24 @@ ConnectorPathQuery+ , SpacingProjection , ArrowTip(..) , ArrowConnector - , leftArrow- , rightArrow - , leftRightArrow- , uniformArrow + , ConnectorConfig(..)+ , ConnectorPathSpec(..)+ , renderConnectorConfig - , rightArrowPath+ , arrowDecoratePath + , leftArrowConnector+ , rightArrowConnector+ , uniformArrowConnector+ ) where +import Wumpus.Drawing.Connectors.ConnectorProps import Wumpus.Drawing.Paths import Wumpus.Basic.Kernel -- package: wumpus-basic@@ -43,151 +48,121 @@ --- | The type of Connectors - a query from start and end point to --- a Path.+type SpacingProjection u = + ConnectorProps -> Point2 u -> Point2 u -> Query u (Point2 u)++++-- | The type of Connectors - a query from start and end point +-- returning an AbsPath. -- type ConnectorPathQuery u = ConnectorQuery u (AbsPath u) ++ -- | Arrowhead /algorithm/ - the components of an arrowhead. -- --- Retract distance may have to account for line width.+-- Retract distance is rather vague - depending on the arrowhead+-- it may represent a flush join between the path and the tip+-- or a join that uses the z-order (tip over path) to create the +-- join. --+-- \*\* WARNING \*\* - pending revision...+-- data ArrowTip = ArrowTip- { retract_distance :: Double -> En+ { retract_distance :: 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)----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)----- | Connector with an arrow tip at the end point (i.e right).----rightArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip -> ConnectorPathQuery u -> ArrowConnector u-rightArrow alg conn = promoteConn $ \p0 p1 ->- applyConn (liftConnectorQuery 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 -> ConnectorPathQuery u -> ArrowConnector u-leftArrow alg conn = promoteConn $ \p0 p1 ->- applyConn (liftConnectorQuery conn) p0 p1 >>= \full_path -> - leftArrowPath alg full_path ----- | Connector with different arrow tips at the start point and --- end points.----leftRightArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip -> ArrowTip -> ConnectorPathQuery u -> ArrowConnector u-leftRightArrow algl algr conn = promoteConn $ \p0 p1 ->- applyConn (liftConnectorQuery conn) p0 p1 >>= \full_path -> - leftRightArrowPath algl algr full_path --+newtype ConnectorPathSpec u = ConnectorPathSpec { + getConnectorPathSpec :: ConnectorProps -> ConnectorPathQuery u } --- | Connector with the same arrow tip at the start point and --- end points.+-- | total_path is the path before accounting for arrow +-- retract distances. ---uniformArrow :: (Real u, Floating u, InterpretUnit u) - => ArrowTip -> ConnectorPathQuery u -> ArrowConnector u-uniformArrow alg conn = promoteConn $ \p0 p1 ->- applyConn (liftConnectorQuery conn) p0 p1 >>= \full_path -> - leftRightArrowPath alg alg full_path +data ConnectorConfig u = ConnectorConfig+ { conn_arrowl :: Maybe ArrowTip+ , conn_arrowr :: Maybe ArrowTip+ , conn_path_spec :: ConnectorPathSpec u + } --- TODO - possible there are opportunities to be more --- compositional here.----- | Path with an arrow tip at the start point (i.e left).------ TODO - shortening a curve does not seem to be working properly...+-- Ideally there should be a plus operation to combine tips +-- allowing double tips. -- ----leftArrowPath :: (Real u, Floating u, InterpretUnit u) - => ArrowTip -> AbsPath u -> Image u (AbsPath u)-leftArrowPath alg full_path =- liftQuery (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 $ - sdecorate tip $ drawPath OSTROKE short_path ----- | 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 =- liftQuery (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 $ - sdecorate tip $ drawPath OSTROKE short_path+type ArrowConnector u = ConnectorImage u (AbsPath u) --- | Path with an arrow tip at the end point (i.e right).------ TODO - shortening a curve does not seem to be working properly...+-- | NOTE - the prefix /render/ needs (re-) consideration... -- +-- If it is a good prefix other functions e.g. drawPath should +-- use render rather than draw. ---leftRightArrowPath :: (Real u, Floating u, InterpretUnit u) - => ArrowTip -> ArrowTip -> AbsPath u -> Image u (AbsPath u)-leftRightArrowPath algl algr full_path =- liftQuery (runArrowTip algl) >>= \(retractl, lenl, decol) -> - liftQuery (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 $ - sdecorate (tipl `mappend` tipr) $ drawPath OSTROKE short_path- +renderConnectorConfig :: (Real u, Floating u, InterpretUnit u)+ => ConnectorProps+ -> ConnectorConfig u+ -> ConnectorImage u (AbsPath u)+renderConnectorConfig props (ConnectorConfig mbl mbr pspec) = + promoteConn $ \src dst -> + liftQuery (qapplyConn path_spec src dst) >>= \tot_path -> + connectorSrcSpace props >>= \sepl -> + connectorDstSpace props >>= \sepr ->+ arrowDecoratePath mbl mbr $ shortenL sepl $ shortenR sepr tot_path+ where+ path_spec = getConnectorPathSpec pspec props +arrowDecoratePath :: (Real u, Floating u, InterpretUnit u) + => Maybe ArrowTip -> Maybe ArrowTip -> (AbsPath u) + -> Image u (AbsPath u)+arrowDecoratePath mbl mbr initial_path = + uconvertCtx1 (maybe 0 retract_distance mbl) >>= \retl -> + uconvertCtx1 (maybe 0 retract_distance mbr) >>= \retr -> + let (p1,theta1) = atstart initial_path+ (p2,theta2) = atend initial_path+ new_path = shortenL retl $ shortenR retr initial_path+ arrl = mbTip p1 (pi + theta1) mbl+ arrr = mbTip p2 theta2 mbr+ in replaceAns initial_path $ + decorate ZABOVE (renderPath OSTROKE new_path) (arrl `mappend` arrr)+ where+ mbTip pt ang = maybe emptyImage (supplyLocTheta pt ang . uconvF . tip_deco) --- | Helper - direction looks best at half the retract distance.++-- | Shorthand... ---tipDirectionL :: (Real u, Floating u) => u -> AbsPath u -> Radian-tipDirectionL u absp | u <= 0 = directionL absp- |otherwise = directionL $ shortenL (0.5*u) absp- -tipDirectionR :: (Real u, Floating u) => u -> AbsPath u -> Radian-tipDirectionR u absp | u <= 0 = directionR absp- |otherwise = directionR $ shortenR (0.5*u) absp- +leftArrowConnector :: (Real u, Floating u, InterpretUnit u)+ => ConnectorProps -> ConnectorPathSpec u -> ArrowTip+ -> ConnectorImage u (AbsPath u)+leftArrowConnector props cpath tip = renderConnectorConfig props cfg + where+ cfg = ConnectorConfig { conn_arrowl = Just tip + , conn_arrowr = Nothing+ , conn_path_spec = cpath } +rightArrowConnector :: (Real u, Floating u, InterpretUnit u)+ => ConnectorProps -> ConnectorPathSpec u -> ArrowTip+ -> ConnectorImage u (AbsPath u)+rightArrowConnector props cpath tip = renderConnectorConfig props cfg + where+ cfg = ConnectorConfig { conn_arrowl = Nothing+ , conn_arrowr = Just tip+ , conn_path_spec = cpath }+ +uniformArrowConnector :: (Real u, Floating u, InterpretUnit u)+ => ConnectorProps -> ConnectorPathSpec u -> ArrowTip+ -> ConnectorImage u (AbsPath u)+uniformArrowConnector props cpath tip = renderConnectorConfig props cfg + where+ cfg = ConnectorConfig { conn_arrowl = Just tip+ , conn_arrowr = Just tip+ , conn_path_spec = cpath }+
src/Wumpus/Drawing/Connectors/BoxConnectors.hs view
@@ -17,22 +17,27 @@ module Wumpus.Drawing.Connectors.BoxConnectors ( ConnectorBox- , connbox- , conntube+ , ConnectorBoxSpec(..)+ , renderConnectorBoxSpec + , conn_box+ , conn_tube+ , conn_chamf_box ++ ) where --- import Wumpus.Drawing.Connectors.Base+import Wumpus.Drawing.Basis.InclineTrails import Wumpus.Drawing.Connectors.ConnectorProps import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core +import Data.VectorSpace -- package: vector-space -import Data.Monoid --- NOTE - boxes (currently) seem to only support stroke otherwise+-- NOTE - boxes seem to only support stroke otherwise -- they would obliterate what they connect. @@ -45,67 +50,67 @@ -- type ConnectorBox u = ConnectorGraphic u +newtype ConnectorBoxSpec u = ConnectorBoxSpec { + getConnectorBoxSpec :: ConnectorProps -> ConnectorBox u } ++renderConnectorBoxSpec :: (Real u, Floating u, InterpretUnit u)+ => ConnectorProps+ -> ConnectorBoxSpec u+ -> ConnectorBox u+renderConnectorBoxSpec props spec = + getConnectorBoxSpec spec props+++++ -- -- DESIGN NOTE - boxes (probably) should not use source and dest -- separators. -- ---- | Draw a stroked, rectangular box around the connector points.------ The rectangle will be inclined to the line.----connbox :: (Real u, Floating u, InterpretUnit u) - => ConnectorProps -> ConnectorBox u-connbox props = promoteConn $ \p0 p1 -> - connectorBoxHalfSize props >>= \sz ->- applyLoc (drawPlacedTrail CSTROKE $ cfconnbox sz (pvec p0 p1)) p0+boxConnector :: (Floating u, Ord u, InterpretUnit u) + => (ConnectorProps -> Point2 u -> Point2 u -> Image u a) + -> ConnectorBoxSpec u+boxConnector mf = ConnectorBoxSpec $ \props -> + promoteConn $ \p0 p1 -> ignoreAns $ mf props p0 p1 -conntube :: (Real u, Floating u, InterpretUnit u) - => ConnectorProps -> ConnectorBox u-conntube props = promoteConn $ \p0 p1 -> +adaptAnaTrail :: (Real u, Floating u, Ord u, InterpretUnit u) + => (u -> Vec2 u -> AnaTrail u) + -> ConnectorBoxSpec u+adaptAnaTrail fn = boxConnector $ \props p0 p1 -> connectorBoxHalfSize props >>= \sz ->- applyLoc (drawPlacedTrail CSTROKE $ cfconntube sz (pvec p0 p1)) p0-+ let v0 = pvec p0 p1 + v1 = v0 ^+^ avec (vdirection v0) (2*sz)+ vinit = avec (vdirection v0) (-sz)+ in applyLoc (renderAnaTrail CSTROKE $ fn sz v1) (displace vinit p0)+ --- Box connectors aren\'t especially coordinate free.---- | @v1@ is the /interior/ vector.+-- | Draw a stroked, rectangular box around the connector points. ---cfconnbox :: (Real u, Floating u) => u -> Vec2 u -> PlacedTrail u-cfconnbox du v1 = - placeCatTrail (orthoVec (-du) (-du) ang) $ mconcat $- [ trail_theta_right w ang- , trail_theta_up h ang- , trail_theta_left w ang- , trail_theta_down h ang- ]- where- ang = vdirection v1 - w = (2*du) + vlength v1- h = 2*du- +-- The rectangle will be inclined to the line.+--+conn_box :: (Real u, Floating u, InterpretUnit u) + => ConnectorBoxSpec u+conn_box = adaptAnaTrail (\sz -> incline_rect (2 * sz)) --- | @v1@ is the /interior/ vector.+-- | Draw a stroked, tube around the connector points. ---cfconntube :: (Real u, Floating u) => u -> Vec2 u -> PlacedTrail u-cfconntube du v1 = - placeCatTrail (orthoVec 0 (-du) ang) $ mconcat $- [ trail_theta_right w ang- , semicircleCCW vup- , trail_theta_left w ang- , semicircleCCW vdown- ]- where- ang = vdirection v1 - w = vlength v1- vup = avec (ang + half_pi) (2*du)- vdown = avec (ang - half_pi) (2*du)-- +-- The tube will be inclined to the line.+--+conn_tube :: (Real u, Floating u, InterpretUnit u) + => ConnectorBoxSpec u+conn_tube = adaptAnaTrail (\sz -> incline_tube (2 * sz)) +-- | Draw a stroked, chamfered box around the connector points.+--+-- The tube will be inclined to the line.+--+conn_chamf_box :: (Real u, Floating u, InterpretUnit u) + => ConnectorBoxSpec u+conn_chamf_box = adaptAnaTrail (\sz -> incline_chamf_rect (2 * sz))
src/Wumpus/Drawing/Connectors/ConnectorPaths.hs view
@@ -17,194 +17,85 @@ module Wumpus.Drawing.Connectors.ConnectorPaths ( - connline- , connarc- , connhdiagh- , connvdiagv+ conn_line++ , conna_arc+ , connb_arc++ , conn_hdiagh+ , conn_vdiagv - , conndiagh- , conndiagv+ , conn_diagh+ , conn_diagv - , connhdiag- , connvdiag+ , conn_hdiag+ , conn_vdiag - , connabar- , connbbar+ , conna_bar+ , connb_bar+ + , conna_flam+ , connb_flam - , connaright- , connbright+ , conna_orthohbar+ , connb_orthohbar - , connhrr- , connrrh- , connvrr- , connrrv+ , conna_orthovbar+ , connb_orthovbar - , connaloop- , connbloop+ , conna_right+ , connb_right - , connhbezier- , connvbezier+ , conn_hrr+ , conn_rrh+ , conn_vrr+ , conn_rrv + , conna_loop+ , connb_loop++ , conn_hbezier+ , conn_vbezier+ ) where +import Wumpus.Drawing.Basis.InclineTrails import Wumpus.Drawing.Connectors.Base import Wumpus.Drawing.Connectors.ConnectorProps import Wumpus.Drawing.Paths -import Wumpus.Basic.Geometry.Quadrant -- package: wumpus-basic-import Wumpus.Basic.Kernel hiding ( promoteConn )+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core import Data.AffineSpace -- package: vector-space +import Control.Applicative -type ProjectionQuery u = - ConnectorProps -> Point2 u -> Point2 u -> Query u (Point2 u) -inlineSrc :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-inlineSrc props p0 p1 = - connectorSrcSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p0 .+^ avec ang sep -inlineDst :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-inlineDst props p0 p1 = - connectorDstSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p1 .-^ avec ang sep---- | Like 'inlineSrc' but /expands/ rather than /contracts/.--- --- Use for loops.----extlineSrc :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-extlineSrc props p0 p1 = - connectorSrcSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p0 .-^ avec ang sep----- | Like 'inlineDst' but /expands/ rather than /contracts/.--- --- Use for loops.----extlineDst :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-extlineDst props p0 p1 = - connectorDstSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p1 .+^ avec ang sep---- | Horizontal \"orthonormal\" version of 'inlineSrc'.----horizontalSrc :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-horizontalSrc props p0 p1 = - connectorSrcSpace props >>= \sep ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> return $ p0 .+^ go_right sep- QUAD_SE -> return $ p0 .+^ go_right sep- _ -> return $ p0 .+^ go_left sep ------ | Horizontal \"orthonormal\" version of 'inlineDst'.----horizontalDst :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-horizontalDst props p0 p1 = - connectorDstSpace props >>= \sep ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> return $ p1 .+^ go_left sep- QUAD_SE -> return $ p1 .+^ go_left sep - _ -> return $ p1 .+^ go_right sep------ | Vertical \"orthonormal\" version of 'inlineSrc'.----verticalSrc :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-verticalSrc props p0 p1 =- connectorSrcSpace props >>= \sep ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> return $ p0 .+^ go_up sep - QUAD_NW -> return $ p0 .+^ go_up sep- _ -> return $ p0 .+^ go_down sep----- | Vertical \"orthonormal\" version of 'inlineDst'.----verticalDst :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-verticalDst props p0 p1 =- connectorDstSpace props >>= \sep ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> return $ p1 .+^ go_down sep - QUAD_NW -> return $ p1 .+^ go_down sep- _ -> return $ p1 .+^ go_up sep---abovePerpSrc :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-abovePerpSrc props p0 p1 = - connectorSrcSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p0 .+^ avec (ang + half_pi) sep--abovePerpDst :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-abovePerpDst props p0 p1 =- connectorDstSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p1 .+^ avec (ang + half_pi) sep---belowPerpSrc :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-belowPerpSrc props p0 p1 =- connectorSrcSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p0 .+^ avec (ang - half_pi) sep--belowPerpDst :: (Real u, Floating u, InterpretUnit u) - => ProjectionQuery u-belowPerpDst props p0 p1 =- connectorDstSpace props >>= \sep -> - let ang = vdirection $ pvec p0 p1- in return $ p1 .+^ avec (ang - half_pi) sep------ | Promote a function from source and dest points to a connector --- function accounting for the separator values in the --- DrawingContext.+-- | Build as Path as a CatTrail between two points. ---buildConn :: (Real u, Floating u, InterpretUnit u) - => ConnectorProps - -> ProjectionQuery u -> ProjectionQuery u- -> (Point2 u -> Point2 u -> Query u (AbsPath u))- -> ConnectorPathQuery u-buildConn props qsrc qdst fn = qpromoteConn $ \p0 p1 -> - qsrc props p0 p1 >>= \q0 -> qdst props p0 p1 >>= \q1 -> fn q0 q1----+catConnector :: (Floating u, Ord u, InterpretUnit u, Tolerance u) + => (ConnectorProps -> Point2 u -> Point2 u -> Query u (CatTrail u)) + -> ConnectorPathSpec u+catConnector mf = ConnectorPathSpec $ \props -> + qpromoteConn $ \p0 p1 -> catTrailPath p0 <$> mf props p0 p1 +horizontally :: (Real u, Floating u) + => (Vec2 u -> a) -> (Vec2 u -> a) -> Vec2 u -> a+horizontally rightf leftf v1 = + case horizontalDirection $ vdirection v1 of+ RIGHTWARDS -> rightf v1+ LEFTWARDS -> leftf v1 -- | Straight line connector. ---connline :: (Real u, Floating u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connline props = buildConn props inlineSrc inlineDst $ \p0 p1 -> - return $ line1 p0 p1+conn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ConnectorPathSpec u+conn_line = catConnector $ \_ p0 p1 -> pure $ catline $ pvec p0 p1 @@ -218,17 +109,28 @@ -- The notion of /above/ is respective to the line direction, of -- course. -- +-- TODO - above and below versions... ---connarc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) - => ConnectorProps -> ConnectorPathQuery u-connarc props = buildConn props inlineSrc inlineDst $ \p0 p1 -> +conna_arc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) + => ConnectorPathSpec u+conna_arc = connArcBody (vtriCurve CW) (vtriCurve CCW)++-- | Below version of 'conna_arc'.+--+connb_arc :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) + => ConnectorPathSpec u+connb_arc = connArcBody (vtriCurve CCW) (vtriCurve CW)+++connArcBody :: (Real u, Floating u, Ord u, InterpretUnit u, Tolerance u) + => (u -> Vec2 u -> CatTrail u) + -> (u -> Vec2 u -> CatTrail u) + -> ConnectorPathSpec u+connArcBody rightf leftf = catConnector $ \props p0 p1 -> let arc_ang = conn_arc_ang props v1 = pvec p0 p1- hlen = 0.5 * vlength v1- ang = vdirection v1- cp0 = p0 .+^ avec (ang + arc_ang) hlen- cp1 = p1 .+^ avec (pi + ang - arc_ang) hlen- in return $ curve1 p0 cp0 cp1 p1+ h = (0.5 * vlength v1) * (fromRadian $ tan arc_ang)+ in return $ horizontally (rightf h) (leftf h) v1 @@ -242,22 +144,14 @@ -- Horizontal /arms/ are drawn from the start and end points, a -- diagonal segment joins the arms. -- -connhdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => ConnectorProps -> ConnectorPathQuery u-connhdiagh props = buildConn props horizontalSrc horizontalDst $ \p0 p1 -> - connectorArms props >>= \(src_arm, dst_arm) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> right p0 p1 src_arm dst_arm- QUAD_SE -> right p0 p1 src_arm dst_arm- _ -> left p0 p1 src_arm dst_arm- where- right p0 p1 h0 h1 = return $ vertexPath [ p0, p0 .+^ hvec h0- , p1 .-^ hvec h1, p1 ]-- left p0 p1 h0 h1 = return $ vertexPath [ p0, p0 .-^ hvec h0 - , p1 .+^ hvec h1, p1 ]+conn_hdiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => ConnectorPathSpec u+conn_hdiagh = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(src_leg, dst_leg) ->+ return $ trail_hdiagh src_leg dst_leg $ pvec p0 p1 +-- probably want trail_hdiagh as a library function -- | Vertical-diagonal-vertical connector. --@@ -270,21 +164,11 @@ -- Vertical /arms/ are drawn from the start and end points, a -- diagonal segment joins the arms. -- -connvdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => ConnectorProps -> ConnectorPathQuery u-connvdiagv props = buildConn props verticalSrc verticalDst $ \p0 p1 -> - connectorArms props >>= \(src_arm, dst_arm) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> up p0 p1 src_arm dst_arm- QUAD_NW -> up p0 p1 src_arm dst_arm- _ -> down p0 p1 src_arm dst_arm- where- up p0 p1 v0 v1 = return $ vertexPath [ p0, p0 .+^ vvec v0- , p1 .-^ vvec v1, p1 ]-- down p0 p1 v0 v1 = return $ vertexPath [ p0, p0 .-^ vvec v0 - , p1 .+^ vvec v1, p1 ]-+conn_vdiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => ConnectorPathSpec u+conn_vdiagv = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(src_leg, dst_leg) ->+ return $ trail_vdiagv src_leg dst_leg $ pvec p0 p1 -- | Diagonal-horizontal connector.@@ -297,18 +181,11 @@ -- from the start point joining a horizontal arm drawn from the -- end point -- -conndiagh :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => ConnectorProps -> ConnectorPathQuery u-conndiagh props = buildConn props inlineSrc horizontalDst $ \p0 p1 -> - connectorArms props >>= \(_,dst_arm) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> right p0 p1 dst_arm- QUAD_SE -> right p0 p1 dst_arm- _ -> left p0 p1 dst_arm- where- right p0 p1 h1 = return $ vertexPath [ p0, p1 .-^ hvec h1, p1 ]-- left p0 p1 h1 = return $ vertexPath [ p0, p1 .+^ hvec h1, p1 ]+conn_diagh :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => ConnectorPathSpec u+conn_diagh = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(_, dst_leg) ->+ return $ trail_diagh dst_leg $ pvec p0 p1 -- | Diagonal-vertical connector.@@ -322,18 +199,11 @@ -- from the start point joining a vertical arm drawn from the end -- point. -- -conndiagv :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => ConnectorProps -> ConnectorPathQuery u-conndiagv props = buildConn props inlineSrc verticalDst $ \p0 p1 -> - connectorArms props >>= \(_,dst_arm) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> up p0 p1 dst_arm- QUAD_NW -> up p0 p1 dst_arm- _ -> down p0 p1 dst_arm- where- up p0 p1 v1 = return $ vertexPath [ p0, p1 .-^ vvec v1, p1 ]-- down p0 p1 v1 = return $ vertexPath [ p0, p1 .+^ vvec v1, p1 ]+conn_diagv :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => ConnectorPathSpec u+conn_diagv = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(_, dst_leg) ->+ return $ trail_diagv dst_leg $ pvec p0 p1 @@ -347,18 +217,11 @@ -- from the start point joining a diagonal segment drawn from the -- end point. -- -connhdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => ConnectorProps -> ConnectorPathQuery u-connhdiag props = buildConn props horizontalSrc inlineDst $ \p0 p1 -> - connectorArms props >>= \(src_arm,_) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> right p0 p1 src_arm- QUAD_SE -> right p0 p1 src_arm- _ -> left p0 p1 src_arm- where- right p0 p1 h1 = return $ vertexPath [ p0, p0 .+^ hvec h1, p1 ]-- left p0 p1 h1 = return $ vertexPath [ p0, p0 .-^ hvec h1, p1 ]+conn_hdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => ConnectorPathSpec u+conn_hdiag = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(src_leg, _) ->+ return $ trail_hdiag src_leg $ pvec p0 p1 -- | Vertical-diagonal connector.@@ -372,23 +235,16 @@ -- from the start point joining a vertical segment drawn from the -- end point. -- -connvdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => ConnectorProps -> ConnectorPathQuery u-connvdiag props = buildConn props verticalSrc inlineDst $ \p0 p1 -> - connectorArms props >>= \(src_arm,_) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> up p0 p1 src_arm- QUAD_NW -> up p0 p1 src_arm- _ -> down p0 p1 src_arm- where- up p0 p1 v1 = return $ vertexPath [ p0, p0 .+^ vvec v1, p1 ]-- down p0 p1 v1 = return $ vertexPath [ p0, p0 .-^ vvec v1, p1 ]+conn_vdiag :: (Real u, Floating u, Tolerance u, InterpretUnit u)+ => ConnectorPathSpec u+conn_vdiag = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(src_leg, _) ->+ return $ trail_vdiag src_leg $ pvec p0 p1 -- DESIGN NOTE - should the concept of /above/ and /below/ use --- quadrants?+-- ClockDirection instead? -- @@ -400,13 +256,9 @@ -- -- The bar is drawn /above/ the points. ---connabar :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connabar props = buildConn props abovePerpSrc abovePerpDst $ \p0 p1 ->- connectorArms props >>= \(src_arm,dst_arm) ->- let ang = vdirection $ pvec p0 p1- in return $ vertexPath [ p0, dispDirectionTheta UP src_arm ang p0- , dispDirectionTheta UP dst_arm ang p1, p1 ]+conna_bar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conna_bar = connBarBody (trail_perp_bar2 CW) (trail_perp_bar2 CCW) -- | Bar connector.@@ -417,16 +269,104 @@ -- -- The bar is drawn /below/ the points. ---connbbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connbbar props = buildConn props belowPerpSrc belowPerpDst $ \p0 p1 ->- connectorArms props >>= \(src_arm, dst_arm) ->- let ang = vdirection $ pvec p0 p1- in return $ vertexPath [ p0, dispDirectionTheta DOWN src_arm ang p0- , dispDirectionTheta DOWN dst_arm ang p1, p1 ]+connb_bar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+connb_bar = connBarBody (trail_perp_bar2 CCW) (trail_perp_bar2 CW) +connBarBody :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => (u -> u -> Vec2 u -> CatTrail u) + -> (u -> u -> Vec2 u -> CatTrail u) + -> ConnectorPathSpec u+connBarBody rightf leftf = catConnector $ \props p0 p1 ->+ connectorLegs props >>= \(src, dst) ->+ return $ horizontally (rightf src dst) (leftf src dst) $ pvec p0 p1 +++-- | /Flam/ connector.+--+-- > ,- '+-- > ,- | +-- > | |+-- > o @ +--+-- The bar is drawn /above/ the points.+--+conna_flam :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conna_flam = connFlamBody (trail_vflam CW) (trail_vflam CCW)++-- | /Flam/ connector - bleow.+--+connb_flam :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+connb_flam = connFlamBody (trail_vflam CCW) (trail_vflam CW) +++connFlamBody :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => (u -> u -> Vec2 u -> CatTrail u) + -> (u -> u -> Vec2 u -> CatTrail u) + -> ConnectorPathSpec u+connFlamBody rightf leftf = catConnector $ \props p0 p1 ->+ connectorLegs props >>= \(src,dst) ->+ return $ horizontally (rightf src dst) (leftf src dst) $ pvec p0 p1+++++-- | Bar connector - always orthonormal .+--+-- > +-- > ,----, +-- > | |+-- > o @ +--+-- The bar is drawn /above/ the points.+--+conna_orthohbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conna_orthohbar = connOrthobarBody (trail_ortho_hbar CW) (trail_ortho_hbar CCW)++-- | Bar connector orthonormal - below.+--+connb_orthohbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+connb_orthohbar = connOrthobarBody (trail_ortho_hbar CCW) (trail_ortho_hbar CW)++++connOrthobarBody :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => (u -> Vec2 u -> CatTrail u)+ -> (u -> Vec2 u -> CatTrail u)+ -> ConnectorPathSpec u+connOrthobarBody rightf leftf = catConnector $ \props p0 p1 ->+ connectorLoopSize props >>= \looph ->+ return $ horizontally (rightf looph) (leftf looph) $ pvec p0 p1+++-- | Bar connector - always orthonormal.+--+-- > +-- > ,--- o +-- > | +-- > '--- @ +-- > +--+-- The bar is drawn /left/ of the points.+--+conna_orthovbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conna_orthovbar = connOrthobarBody (trail_ortho_vbar CW) (trail_ortho_vbar CCW)++-- | Bar connector orthonormal - right of the points.+--+connb_orthovbar :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+connb_orthovbar = connOrthobarBody (trail_ortho_vbar CCW) (trail_ortho_vbar CW)+++ -- | Right angle connector. -- -- > ,----@ @@ -435,11 +375,10 @@ -- -- The bar is drawn /above/ the points. ---connaright :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connaright props = - buildConn props verticalSrc horizontalDst $ \ p0@(P2 x0 _) p1@(P2 _ y1) ->- let mid = P2 x0 y1 in return $ vertexPath [p0, mid, p1]+conna_right :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conna_right = catConnector $ \_ p0 p1 ->+ return $ trail_vright $ pvec p0 p1 -- | Right angle connector.@@ -450,24 +389,15 @@ -- -- The bar is drawn /below/ the points. ---connbright :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connbright props = - buildConn props horizontalSrc verticalDst $ \ p0@(P2 _ y0) p1@(P2 x1 _) ->- let mid = P2 x1 y0 in return $ vertexPath [p0, mid, p1]+connb_right :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+connb_right = catConnector $ \_ p0 p1 -> + return $ trail_hright $ pvec p0 p1 --- Helper --- | Derive the direction aka. sign of an arm.----directional :: (Num u, Ord u) => u -> u -> u -> u-directional src dst arm = if src < dst then arm else negate arm- ----- | Connector with two horizontal segements and a joining +-- | Connector with two horizontal segments and a joining -- vertical segment. -- -- > ,--@@@ -475,17 +405,14 @@ -- > o----' -- -- The length of the first horizontal segment is the source arm --- length. The length of the final segment is the remaing +-- length. The length of the final segment is the remaining -- horizontal distance. ---connhrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connhrr props = - buildConn props horizontalSrc horizontalDst $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->- connectorArms props >>= \(src_arm,_) -> - let a0 = p0 .+^ hvec (directional x0 x1 src_arm)- a1 = a0 .+^ vvec (y1 - y0)- in return $ vertexPath [p0, a0, a1, p1]+conn_hrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conn_hrr = catConnector $ \props p0 p1 ->+ connectorLegs props >>= \(src_leg,_) ->+ return $ trail_hrr src_leg $ pvec p0 p1 -- | Connector with two horizontal segements and a joining @@ -495,18 +422,15 @@ -- > | -- > o--' ----- The length of the final horizontal segment is the distination +-- The length of the final horizontal segment is the destination -- arm length. The length of the initial segment is the remaining -- horizontal distance. ---connrrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connrrh props = - buildConn props horizontalSrc horizontalDst $ \p0@(P2 x0 y0) p1@(P2 x1 y1) ->- connectorArms props >>= \(_,dst_arm) -> - let a1 = p1 .-^ hvec (directional x0 x1 dst_arm)- a0 = a1 .-^ vvec (y1 - y0)- in return $ vertexPath [p0, a0, a1, p1]+conn_rrh :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conn_rrh = catConnector $ \props p0 p1 ->+ connectorLegs props >>= \(_,dst_leg) ->+ return $ trail_rrh dst_leg $ pvec p0 p1 -- | Connector with two right angles...@@ -517,14 +441,15 @@ -- > | -- > o ---connvrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connvrr props = - buildConn props verticalSrc verticalDst $ \p0@(P2 x0 y0) p1@(P2 x1 y1) ->- connectorArms props >>= \(src_arm,_) -> - let a0 = p0 .+^ vvec (directional y0 y1 src_arm)- a1 = a0 .+^ hvec (x1 - x0)- in return $ vertexPath [p0, a0, a1, p1]+-- The length of the first vertical segment is the source arm +-- length. The length of the final segment is the remaining +-- vertical distance. +--+conn_vrr :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conn_vrr = catConnector $ \props p0 p1 ->+ connectorLegs props >>= \(src_leg,_) ->+ return $ trail_vrr src_leg $ pvec p0 p1 -- | Connector with two right angles...@@ -535,15 +460,15 @@ -- > | -- > o ---connrrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connrrv props = - buildConn props verticalSrc verticalDst $ \ p0@(P2 x0 y0) p1@(P2 x1 y1) ->- connectorArms props >>= \(_,dst_arm) -> - let a1 = p1 .-^ vvec (directional y0 y1 dst_arm)- a0 = a1 .-^ hvec (x1 - x0)- in return $ vertexPath [p0, a0, a1, p1]-+-- The length of the final vertical segment is the destination +-- arm length. The length of the initial segment is the remaining+-- vertical distance. +--+conn_rrv :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conn_rrv = catConnector $ \props p0 p1 ->+ connectorLegs props >>= \(_,dst_leg) ->+ return $ trail_rrv dst_leg $ pvec p0 p1 @@ -555,9 +480,10 @@ -- -- The loop is drawn /above/ the points. ---connaloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connaloop = loopbody id+conna_loop :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+conna_loop = connLoopBody (trail_rect_loop CW) (trail_rect_loop CCW)+ -- | Loop connector. --@@ -565,26 +491,25 @@ -- > | | -- > '---------' ----- The loop is drawn /above/ the points.+-- The loop is drawn /below/ the points. ---connbloop :: (Real u, Floating u, Tolerance u, InterpretUnit u) - => ConnectorProps -> ConnectorPathQuery u-connbloop = loopbody negate+connb_loop :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => ConnectorPathSpec u+connb_loop = connLoopBody (trail_rect_loop CCW) (trail_rect_loop CW) --- | Looping just differs on a negate...----loopbody :: (Real u, Floating u, Tolerance u, InterpretUnit u)- => (u -> u) -> ConnectorProps -> ConnectorPathQuery u-loopbody fn props = buildConn props extlineSrc extlineDst $ \p0 p1 ->- connectorArms props >>= \(src_arm, dst_arm) ->- connectorLoopSize props >>= \loop_len ->- let ang = vdirection $ pvec p0 p1 - 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 ] +connLoopBody :: (Real u, Floating u, Tolerance u, InterpretUnit u) + => (u -> u -> u -> Vec2 u -> CatTrail u) + -> (u -> u -> u -> Vec2 u -> CatTrail u) + -> ConnectorPathSpec u+connLoopBody rightf leftf = catConnector $ \props p0 p1 -> + connectorLegs props >>= \(src,dst) ->+ connectorLoopSize props >>= \looph ->+ return $ horizontally (rightf src dst looph) (leftf src dst looph) + $ pvec p0 p1+++ -- | Bezier curve connector - the control points are positioned -- horizontally respective to the source and dest. --@@ -596,17 +521,14 @@ -- Note - the source and dest arm lengths are doubled, generally -- this produces nicer curves. -- --- Warning - currently bezier connectors do not draw properly--- with source or destination spacers.----connhbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u)- => ConnectorProps -> ConnectorPathQuery u-connhbezier props = buildConn props inlineSrc inlineDst $ \p0 p1 -> +conn_hbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => ConnectorPathSpec u+conn_hbezier = ConnectorPathSpec $ \props -> + qpromoteConn $ \p0 p1 -> fmap (\(a,b) -> (2*a,2*b)) (connectorArms props) >>= \(src_arm,dst_arm) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> right p0 p1 src_arm dst_arm- QUAD_SE -> right p0 p1 src_arm dst_arm- _ -> left p0 p1 src_arm dst_arm+ case horizontalDirection $ vdirection $ pvec p0 p1 of+ RIGHTWARDS -> right p0 p1 src_arm dst_arm+ _ -> left p0 p1 src_arm dst_arm where right p0 p1 h0 h1 = return $ curve1 p0 (p0 .+^ hvec h0) (p1 .-^ hvec h1) p1 @@ -625,20 +547,16 @@ -- Note - the source and dest arm lengths are doubled, generally -- this produces nicer curves. ----- Warning - currently bezier connectors do not draw properly--- with source or destination spacers.----connvbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u)- => ConnectorProps -> ConnectorPathQuery u-connvbezier props = buildConn props inlineSrc inlineDst $ \p0 p1 -> +conn_vbezier :: (Real u, Floating u, InterpretUnit u, Tolerance u)+ => ConnectorPathSpec u+conn_vbezier = ConnectorPathSpec $ \props -> + qpromoteConn $ \p0 p1 -> fmap (\(a,b) -> (2*a,2*b)) (connectorArms props) >>= \(src_arm,dst_arm) ->- case quadrant $ vdirection $ pvec p0 p1 of- QUAD_NE -> up p0 p1 src_arm dst_arm- QUAD_NW -> up p0 p1 src_arm dst_arm- _ -> down p0 p1 src_arm dst_arm+ case verticalDirection $ vdirection $ pvec p0 p1 of+ UPWARDS -> up p0 p1 src_arm dst_arm+ _ -> down p0 p1 src_arm dst_arm where up p0 p1 v0 v1 = return $ curve1 p0 (p0 .+^ vvec v0) (p1 .-^ vvec v1) p1- down p0 p1 v0 v1 = return $ curve1 p0 (p0 .-^ vvec v0) (p1 .+^ vvec v1) p1
src/Wumpus/Drawing/Connectors/ConnectorProps.hs view
@@ -25,6 +25,7 @@ , connectorSrcSpace , connectorDstSpace , connectorArms+ , connectorLegs , connectorLoopSize , connectorBoxHalfSize @@ -131,6 +132,15 @@ connectorArms props = (\sz -> ( uconvert1 sz $ conn_src_arm props , uconvert1 sz $ conn_dst_arm props) )+ <$> pointSize++-- | /legs/ are Arms + spacing.+--+connectorLegs :: (DrawingCtxM m, InterpretUnit u) + => ConnectorProps -> m (u,u)+connectorLegs props = + (\sz -> ( uconvert1 sz $ conn_src_space props + conn_src_arm props+ , uconvert1 sz $ conn_dst_space props + conn_dst_arm props ) ) <$> pointSize
src/Wumpus/Drawing/Dots/AnchorDots.hs view
@@ -65,9 +65,9 @@ import Wumpus.Drawing.Dots.SimpleDots ( MarkSize ) import qualified Wumpus.Drawing.Dots.SimpleDots as SD+import Wumpus.Drawing.Paths.Intersection -import Wumpus.Basic.Geometry -- package: wumpus-basic-import Wumpus.Basic.Kernel +import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core @@ -141,17 +141,7 @@ rectCardinal hw _ ctr WEST = ctr .+^ (hvec (-hw)) rectCardinal hw hh ctr NORTH_WEST = ctr .+^ (vec (-hw) hh) -polyCardinal :: Floating u => (Radian -> Point2 u) -> Cardinal -> Point2 u-polyCardinal f NORTH = f (0.5 * pi)-polyCardinal f NORTH_EAST = f (0.25 * pi) -polyCardinal f EAST = f 0 -polyCardinal f SOUTH_EAST = f (1.75 * pi) -polyCardinal f SOUTH = f (1.5 * pi) -polyCardinal f SOUTH_WEST = f (1.25 * pi)-polyCardinal f WEST = f pi -polyCardinal f NORTH_WEST = f (0.75 * pi) - -- | All anchors are the center! -- zeroAnchor :: Point2 u -> DotAnchor u@@ -161,15 +151,27 @@ , cardinal_anchor = const ctr } -rectangleAnchor :: (Real u, Floating u) => u -> u -> Point2 u -> DotAnchor u+rectangleAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance 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 = displace (rectRadialVector hw hh theta) ctr+ fn theta = let mb_v1 = rectangleRadialIntersect (2*hw) (2*hh) theta+ in displace (maybe zeroVec id mb_v1) ctr +triangleAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Point2 u -> DotAnchor u+triangleAnchor hh ctr = + DotAnchor { center_anchor = ctr+ , radial_anchor = fn + , cardinal_anchor = radialCardinal hh ctr }+ where+ fn theta = let mb_v1 = isoscelesTriangleRadialIntersect (2*hh) (2*hh) theta+ in displace (maybe zeroVec id mb_v1) ctr + circleAnchor :: Floating u => u -> Point2 u -> DotAnchor u circleAnchor rad ctr = DotAnchor { center_anchor = ctr@@ -179,19 +181,9 @@ 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 = - DotAnchor { center_anchor = ctr- , radial_anchor = fn - , cardinal_anchor = polyCardinal fn }- where- fn theta = maybe ctr id $ findIntersect ctr theta - $ polygonLineSegments ps ---bboxRectAnchor :: (Real u, Floating u) => BoundingBox u -> DotAnchor u+bboxRectAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => BoundingBox u -> DotAnchor u bboxRectAnchor (BBox bl@(P2 x1 y1) (P2 x2 y2)) = let hw = 0.5 * (x2 - x1) hh = 0.5 * (y2 - y1)@@ -201,7 +193,7 @@ zeroLDO :: InterpretUnit u => LocQuery u (DotAnchor u) zeroLDO = qpromoteLoc $ \pt -> return $ zeroAnchor pt -rectangleLDO :: (Real u, Floating u, InterpretUnit u) +rectangleLDO :: (Real u, Floating u, InterpretUnit u, Tolerance u) => MarkSize -> MarkSize -> LocQuery u (DotAnchor u) rectangleLDO w h = qpromoteLoc $ \pt -> (\uw uh -> rectangleAnchor (uw*0.5) (uh*0.5) pt) @@ -224,12 +216,8 @@ triangleLDO :: (Real u, Floating u, Tolerance u, InterpretUnit u) => MarkSize -> LocQuery u (DotAnchor u) triangleLDO h = qpromoteLoc $ \pt -> - uconvertCtx1 h >>= \uh -> - let alg = trailIterateLocus $ fn3 $ equilateralTriangleVertices uh- in (\ps -> polygonAnchor ps pt) - <$> qapplyLoc (placedTrailPoints alg) pt- where- fn3 (a,b,c) = [a,b,c]+ (\uh -> triangleAnchor (uh*0.5) pt) + <$> uconvertCtx1 h --------------------------------------------------------------------------------@@ -260,7 +248,8 @@ largeCirc = intoLocImage (circleLDO 1.00) SD.largeCirc -dotChar :: (Floating u, Real u, InterpretUnit u) => Char -> DotLocImage u+dotChar :: (Floating u, Real u, InterpretUnit u, Tolerance u) + => Char -> DotLocImage u dotChar ch = dotText [ch] @@ -271,7 +260,8 @@ -- -dotText :: (Floating u, Real u, InterpretUnit u) => String -> DotLocImage u +dotText :: (Floating u, Real u, InterpretUnit u, Tolerance u) + => String -> DotLocImage u dotText ss = fmap bboxRectAnchor $ runPosObjectBBox CENTER $ posText ss @@ -307,7 +297,8 @@ dotDisk = intoLocImage (circleLDO 0.5) SD.dotDisk -dotSquare :: (Floating u, Real u, InterpretUnit u) => DotLocImage u+dotSquare :: (Floating u, Real u, InterpretUnit u, Tolerance u) + => DotLocImage u dotSquare = intoLocImage (rectangleLDO 1 1) SD.dotSquare
src/Wumpus/Drawing/Dots/SimpleDots.hs view
@@ -4,7 +4,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Dots.SimpleDots--- Copyright : (c) Stephen Tetley 2011+-- Copyright : (c) Stephen Tetley 2011-2012 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>@@ -67,9 +67,9 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Basis.Symbols -import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core@@ -128,13 +128,13 @@ -- | Stroked disk (circle) - radius 0.25 MarkSize. -- smallCirc :: InterpretUnit u => LocGraphic u-smallCirc = umark $ ocircle 0.25+smallCirc = umark $ scircle 0.25 -- | Stroked disk (circle) - radius 1.0 MarkSize. -- largeCirc :: InterpretUnit u => LocGraphic u-largeCirc = umark $ ocircle 1+largeCirc = umark $ scircle 1 -- possibly:@@ -197,15 +197,15 @@ dotDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u-dotDiamond = umark $ drawPlacedTrail CSTROKE (diamondTrail 0.5 0.66)+dotDiamond = umark $ renderAnaTrail CSTROKE (diamondTrail 0.5 0.66) dotFDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u-dotFDiamond = umark $ drawPlacedTrail CFILL (diamondTrail 0.5 0.66)+dotFDiamond = umark $ renderAnaTrail CFILL (diamondTrail 0.5 0.66) dotBDiamond :: (Fractional u, InterpretUnit u) => LocGraphic u-dotBDiamond = umark $ drawPlacedTrail CFILL_STROKE (diamondTrail 0.5 0.66)+dotBDiamond = umark $ renderAnaTrail CFILL_STROKE (diamondTrail 0.5 0.66) -- | Note disk is filled.@@ -216,11 +216,11 @@ dotSquare :: (Fractional u, InterpretUnit u) => LocGraphic u-dotSquare = umark $ drawPlacedTrail CSTROKE (rectangleTrail 1 1)+dotSquare = umark $ renderAnaTrail CSTROKE (rectangleTrail 1 1) dotCircle :: (Fractional u, InterpretUnit u) => LocGraphic u-dotCircle = umark $ ocircle 0.5+dotCircle = umark $ scircle 0.5 dotBCircle :: (Fractional u, InterpretUnit u) => LocGraphic u@@ -229,7 +229,7 @@ dotPentagon :: (Floating u, InterpretUnit u) => LocGraphic u-dotPentagon = umark $ drawPlacedTrail CSTROKE (polygonTrail 5 0.5)+dotPentagon = umark $ renderAnaTrail CSTROKE (polygonTrail 5 0.5) @@ -241,7 +241,7 @@ => u -> LocGraphic u starLines hh = promoteLoc $ \ctr -> let alg = polygonTrail 5 hh- in liftQuery (qapplyLoc (placedTrailPoints alg) ctr) >>= \ps -> + in liftQuery (qapplyLoc (anaTrailPoints alg) ctr) >>= \ps -> step $ map (fn ctr) ps where fn p0 p1 = straightLine p0 p1@@ -278,7 +278,4 @@ dotTriangle :: (Floating u, InterpretUnit u) => LocGraphic u-dotTriangle = umark $ drawPlacedTrail CSTROKE alg - where- alg = trailIterateLocus $ fn3 $ equilateralTriangleVertices 1- fn3 = \(a,b,c) -> [a,b,c]+dotTriangle = umark $ renderAnaTrail CSTROKE $ isosceles_triangle_trail 1 1
src/Wumpus/Drawing/Extras/Axes.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Extras.Axes--- Copyright : (c) Stephen Tetley 2011+-- Copyright : (c) Stephen Tetley 2011-2012 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>@@ -37,11 +37,11 @@ -- | Simple orthonormal axes using snap grid units. ---orthontAxes :: (Real u, Floating u, InterpretUnit u)+orthontAxes :: (Real u, Floating u, InterpretUnit u, Tolerance u) => (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+ let conn1 = ignoreAns conn_line xPtl = P2 (x - (uw * fromIntegral xl)) y xPtr = P2 (x + (uw * fromIntegral xr)) y yPtl = P2 x (y - (uh * fromIntegral yl))@@ -51,24 +51,25 @@ -horizontalLabels :: (Num a, Fractional u, InterpretUnit u) +horizontalLabels :: (Num a, Show a, Fractional u, InterpretUnit u) => RectAddress -> [a] -> LocGraphic u horizontalLabels addr ns = - snapmove (1,1) >>= \(V2 uw _) -> ignoreAns (runChainH uw $ mapM mf ns)+ snapmove (1,1) >>= \(V2 uw _) -> ignoreAns (distribH uw $ map mf ns) where- mf n = chain1 $ runPosObject addr $ posTextUpright $ show n+ mf n = runPosObject addr $ posTextUpright $ show n -verticalLabels :: (Num a, Fractional u, InterpretUnit u) +verticalLabels :: (Num a, Show a, Fractional u, InterpretUnit u) => RectAddress -> [a] -> LocGraphic u verticalLabels addr ns = - snapmove (1,1) >>= \(V2 _ uh) -> ignoreAns (runChainV uh $ mapM mf ns)+ snapmove (1,1) >>= \(V2 _ uh) -> ignoreAns (distribV uh $ map mf ns) where- mf n = chain1 $ runPosObject addr $ posTextUpright $ show n+ mf n = runPosObject addr $ posTextUpright $ show n --- Cf. Parsec\'s Token module...+-- Cf. Parsec\'s Token module - remake with same name... ---connline :: (Real u, Floating u, InterpretUnit u) => ConnectorPathQuery u-connline = C.connline default_connector_props+conn_line :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => ArrowConnector u+conn_line = rightArrowConnector default_connector_props C.conn_line barb45
src/Wumpus/Drawing/Extras/Loop.hs view
@@ -16,8 +16,10 @@ module Wumpus.Drawing.Extras.Loop ( - loop- , loopPoints++ loopPath+ , loopTrail+ ) where @@ -31,33 +33,28 @@ import Data.AffineSpace -- package: vector-space --- TODO - Loop is a decoration not a connector.--- It should probably have the same signature as wedge / arc.+import Data.Monoid --- | 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 +loopPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Point2 u -> Radian -> AbsPath u+loopPath zradius ctr incl = anaTrailPath ctr $ loopTrail zradius incl --- 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 +-- This is a legacy definition updated to use Trails, hence it is +-- not so clear. --- | 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 ]+loopTrail :: (Real u, Floating u) => u -> Radian -> AnaTrail u+loopTrail circ_radius incl = + anaCatTrail (pvec zeroPt startl) $ + mconcat [ diffCurve startl cp1 cp2 kitel+ , diffCurve kitel cp3 cp4 top+ , diffCurve top cp5 cp6 kiter+ , diffCurve kiter cp7 cp8 startr+ ] where hw = 1.25 * circ_radius height = 3.8 * circ_radius@@ -71,12 +68,12 @@ 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+ top = dispParallel height incl zeroPt+ kiter = dispOrtho hminor (-hw) incl zeroPt+ kitel = dispOrtho hminor hw incl zeroPt - startr = circ_ctr .+^ avec (circularModulo $ incl - theta) circ_radius- startl = circ_ctr .+^ avec (circularModulo $ incl + theta) circ_radius+ startr = zeroPt .+^ avec (circularModulo $ incl - theta) circ_radius+ startl = zeroPt .+^ avec (circularModulo $ incl + theta) circ_radius -- quadrant III cp1 = startl .+^ end_vec @@ -93,3 +90,4 @@ -- quadrant IV cp7 = dispParallel minor_down incl kiter cp8 = startr .+^ start_vec+
src/Wumpus/Drawing/Paths/Base.hs view
@@ -5,7 +5,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Paths.Base--- Copyright : (c) Stephen Tetley 2010-2011+-- Copyright : (c) Stephen Tetley 2010-2012 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>@@ -14,6 +14,15 @@ -- -- Absolute path type - this should be more amenable for building -- complex drawings than the PrimPath type in Wumpus-Core.+--+-- Note - there is no concatenation (i.e. no Monoid instance),+-- this is because concatenating \*\* absolute \*\* paths has no +-- obvious interpretation - draw a join between the paths, move+-- the second path to start where the first ends...+--+-- Use @CatTrail@ from Wumpus-Basic if you need a relative-path +-- like object that supports concatenation, then convert it in a +-- final step to an @AbsPath@. -- -------------------------------------------------------------------------------- @@ -36,7 +45,7 @@ , vectorPath , vectorPathTheta - , placedTrailPath+ , anaTrailPath , catTrailPath -- * Queries@@ -53,19 +62,20 @@ -- * Conversion , toPrimPath - , drawPath- , drawPath_+ , renderPath+ , renderPath_ -- * Shortening , shortenPath , shortenL , shortenR - -- * Tips and direction+ -- * Tips and inclination , tipL , tipR- , directionL- , directionR+ , inclinationL+ , inclinationR+ , isBezierL , isBezierR @@ -94,15 +104,18 @@ , roundExterior , roundInterior + , deBezier+ , pathMajorPoints+ , pathAllPoints+ -- * Path division , pathdiv ) where -+import Wumpus.Drawing.Basis.BezierCurve -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Basic.Utils.JoinList ( JoinList, ViewL(..), viewl , ViewR(..), viewr, cons, snoc )@@ -210,17 +223,88 @@ -------------------------------------------------------------------------------- -- Translate --- Translate is cheap on AbsPath +-- | AbsPathSegments are build from vectors so they do not+-- respond to translation.+--+instance Num u => Translate (AbsPathSeg u) where+ translate _ _ s1 = s1+++instance (Floating u, Ord u, Tolerance u) => Scale (AbsPathSeg u) where+ scale sx sy (AbsLineSeg _ v1) = absLineSeg $ scale sx sy v1+ scale sx sy (AbsCurveSeg _ v1 v2 v3) = + absCurveSeg (scale sx sy v1) (scale sx sy v2) (scale sx sy v3)++++-- | Translate is cheap on AbsPath it just moves the start and+-- end points. The path itself is otherwise built from vectors+-- so it doesn\'t respond to translation (translate == id).+-- instance Num u => Translate (AbsPath u) where translate x y (AbsPath len sp se ep) = AbsPath len (translate x y sp) se (translate x y ep) +-- | This is expensive on paths - needs a traversal.+--+instance (Floating u, Ord u, Tolerance u) => Scale (AbsPath u) where+ scale sx sy = rebuildPath (scale sx sy) (scale sx sy)+ (\v1 v2 v3 -> ( scale sx sy v1+ , scale sx sy v2+ , scale sx sy v3 ))+++-- | This is expensive on paths - needs a traversal.+--+instance (Real u, Floating u, Ord u, Tolerance u) => Rotate (AbsPath u) where+ rotate ang = rebuildPath (rotate ang) (rotate ang)+ (\v1 v2 v3 -> ( rotate ang v1+ , rotate ang v2+ , rotate ang v3 ))++-- | This is expensive on paths - needs a traversal.+--+instance (Real u, Floating u, Ord u, Tolerance u) => RotateAbout (AbsPath u) where+ rotateAbout ang pt = + rebuildPath (rotateAbout ang pt) (rotateAbout ang pt)+ (\v1 v2 v3 -> ( rotateAbout ang pt v1+ , rotateAbout ang pt v2+ , rotateAbout ang pt v3 ))+++++rebuildPath :: (Floating u, Ord u, Tolerance u) + => (Point2 u -> Point2 u) + -> (Vec2 u -> Vec2 u) + -> (Vec2 u -> Vec2 u -> Vec2 u -> (Vec2 u, Vec2 u, Vec2 u))+ -> AbsPath u + -> AbsPath u+rebuildPath pointf linef curvef (AbsPath _ sp segs _) = + step (emptyPath $ pointf sp) (viewl segs)+ where+ step ac EmptyL = ac++ step ac (AbsLineSeg _ v1 :< xs) = + step (snocLine ac $ linef v1) (viewl xs) ++ step ac (AbsCurveSeg _ v1 v2 v3 :< xs) = + step (snocCurve ac $ curvef v1 v2 v3) (viewl xs) + -------------------------------------------------------------------------------- -- Construction +absLineSeg :: Floating u => Vec2 u -> AbsPathSeg u+absLineSeg v1 = AbsLineSeg (vlength v1) v1++absCurveSeg :: (Floating u, Ord u, Tolerance u) + => Vec2 u -> Vec2 u -> Vec2 u -> AbsPathSeg u+absCurveSeg v1 v2 v3 = + AbsCurveSeg (bezierLength $ vbezierCurve v1 v2 v3 zeroPt) v1 v2 v3+ -- | Create the empty path. -- -- Note - an absolute path needs /locating/ and cannot be built @@ -237,10 +321,9 @@ -- supplied points. -- line1 :: Floating u => Point2 u -> Point2 u -> AbsPath u -line1 p0 p1 = AbsPath len p0 (JL.one $ AbsLineSeg len v1) p1+line1 p0 p1 = AbsPath len p0 (JL.one s1) p1 where- v1 = pvec p0 p1- len = vlength v1+ s1@(AbsLineSeg len _) = absLineSeg $ pvec p0 p1 -- | Create an absolute path from a single cubic Bezier curve. --@@ -320,10 +403,10 @@ vectorPathTheta vs ang = vectorPath $ map (rotate ang) vs -placedTrailPath :: (Floating u, Ord u, Tolerance u) - => Point2 u -> PlacedTrail u -> AbsPath u-placedTrailPath pt trl = - let (v1,ss) = destrPlacedTrail trl in step (emptyPath $ pt .+^ v1) ss+anaTrailPath :: (Floating u, Ord u, Tolerance u) + => Point2 u -> AnaTrail u -> AbsPath u+anaTrailPath pt trl = + let (v1,ss) = destrAnaTrail trl in step (emptyPath $ pt .+^ v1) ss where step ac [] = ac step ac (TLine v1:xs) = step (ac `snocLine` v1) xs@@ -468,15 +551,15 @@ -drawPath :: InterpretUnit u +renderPath :: InterpretUnit u => PathMode -> AbsPath u -> Image u (AbsPath u)-drawPath mode rp = replaceAns rp $ +renderPath mode rp = replaceAns rp $ liftQuery (toPrimPath rp) >>= dcPath mode -drawPath_ :: InterpretUnit u +renderPath_ :: InterpretUnit u => PathMode -> AbsPath u -> Graphic u-drawPath_ mode rp = liftQuery (toPrimPath rp) >>= dcPath mode+renderPath_ mode rp = liftQuery (toPrimPath rp) >>= dcPath mode -- | Turn a Path into an ordinary PrimPath.@@ -552,7 +635,7 @@ => u -> Point2 u -> AbsPathSeg u -> (Point2 u, AbsPathSeg u) shortenSegL n sp (AbsLineSeg u v1) = let v2 = shortenVec n v1 - sp' = sp .+^ (v1 ^-^ v2)+ sp' = sp .+^ avec (vdirection v1) n in (sp', AbsLineSeg (u-n) v2) shortenSegL n sp (AbsCurveSeg u v1 v2 v3) = @@ -586,7 +669,7 @@ | otherwise = step n (viewr segs) endpt where step _ EmptyR _ = AbsPath 0 sp mempty sp - step d (se :> e) ep = let z = segmentLength e + step d (se :> e) ep = let z = segmentLength e enext = ep .-^ segmentVector e in case compare d z of GT -> step (d-z) (viewr se) enext@@ -606,7 +689,7 @@ => u -> AbsPathSeg u -> Point2 u -> (AbsPathSeg u, Point2 u) shortenSegR n (AbsLineSeg u v1) ep = let v2 = shortenVec n v1 - ep' = ep .-^ (v1 ^+^ v2)+ ep' = ep .-^ avec (vdirection v1) n in (AbsLineSeg (u-n) v2, ep') shortenSegR n (AbsCurveSeg u v1 v2 v3) ep = @@ -636,24 +719,28 @@ -------------------------------------------------------------------------------- -- line direction ++ -- | Direction of empty path is considered to be 0. ---directionL :: (Real u, Floating u) => AbsPath u -> Radian-directionL (AbsPath _ _ se _) = step $ viewl se+inclinationL :: (Real u, Floating u) => AbsPath u -> Radian+inclinationL (AbsPath _ _ se _) = step $ viewl se where- step (AbsLineSeg _ v1 :< _) = vdirection $ negateV v1- step (AbsCurveSeg _ v1 _ _ :< _) = vdirection $ negateV v1+ step (AbsLineSeg _ v1 :< _) = vdirection v1+ step (AbsCurveSeg _ v1 _ _ :< _) = vdirection v1 step _ = 0 -- | Direction of empty path is considered to be 0. ---directionR :: (Real u, Floating u) => AbsPath u -> Radian-directionR (AbsPath _ _ se _) = step $ viewr se+inclinationR :: (Real u, Floating u) => AbsPath u -> Radian+inclinationR (AbsPath _ _ se _) = step $ viewr se where step (_ :> AbsLineSeg _ v1) = vdirection v1 step (_ :> AbsCurveSeg _ _ _ v3) = vdirection v3 step _ = 0++ -- | Is the left tip a Bezier curve? --@@ -682,7 +769,7 @@ midway :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian) midway pa@(AbsPath u sp _ _) | u == 0 = (sp,0)- | otherwise = let pa1 = shortenR (u/2) pa in (tipR pa1, directionR pa1)+ | otherwise = let pa1 = shortenR (u/2) pa in (tipR pa1, inclinationR pa1) -- Just the midway point. --@@ -691,14 +778,14 @@ atstart :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)-atstart pa@(AbsPath _ sp _ _) = (sp, directionL pa)+atstart pa@(AbsPath _ sp _ _) = (sp, inclinationL pa) atstart_ :: AbsPath u -> Point2 u atstart_ (AbsPath _ sp _ _) = sp atend :: (Real u, Floating u) => AbsPath u -> (Point2 u, Radian)-atend pa@(AbsPath _ _ _ ep) = (ep, directionR pa)+atend pa@(AbsPath _ _ _ ep) = (ep, inclinationR pa) atend_ :: AbsPath u -> Point2 u@@ -857,7 +944,7 @@ -- -- The path is treated as open - the start of the initial and end -- of the final segments are not rounded. Only straight line to --- straight line joins are rounded, joins to or from Beczier +-- straight line joins are rounded, joins to or from Bezier -- curves are not rounded. -- -- Caution - all path segments are expected to be longer than@@ -896,7 +983,8 @@ base_vec = tv1 ^+^ tv2 bw = vlength base_vec h = sqrt $ pow2 du - (pow2 $ 0.5 * bw)- tcurve = tricurve bw (-h) (vdirection base_vec)+ clockd = clockDirection v1 v2+ tcurve = triCurve clockd bw (-h) (vdirection base_vec) -- note the (-h) in tricurve is wrong, we need to account -- for CCW or CW properly...@@ -946,6 +1034,54 @@ step1 _ _ [] = error "roundExteriorCat - unreachable 2."+++-- | Redraw an 'AbsPath' replacing the Bezier curves with three +-- lines along the control vectors.+--+deBezier :: Floating u => AbsPath u -> AbsPath u+deBezier (AbsPath _ sp segs _) = + step (emptyPath sp) (viewl segs)+ where+ step ac EmptyL = ac++ step ac (AbsLineSeg _ v1 :< xs) = + step (ac `snocLine` v1) (viewl xs) ++ step ac (AbsCurveSeg _ v1 v2 v3 :< xs) = + step (ac `snocLine` v1 `snocLine` v2 `snocLine` v3) (viewl xs) ++-- | This does not extract the control points of Bezier curves.+-- +pathMajorPoints :: Num u => AbsPath u -> [Point2 u]+pathMajorPoints (AbsPath _ sp segs _) = sp : step sp (viewl segs)+ where+ step _ EmptyL = []++ step pt (AbsLineSeg _ v1 :< xs) = + let p1 = pt .+^ v1 in p1 : step p1 (viewl xs) ++ step pt (AbsCurveSeg _ v1 v2 v3 :< xs) = + let p1 = pt .+^ v1 in p1 : step (p1 .+^ (v2 ^+^ v3)) (viewl xs) + ++-- | This extracts the control points of Bezier curves.+-- +pathAllPoints :: Num u => AbsPath u -> [Point2 u]+pathAllPoints (AbsPath _ sp segs _) = sp : step sp (viewl segs)+ where+ step _ EmptyL = []+ + step pt (AbsLineSeg _ v1 :< xs) = + let p1 = pt .+^ v1 in p1 : step p1 (viewl xs) ++ step pt (AbsCurveSeg _ v1 v2 v3 :< xs) = + let p1 = pt .+^ v1 + p2 = p1 .+^ v2+ p3 = p2 .+^ v3+ in p1 : p2 : p3 : step p3 (viewl xs) ++ -------------------------------------------------------------------------------- -- Path division
+ src/Wumpus/Drawing/Paths/Illustrate.hs view
@@ -0,0 +1,61 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Illustrate+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Illustrate a path - show the construction of its Bezier curves.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Illustrate+ ( ++ path_as_control_box+ , path_with_control_points+ + ) where++import Wumpus.Drawing.Paths.Base++import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Colour+import Data.Monoid++++grey1 :: RGBi+grey1 = RGBi 200 200 200++-- | Illustrate the control points as a /boxed/ path - Bezier +-- curves are replaced with straight lines spanning the +-- control points.+--+path_as_control_box :: (Floating u, InterpretUnit u) => AbsPath u -> Graphic u+path_as_control_box path1 = pic1 `mappend` pic2+ where+ pic1 = localize (set_line_width 8 . stroke_colour grey1) $+ renderPath_ OSTROKE path1+ pic2 = localize (set_line_width 1 . stroke_colour black) $+ renderPath_ OSTROKE $ deBezier path1+++path_with_control_points :: (Floating u, InterpretUnit u) => AbsPath u -> Graphic u+path_with_control_points path1 = pic1 `mappend` pic2+ where+ pic1 = localize (fill_colour grey1) $+ mconcat $ map (disk1 `at`) $ pathAllPoints path1++ pic2 = localize (set_line_width 1 . stroke_colour black) $+ renderPath_ OSTROKE path1++ disk1 = dcDisk DRAW_FILL 3+
+ src/Wumpus/Drawing/Paths/Intersection.hs view
@@ -0,0 +1,318 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Drawing.Paths.Intersection+-- Copyright : (c) Stephen Tetley 2011-2012+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Intersection of Paths with (infinite) lines.+-- +--------------------------------------------------------------------------------++module Wumpus.Drawing.Paths.Intersection+ ( ++ Line(..)+ , inclinedLine+ , vectorLine+ , Ray(..)+ , inclinedRay++ , lineLineIntersection+ , linePathIntersection+ , linePathSegmentIntersection+ , rayPathIntersection+ , rayPathSegmentIntersection++ , rectangleRadialIntersect+ , isoscelesTriangleRadialIntersect++ ) where++import Wumpus.Drawing.Basis.BezierCurve+import Wumpus.Drawing.Basis.ShapeTrails+import Wumpus.Drawing.Paths.Base++import Wumpus.Basic.Kernel -- package: wumpus-basic+import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space++--------------------------------------------------------------------------------+++--+-- Private types - LineEquation, 2x2 matrix and bezier curve.+--+-- Although these types are /general/ exposing them just leads +-- to a bloated API.+--+-- If these types are fund to be more useful - they can go into +-- @Drawing.Basis@.+--+++-- | Line in equational form, i.e. @Ax + By + C = 0@.+--+data LineEquation u = LineEquation + { _line_eqn_A :: !u+ , _line_eqn_B :: !u+ , _line_eqn_C :: !u + }+ deriving (Eq,Show)++type instance DUnit (LineEquation u) = u+++-- | 'lineEquation' : @ point1 * point2 -> LineEquation @+-- +-- Construct a line in equational form bisecting the supplied +-- points.+--+lineEquation :: Num u => Point2 u -> Point2 u -> LineEquation u+lineEquation (P2 x1 y1) (P2 x2 y2) = LineEquation a b c + where+ a = y1 - y2+ b = x2 - x1+ c = (x1*y2) - (x2*y1)++-- | 2x2 matrix, considered to be in row-major form.+-- +-- > (M2'2 a b+-- > c d)+--+-- ++data Matrix2'2 u = M2'2 !u !u !u !u+ deriving (Eq)++type instance DUnit (Matrix2'2 u) = u+++-- | Determinant of a 2x2 matrix.+--+det2'2 :: Num u => Matrix2'2 u -> u+det2'2 (M2'2 a b c d) = a*d - b*c++++++--------------------------------------------------------------------------------++-- | Infinite line represented by two points.+--+data Line u = Line (Point2 u) (Point2 u)+ deriving (Eq,Show)++type instance DUnit (Line u) = u++++-- | 'inclinedLine' : @ point * ang -> Line @+--+++-- | Make an infinite line passing through the supplied point +-- inclined by @ang@.+--+inclinedLine :: Floating u => Point2 u -> Radian -> Line u+inclinedLine radial_ogin ang = Line radial_ogin (radial_ogin .+^ avec ang 100)++vectorLine :: Num u => Vec2 u -> Point2 u -> Line u+vectorLine v1 p0 = Line p0 (p0 .+^ v1)+++-- | A 'Ray' extends from the first point, through the second to+-- infinity.+--+-- ('Line' extends to infinity in both directions.+--+data Ray u = Ray (Point2 u) (Point2 u) + deriving (Eq,Show)++type instance DUnit (Ray u) = u+++-- | Make an infinite ray starting from the supplied point +-- inclined by @ang@.+--+inclinedRay :: Floating u => Point2 u -> Radian -> Ray u+inclinedRay ray_ogin ang = Ray ray_ogin (ray_ogin .+^ avec ang 100)+ +++++pointOnLineSeg :: (Real u, Floating u, Ord u, Tolerance u) + => Point2 u -> (Point2 u, Point2 u) -> Bool+pointOnLineSeg pt (p0,p1) + | pt == p0 || pt == p1 = True+ | otherwise = + vdirection v1 == vdirection v0 && vlength v1 `tLTE` vlength v0+ where+ v0 = pvec p0 p1+ v1 = pvec p0 pt+ ++-- | 'interLineLine' : @ line1 * line2 -> Maybe Point @+-- +-- Find the intersection of two lines, if there is one. +--+-- Lines are infinite they are represented by points on them, +-- they are not line segments.+--+-- An answer of @Nothing@ may indicate either the lines coincide+-- or the are parallel.+--+lineLineIntersection :: (Fractional u, Ord u, Tolerance u)+ => Line u -> Line u -> Maybe (Point2 u)+lineLineIntersection (Line p1 p2) (Line q1 q2) = + if det_co `tEQ` 0 then Nothing + else Just $ P2 (det_xm / det_co) (det_ym / det_co)+ where+ -- Ax + By + C = 0+ LineEquation a1 b1 c1 = lineEquation p1 p2+ LineEquation a2 b2 c2 = lineEquation q1 q2++ coeffM = M2'2 a1 b1 a2 b2+ det_co = det2'2 coeffM++ xM = M2'2 (negate c1) b1 (negate c2) b2+ det_xm = det2'2 xM++ yM = M2'2 a1 (negate c1) a2 (negate c2)+ det_ym = det2'2 yM+++linePathIntersection :: (Real u, Floating u, Ord u, Tolerance u) + => Line u -> AbsPath u -> Maybe (Point2 u)+linePathIntersection ln = step . pathViewL+ where+ step EmptyPathL = Nothing+ step (a :<< bs) = let ans = linePathSegmentIntersection ln a+ in case ans of+ Nothing -> step (pathViewL bs)+ _ -> ans++linePathSegmentIntersection :: (Real u, Floating u, Ord u, Tolerance u) + => Line u -> PathSegment u -> Maybe (Point2 u)+linePathSegmentIntersection ln1 (LineSeg _ p0 p1) = + mbWithin p0 p1 $ lineLineIntersection ln1 (Line p0 p1)++linePathSegmentIntersection (Line pa pb) (CurveSeg _ p0 p1 p2 p3) = + lineEqnCurveIntersection (lineEquation pa pb) (BezierCurve p0 p1 p2 p3)+++mbWithin :: (Real u, Floating u, Ord u, Tolerance u) + => Point2 u -> Point2 u -> Maybe (Point2 u) -> Maybe (Point2 u)+mbWithin p0 p1 mb = mb >>= \pt -> + if pointOnLineSeg pt (p0,p1) then Just pt else Nothing++lineEqnCurveIntersection :: (Floating u, Ord u, Tolerance u) + => LineEquation u -> BezierCurve u -> Maybe (Point2 u)+lineEqnCurveIntersection eqnline c0 = step c0+ where+ step c = case cut eqnline c of+ Left pt -> Just pt -- cut at start or end+ Right False -> Nothing+ Right True -> let (a,b) = subdivide c+ in case step a of+ Just pt -> Just pt+ Nothing -> step b+++rayPathIntersection :: (Real u, Floating u, Ord u, Tolerance u) + => Ray u -> AbsPath u -> Maybe (Point2 u)+rayPathIntersection ry = step . pathViewL+ where+ step EmptyPathL = Nothing+ step (a :<< bs) = let ans = rayPathSegmentIntersection ry a+ in case ans of+ Nothing -> step (pathViewL bs)+ _ -> ans++rayPathSegmentIntersection :: (Real u, Floating u, Ord u, Tolerance u) + => Ray u -> PathSegment u -> Maybe (Point2 u)+rayPathSegmentIntersection (Ray p0 p1) seg = + test =<< linePathSegmentIntersection (Line p0 p1) seg+ where+ test pt = if vdirection (pvec p0 p1) == vdirection (pvec p0 pt)+ then Just pt else Nothing+ +-- | Is the curve cut by the line? +--+-- The curve might cut at the start or end points - which is good+-- as it saves performing a subdivision, but it makes the return +-- type a bit involved.+--+cut :: (Floating u , Ord u, Tolerance u)+ => LineEquation u -> BezierCurve u -> Either (Point2 u) Bool+cut eqnline (BezierCurve p0 p1 p2 p3) = + if d0 `tEQ` 0 then Left p0 else+ if d3 `tEQ` 0 then Left p3 else+ let ds = [d0,d1,d2,d3] in Right $ not $ all pve ds || all nve ds+ where+ pve = (>= 0)+ nve = (< 0)+ d0 = pointLineDistance p0 eqnline + d1 = pointLineDistance p1 eqnline + d2 = pointLineDistance p2 eqnline + d3 = pointLineDistance p3 eqnline +++++-- | 'pointLineDistance' : @ point -> line -> Distance @+--+-- Find the distance from a point to a line in equational form+-- using this formula:+-- +-- > P(u,v) +-- > L: Ax + By + C = 0+-- >+-- > (A*u) + (B*v) + C +-- > -----------------+-- > sqrt $ (A^2) +(B^2)+--+-- A positive distance indicates the point is above the line, +-- negative indicates below.+--+pointLineDistance :: Floating u => Point2 u -> LineEquation u -> u+pointLineDistance (P2 u v) (LineEquation a b c) = + ((a*u) + (b*v) + c) / base+ where+ base = sqrt $ (a^two) + (b^two)+ two :: Integer+ two = 2+++--------------------------------------------------------------------------------+-- Intersections on common shapes++-- | Answer is vector from center.+--+rectangleRadialIntersect :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Radian -> Maybe (Vec2 u) +rectangleRadialIntersect w h ang = + fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp + where+ rp = anaTrailPath zeroPt $ rectangle_trail w h++++-- | Answer is vector from centroid.+--+isoscelesTriangleRadialIntersect :: (Real u, Floating u+ , InterpretUnit u, Tolerance u) + => u -> u -> Radian -> Maybe (Vec2 u) +isoscelesTriangleRadialIntersect bw h ang = + fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp + where+ rp = anaTrailPath zeroPt $ isosceles_triangle_trail bw h
src/Wumpus/Drawing/Paths/PathBuilder.hs view
@@ -4,7 +4,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.Paths.PathBuilder--- Copyright : (c) Stephen Tetley 2011+-- Copyright : (c) Stephen Tetley 2011-2012 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>@@ -90,7 +90,7 @@ getGenPathSpec :: DrawingContext -> PathSt st -> (a, PathSt st, CatPrim) } type instance DUnit (GenPathSpec st u a) = u-type instance UState (GenPathSpec st u) = st+type instance UState (GenPathSpec st u a) = st type PathSpec u a = GenPathSpec () u a @@ -228,7 +228,7 @@ dpath = translate dx dy $ st_cumulative_path s1 upath = dinterpF (dc_font_size ctx) dpath pctx = st_pen_ctx s1- (_,w2) = runImage pctx (drawActivePen mode $ st_active_pen s1) + (_,w2) = runImage pctx (renderActivePen mode $ st_active_pen s1) wfinal = cpmove (V2 dx dy) $ w1 `mappend` w2 in replaceAns (a, st_user_state s1, upath) $ primGraphic wfinal @@ -293,9 +293,9 @@ -- | Helper. ---drawActivePen :: PathMode -> ActivePen -> DGraphic -drawActivePen _ PEN_UP = mempty-drawActivePen mode (PEN_DOWN abs_path) = drawPath_ mode abs_path+renderActivePen :: PathMode -> ActivePen -> DGraphic +renderActivePen _ PEN_UP = mempty+renderActivePen mode (PEN_DOWN abs_path) = renderPath_ mode abs_path @@ -317,7 +317,7 @@ dp1 = normalizeF (dc_font_size ctx) p1 v1 = pvec dpt dp1 pctx = st_pen_ctx s1- (_,w2) = runImage pctx $ drawActivePen OSTROKE $ st_active_pen s1+ (_,w2) = runImage pctx $ renderActivePen OSTROKE $ st_active_pen s1 wfinal = w1 `mappend` w2 in primGraphic $ cpmove (negateV v1) wfinal where@@ -393,7 +393,7 @@ movebyImpl v1 = GenPathSpec $ \ctx s@(PathSt {st_pen_ctx = pctx}) -> let sz = dc_font_size ctx dv1 = normalizeF sz v1- (_,w1) = runImage pctx $ drawActivePen OSTROKE $ st_active_pen s+ (_,w1) = runImage pctx $ renderActivePen OSTROKE $ st_active_pen s cpath = snocLine (st_cumulative_path s) dv1 in ((), s { st_active_pen = PEN_UP, st_cumulative_path = cpath }, w1) @@ -433,7 +433,7 @@ vamp (Vamp v1 conn) = GenPathSpec $ \ctx s@(PathSt {st_pen_ctx = pctx}) -> let sz = dc_font_size ctx dv1 = normalizeF sz v1- (_,w1) = runImage pctx $ drawActivePen OSTROKE $ st_active_pen s+ (_,w1) = runImage pctx $ renderActivePen OSTROKE $ st_active_pen s upt = dinterpF sz (tipR $ st_cumulative_path s) (_,w2) = runConnectorImage ctx upt (upt .+^ v1) conn cpath = snocLine (st_cumulative_path s) dv1@@ -443,7 +443,7 @@ cycleSubPath :: DrawMode -> GenPathSpec st u () cycleSubPath mode = GenPathSpec $ \_ s@(PathSt {st_pen_ctx = pctx}) ->- let (_,w1) = runImage pctx $ drawActivePen (fn mode) (st_active_pen s)+ let (_,w1) = runImage pctx $ renderActivePen (fn mode) (st_active_pen s) in ((), s { st_active_pen = PEN_UP }, w1) where fn DRAW_STROKE = CSTROKE
src/Wumpus/Drawing/Paths/Vamps.hs view
@@ -43,7 +43,7 @@ where conn = promoteConn $ \p1 p2 -> let dir = vdirection $ pvec p1 p2- in drawPath_ CSTROKE $ vectorPathTheta path1 dir p1+ in renderPath_ CSTROKE $ vectorPathTheta path1 dir p1 hdiam = 0.5 * diam path1 = [ vvec hdiam, hvec diam, vvec (-diam), hvec (-diam) ]
src/Wumpus/Drawing/Shapes/Base.hs view
@@ -42,6 +42,7 @@ , makeShapeCTM , ctmCenter , ctmAngle+ , ctmLocale , projectFromCtr ) where@@ -132,7 +133,7 @@ -- Probably Wumpus should calculate two paths instead. -- dblStrokedShape :: InterpretUnit u => Shape t u -> LocImage u (t u)-dblStrokedShape sh = sdecorate back fore +dblStrokedShape sh = decorateAbove back fore where img = shapeToLoc (dcClosedPath DRAW_STROKE) sh back = getLineWidth >>= \lw ->@@ -155,7 +156,7 @@ applyLocTheta (liftLocThetaQuery $ shape_ans_fun sh) pt 0 >>= \a -> applyLocTheta (liftLocThetaQuery $ shape_path_fun sh) pt 0 >>= \spath -> let g2 = atIncline (shape_decoration sh) pt 0 - in replaceAns a (sdecorate g2 $ liftQuery (toPrimPath spath) >>= drawF)+ in replaceAns a (decorateAbove g2 $ liftQuery (toPrimPath spath) >>= drawF) @@ -177,7 +178,7 @@ applyLocTheta (liftLocThetaQuery $ shape_ans_fun sh) pt theta >>= \a -> applyLocTheta (liftLocThetaQuery $ shape_path_fun sh) pt theta >>= \spath -> let g2 = atIncline (shape_decoration sh) pt theta- in replaceAns a $ sdecorate g2 (liftQuery (toPrimPath spath) >>= drawF)+ in replaceAns a $ decorateAbove g2 (liftQuery (toPrimPath spath) >>= drawF) @@ -246,6 +247,9 @@ ctmAngle :: ShapeCTM u -> Radian ctmAngle = ctm_rotation++ctmLocale :: ShapeCTM u -> (Point2 u, Radian)+ctmLocale ctm = (ctm_center ctm, ctm_rotation ctm) instance (Fractional u) => Scale (ShapeCTM u) where
src/Wumpus/Drawing/Shapes/Diamond.hs view
@@ -25,12 +25,14 @@ ) where ++import Wumpus.Drawing.Basis.ShapeTrails+import Wumpus.Drawing.Basis.Geometry import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Geometry.Quadrant-import Wumpus.Basic.Kernel +import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core @@ -123,14 +125,21 @@ -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Diamond u) where radialAnchor ang = runDisplaceCenter $ \hw hh -> - diamondRadialVector hw hh ang+ maybe zeroVec id $ diamondRadialAnchor hw hh ang +diamondRadialAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Radian -> Maybe (Vec2 u) +diamondRadialAnchor hw hh ang = + fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp + where+ rp = anaTrailPath zeroPt $ diamond_trail (2*hw) (2*hh) + -------------------------------------------------------------------------------- -- Construction @@ -140,7 +149,7 @@ -- diamond :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Diamond u-diamond hw hh = makeShape (mkDiamond hw hh) (mkDiamondPath 0 hw hh)+diamond hw hh = makeShape (mkDiamond hw hh) (mkDiamondPath hw hh) mkDiamond :: InterpretUnit u => u -> u -> LocThetaQuery u (Diamond u)@@ -152,11 +161,7 @@ mkDiamondPath :: (Real u, Floating u, InterpretUnit u, Tolerance u)- => u -> u -> u -> LocThetaQuery u (AbsPath u)-mkDiamondPath rnd hw hh = qpromoteLocTheta $ \ctr theta -> - qapplyLoc (placedTrailPoints $ diamondTrail hw hh) ctr >>= \ps ->- roundCornerShapePath rnd $ map (rotateAbout theta ctr) ps---+ => u -> u -> LocThetaQuery u (AbsPath u)+mkDiamondPath hw hh = qpromoteLocTheta $ \ctr theta -> + return $ anaTrailPath ctr $ rdiamond_trail (2*hw) (2*hh) theta
src/Wumpus/Drawing/Shapes/Ellipse.hs view
@@ -27,6 +27,7 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Paths import Wumpus.Drawing.Shapes.Base @@ -148,8 +149,7 @@ mkEllipsePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> LocThetaQuery u (AbsPath u)-mkEllipsePath rx ry = qpromoteLocTheta $ \pt theta -> - let xs = map (rotateAbout theta pt) $ bezierEllipse rx ry pt- in return $ curvePath xs+mkEllipsePath rx ry = qpromoteLocTheta $ \ctr theta -> + return $ anaTrailPath ctr $ rellipse_trail rx ry theta
src/Wumpus/Drawing/Shapes/InvSemicircle.hs view
@@ -100,7 +100,7 @@ west = runRotateAnchor east -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (InvSemicircle u) where northeast = runRotateAnchor southwest southeast = runRotateAnchor northwest@@ -109,7 +109,7 @@ -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (InvSemicircle u) where radialAnchor theta = runRotateAnchor (radialAnchor $ circularModulo $ pi+theta)
src/Wumpus/Drawing/Shapes/InvSemiellipse.hs view
@@ -93,7 +93,7 @@ topLeftCorner = runRotateAnchor bottomRightCorner topRightCorner = runRotateAnchor bottomLeftCorner -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor (InvSemiellipse u) where north = runRotateAnchor south south = runRotateAnchor north@@ -101,7 +101,7 @@ west = runRotateAnchor east -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (InvSemiellipse u) where northeast = runRotateAnchor southwest southeast = runRotateAnchor northwest@@ -110,7 +110,7 @@ -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (InvSemiellipse u) where radialAnchor theta = runRotateAnchor (radialAnchor $ circularModulo $ pi+theta)
src/Wumpus/Drawing/Shapes/InvTriangle.hs view
@@ -25,11 +25,11 @@ ) where +import Wumpus.Drawing.Basis.Geometry import Wumpus.Drawing.Shapes.Base import Wumpus.Drawing.Shapes.Triangle -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Kernel+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core @@ -122,7 +122,7 @@ west = runRotateAnchor east -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (InvTriangle u) where northeast = runRotateAnchor southwest southeast = runRotateAnchor northwest@@ -131,7 +131,7 @@ -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (InvTriangle u) where radialAnchor theta = runRotateAnchor (radialAnchor $ circularModulo $ pi+theta)
src/Wumpus/Drawing/Shapes/Parallelogram.hs view
@@ -27,12 +27,15 @@ ) where +import Wumpus.Drawing.Basis.Geometry+import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry -- package: wumpus-basic-import Wumpus.Basic.Kernel +import Wumpus.Basic.Kernel -- package: wumpus-basic+ import Wumpus.Core -- package: wumpus-core import Data.VectorSpace -- package: vector-space@@ -48,10 +51,10 @@ -- | A Paralleogram. -- data Parallelogram u = Parallelogram - { pll_ctm :: ShapeCTM u- , pll_base_width :: !u- , pll_height :: !u- , pll_base_l_ang :: Radian+ { pll_ctm :: ShapeCTM u+ , pll_base_width :: !u+ , pll_height :: !u+ , pll_base_left_ang :: Radian } type instance DUnit (Parallelogram u) = u@@ -88,21 +91,28 @@ -------------------------------------------------------------------------------- -- Anchors --- | 'runDisplaceCenter' : @ ( half_base_width--- * half_height +-- | 'runDisplaceCenter' : @ ( base_width+-- * height -- * base_minor--- * base_major -> Vec ) * parallelogram -> Point @+-- -> Vec ) * parallelogram -> Point @ -- runDisplaceCenter :: (Real u, Floating u) => (u -> u -> Radian -> Vec2 u) -> Parallelogram u -> Anchor u-runDisplaceCenter fn (Parallelogram { pll_ctm = ctm- , pll_base_width = bw- , pll_height = h - , pll_base_l_ang = lang }) =- projectFromCtr (fn (0.5 * bw) (0.5 * h) lang) ctm+runDisplaceCenter fn (Parallelogram { pll_ctm = ctm+ , pll_base_width = bw+ , pll_height = h + , pll_base_left_ang = lang }) =+ projectFromCtr (fn bw h lang) ctm +runDisplaceCenterHalves :: (Real u, Floating u)+ => (u -> u -> Radian -> Vec2 u) + -> Parallelogram u + -> Anchor u+runDisplaceCenterHalves fn = + runDisplaceCenter $ \bw h bl_ang -> fn (0.5*bw) (0.5*h) bl_ang + instance (Real u, Floating u) => CenterAnchor (Parallelogram u) where center = runDisplaceCenter $ \_ _ _ -> V2 0 0@@ -115,18 +125,18 @@ instance (Real u, Floating u) => TopCornerAnchor (Parallelogram u) where- topLeftCorner = runDisplaceCenter $ \hw hh lang -> + topLeftCorner = runDisplaceCenterHalves $ \hw hh lang -> let hypo = hh / (fromRadian $ sin lang) in hvec (-hw) ^+^ avec lang hypo - topRightCorner = runDisplaceCenter $ \hw hh lang ->+ topRightCorner = runDisplaceCenterHalves $ \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 $ \hw hh lang ->+ bottomLeftCorner = runDisplaceCenterHalves $ \hw hh lang -> let hypo = hh / (fromRadian $ sin lang) in hvec (-hw) ^+^ avec lang (-hypo) - bottomRightCorner = runDisplaceCenter $ \hw hh lang -> + bottomRightCorner = runDisplaceCenterHalves $ \hw hh lang -> let hypo = hh / (fromRadian $ sin lang) in hvec hw ^+^ avec lang (-hypo) @@ -142,28 +152,30 @@ -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance 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 = radialAnchor (0.5 * pi)+ south = radialAnchor (1.5 * pi)+ east = radialAnchor 0+ west = radialAnchor pi instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Parallelogram u) where- northeast = pllRadialAnchor (0.25*pi)- southeast = pllRadialAnchor (1.75*pi)- southwest = pllRadialAnchor (1.25*pi)- northwest = pllRadialAnchor (0.75*pi)+ northeast = radialAnchor (0.25*pi)+ southeast = radialAnchor (1.75*pi)+ southwest = radialAnchor (1.25*pi)+ northwest = radialAnchor (0.75*pi) instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Parallelogram u) where- radialAnchor = pllRadialAnchor+ radialAnchor ang = runDisplaceCenter $ \bw h bl_ang-> + maybe zeroVec id $ pllRadialAnchor bw h bl_ang ang + -- | Note - it is not worth changing this to a quadrantAlg. -- -- There are pathological parallelograms that the current @@ -171,19 +183,12 @@ -- 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_base_width = bw- , pll_height = h- , pll_base_l_ang = lang }) =- post $ findIntersect zeroPt theta $ polygonLineSegments ps- where - ps = runVertices4 zeroPt $ parallelogramVertices bw h lang+ => u -> u -> Radian -> Radian -> Maybe (Vec2 u)+pllRadialAnchor bw h bl_ang ang =+ fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp + where+ rp = anaTrailPath zeroPt $ parallelogram_trail bw h bl_ang - post = \ans -> case ans of - Nothing -> projectFromCtr (V2 0 0) ctm- Just (P2 x y) -> projectFromCtr (V2 x y) ctm- -------------------------------------------------------------------------------- -- Construction@@ -195,7 +200,7 @@ parallelogram :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Radian -> Shape Parallelogram u parallelogram bw h lang =- makeShape (mkParallelogram bw h lang) (mkParallelogramPath 0 bw h lang)+ makeShape (mkParallelogram bw h lang) (mkParallelogramPath bw h lang) -- | 'zparallelogram' : @ base_width * height -> Parallelogram @@@ -213,21 +218,21 @@ mkParallelogram :: (Real u, Fractional u, InterpretUnit u, Tolerance u) => 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+mkParallelogram bw h bl_ang = qpromoteLocTheta $ \ctr theta -> + pure $ Parallelogram { pll_ctm = makeShapeCTM ctr theta+ , pll_base_width = bw+ , pll_height = h+ , pll_base_left_ang = bl_ang } mkParallelogramPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => 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 + => u -> u -> Radian -> LocThetaQuery u (AbsPath u)+mkParallelogramPath bw h bl_ang = qpromoteLocTheta $ \ctr theta -> + return $ anaTrailPath ctr $ rparallelogram_trail bw h bl_ang theta+
src/Wumpus/Drawing/Shapes/Rectangle.hs view
@@ -27,10 +27,11 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry -- package: wumpus-basic import Wumpus.Basic.Kernel import Wumpus.Core -- package: wumpus-core@@ -124,7 +125,7 @@ east = runDisplaceCenter $ \hw _ -> V2 hw 0 west = runDisplaceCenter $ \hw _ -> V2 (-hw) 0 -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Rectangle u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi)@@ -132,11 +133,10 @@ northwest = radialAnchor (0.75*pi) -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Rectangle u) where- radialAnchor theta = runDisplaceCenter $ \hw hh -> - rectRadialVector hw hh theta-+ radialAnchor ang = runDisplaceCenter $ \hw hh -> + maybe zeroVec id $ rectangleRadialIntersect (2*hw) (2*hh) ang --------------------------------------------------------------------------------@@ -148,7 +148,7 @@ rectangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Rectangle u rectangle w h = - makeShape (mkRectangle (0.5*w) (0.5*h)) (mkRectPath 0 (0.5*w) (0.5*h))+ makeShape (mkRectangle (0.5*w) (0.5*h)) (mkRectPath (0.5*w) (0.5*h)) mkRectangle :: InterpretUnit u => u -> u -> LocThetaQuery u (Rectangle u)@@ -158,12 +158,12 @@ , rect_hh = hh } - mkRectPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> u -> LocThetaQuery u (AbsPath u)-mkRectPath rnd hw hh = qpromoteLocTheta $ \ctr theta -> - let xs = runVertices4 ctr $ rectangleVertices hw hh- in roundCornerShapePath rnd $ map (rotateAbout theta ctr) xs- + => u -> u -> LocThetaQuery u (AbsPath u)+mkRectPath hw hh = qpromoteLocTheta $ \ctr theta -> + return $ anaTrailPath ctr $ rrectangle_trail (2*hw) (2*hh) theta+++
src/Wumpus/Drawing/Shapes/Semicircle.hs view
@@ -24,18 +24,16 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Geometry.Intersection-import Wumpus.Basic.Kernel+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace -- package: vector-space - import Control.Applicative @@ -50,15 +48,6 @@ type instance DUnit (Semicircle u) = u --- | Height minor and major.----data SyntheticProps u = SP- { sc_hminor :: u- , sc_hmajor :: u- }--type instance DUnit (SyntheticProps u) = u- type DSemicircle = Semicircle Double @@ -76,14 +65,15 @@ -- -- 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 +hminor :: Floating u => u -> u+hminor radius = (4 * radius) / (3 * pi)++hmajor :: Floating u => u -> u+hmajor radius = radius - hminor radius++ -------------------------------------------------------------------------------- -- Affine trans @@ -112,34 +102,31 @@ -- * height_major -> Vec ) * semicircle -> Point @ -- runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> u -> Vec2 u) -> Semicircle u -> Anchor u+ => (u -> Vec2 u) -> Semicircle u -> Anchor u runDisplaceCenter fn (Semicircle { sc_ctm = ctm , sc_radius = radius }) = - projectFromCtr (fn radius hminor hmajor) ctm- where- props = synthesizeProps radius - hminor = sc_hminor props- hmajor = sc_hmajor props+ projectFromCtr (fn radius) ctm + instance (Real u, Floating u) => CenterAnchor (Semicircle u) where- center = runDisplaceCenter $ \_ _ _ -> V2 0 0+ center = runDisplaceCenter $ \_ -> V2 0 0 instance (Real u, Floating u) => ApexAnchor (Semicircle u) where- apex = runDisplaceCenter $ \_ _ cmaj -> V2 0 cmaj+ apex = runDisplaceCenter $ \r -> V2 0 (hmajor r) instance (Real u, Floating u) => BottomCornerAnchor (Semicircle u) where- bottomLeftCorner = runDisplaceCenter $ \r hminor _ -> V2 (-r) (-hminor)- bottomRightCorner = runDisplaceCenter $ \r hminor _ -> V2 r (-hminor)+ bottomLeftCorner = runDisplaceCenter $ \r -> V2 (-r) (negate $ hminor r)+ bottomRightCorner = runDisplaceCenter $ \r -> V2 r (negate $ hminor r) instance (Real u, Floating u) => CardinalAnchor (Semicircle u) where north = apex- south = runDisplaceCenter $ \_ cmin _ -> V2 0 (-cmin)- east = runDisplaceCenter $ \r cmin _ -> let x = pyth r cmin in V2 x 0- west = runDisplaceCenter $ \r cmin _ -> let x = pyth r cmin in V2 (-x) 0+ south = runDisplaceCenter $ \r -> V2 0 (negate $ hminor r)+ east = runDisplaceCenter $ \r -> let x = pyth r (hminor r) in V2 x 0+ west = runDisplaceCenter $ \r -> let x = pyth r (hminor r) in V2 (-x) 0 -- | Use Pythagoras formula for working out the /east/ and /west/ -- distances. A right-triangle is formed below the centroid, @@ -151,7 +138,7 @@ pow2 = (^ (2::Int)) -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Semicircle u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi)@@ -161,70 +148,21 @@ -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Semicircle u) where- radialAnchor theta = runDisplaceCenter (scRadialVec theta)---- 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 (circularModulo theta)- where- (lang,rang) = baselineRange radius hminor- (bctr, br, _, bl) = constructionPoints radius hminor- 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----mkCurve :: Floating u => u -> Radian -> Point2 u -> BezierCurve u-mkCurve radius theta ctr = BezierCurve p0 p1 p2 p3- where- (BezierCurve p0 p1 p2 p3) = bezierMinorArc half_pi radius theta ctr+ radialAnchor ang = runDisplaceCenter $ \r ->+ maybe zeroVec id $ semicircleRadialAnchor r ang --- | 'constructionPoints' : @ radius * hminor -> --- (base_ctr, base_right, apex, base_left) @------ Assumes centroid is (0,0).----constructionPoints :: Num u - => u -> u -> (Point2 u, Point2 u, Point2 u, Point2 u)-constructionPoints radius hminor = (bctr, br, apx, bl)+semicircleRadialAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> Radian -> Maybe (Vec2 u) +semicircleRadialAnchor r ang = + fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp where- bctr = P2 0 (-hminor)- br = bctr .+^ hvec radius- apx = bctr .+^ vvec radius- bl = bctr .+^ hvec (-radius)--+ rp = anaTrailPath zeroPt $ semicircle_trail r --- | 'baselineRange' : @ radius * hminor -> (left_base_ang, right_base_ang) @------ Find the angle range where a ray from the centroid will cross--- the baseline rather than cut the curve.----baselineRange :: (Real u, Floating u) => u -> u -> (Radian, Radian)-baselineRange radius hminor = (lang, rang)- where- ang = toRadian $ atan (radius / hminor)- lang = (1.5*pi) - ang- rang = (1.5*pi) + ang- -------------------------------------------------------------------------------- -- Construction @@ -232,10 +170,7 @@ -- semicircle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> Shape Semicircle u-semicircle radius = - let props = synthesizeProps radius- in makeShape (mkSemicircle radius) - (mkSemicirclePath radius (sc_hminor props))+semicircle radius = makeShape (mkSemicircle radius) (mkSemicirclePath radius) @@ -252,8 +187,7 @@ -- the center properly... -- mkSemicirclePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> LocThetaQuery u (AbsPath u)-mkSemicirclePath radius cminor = qpromoteLocTheta $ \pt theta ->- let ctr = dispPerpendicular (-cminor) theta pt- in pure $ curvePath $ bezierArcPoints pi radius theta ctr + => u -> LocThetaQuery u (AbsPath u)+mkSemicirclePath radius = qpromoteLocTheta $ \ctr theta ->+ return $ anaTrailPath ctr $ rsemicircle_trail radius theta
src/Wumpus/Drawing/Shapes/Semiellipse.hs view
@@ -24,17 +24,15 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry.Base -- package: wumpus-basic-import Wumpus.Basic.Geometry.Intersection-import Wumpus.Basic.Kernel+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace -- package: vector-space- import Control.Applicative @@ -51,12 +49,6 @@ type instance DUnit (Semiellipse u) = u -data SyntheticProps u = SP- { se_hminor :: u- , se_hmajor :: u- }--type instance DUnit (SyntheticProps u) = u type DSemiellipse = Semiellipse Double @@ -65,14 +57,13 @@ -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+ryminor :: Floating u => u -> u+ryminor ry = (4 * ry) / (3 * pi) +rymajor :: Floating u => u -> u+rymajor ry = ry - ryminor ry + -------------------------------------------------------------------------------- -- Affine trans @@ -103,41 +94,37 @@ -- * ry_major -> Vec ) * semiellipse -> Point @ -- runDisplaceCenter :: (Real u, Floating u) - => (u -> u -> u -> u -> Vec2 u) -> Semiellipse u -> Anchor u+ => (u -> u -> Vec2 u) -> Semiellipse u -> Anchor u runDisplaceCenter fn (Semiellipse { se_ctm = ctm , se_rx = rx , se_ry = ry }) = - projectFromCtr (fn rx ry hminor hmajor) ctm- where- props = synthesizeProps ry - hminor = se_hminor props- hmajor = se_hmajor props+ projectFromCtr (fn rx ry) ctm instance (Real u, Floating u) => CenterAnchor (Semiellipse u) where- center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0+ center = runDisplaceCenter $ \_ _ -> V2 0 0 instance (Real u, Floating u, Tolerance u) => ApexAnchor (Semiellipse u) where- apex = runDisplaceCenter $ \_ _ _ ry_major -> V2 0 ry_major+ apex = runDisplaceCenter $ \_ ry -> V2 0 (rymajor ry) instance (Real u, Floating u) => BottomCornerAnchor (Semiellipse u) where- bottomLeftCorner = runDisplaceCenter $ \rx _ ry_minor _ -> V2 (-rx) (-ry_minor)- bottomRightCorner = runDisplaceCenter $ \rx _ ry_minor _ -> V2 rx (-ry_minor)+ bottomLeftCorner = runDisplaceCenter $ \rx ry -> V2 (-rx) (negate $ ryminor ry)+ bottomRightCorner = runDisplaceCenter $ \rx ry -> V2 rx (negate $ ryminor ry) -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor (Semiellipse u) where north = apex- south = runDisplaceCenter $ \_ _ ry_minor _ -> V2 0 (-ry_minor)+ south = runDisplaceCenter $ \_ ry -> V2 0 (negate $ ryminor ry) east = radialAnchor 0 west = radialAnchor pi -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Semiellipse u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi)@@ -146,56 +133,18 @@ -instance (Real u, Floating u, Tolerance u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Semiellipse u) where- radialAnchor theta = runDisplaceCenter (seRadialVec theta)---seRadialVec :: (Real u, Floating u, Ord u, Tolerance u)- => Radian -> u -> u -> u -> u -> Vec2 u-seRadialVec theta rx ry hminor _ = go theta- where- (lang,rang) = baselineRange rx hminor- (bctr, br, _, bl) = constructionPoints rx ry hminor- 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)- 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------ | 'constructionPoints' : @ rx * ry * hminor -> --- (base_ctr, base_right, apex, base_left) @------ Assumes centroid is (0,0).----constructionPoints :: Num u - => u -> u -> u -> (Point2 u, Point2 u, Point2 u, Point2 u)-constructionPoints rx ry hminor = (bctr, br, apx, bl)- where- bctr = P2 0 (-hminor)- br = bctr .+^ hvec rx- apx = bctr .+^ vvec ry- bl = bctr .+^ hvec (-rx)--+ radialAnchor ang = runDisplaceCenter $ \rx ry ->+ maybe zeroVec id $ semiellipseRadialAnchor rx ry ang --- | 'baselineRange' : @ radius * hminor -> (left_base_ang, right_base_ang) @------ Find the angle range where a ray from the centroid will cross--- the baseline rather than cut the curve.----baselineRange :: (Real u, Floating u) => u -> u -> (Radian, Radian)-baselineRange rx hminor = (lang, rang)+semiellipseRadialAnchor :: (Real u, Floating u, InterpretUnit u, Tolerance u) + => u -> u -> Radian -> Maybe (Vec2 u) +semiellipseRadialAnchor rx ry ang = + fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp where- ang = toRadian $ atan (rx / hminor)- lang = (1.5*pi) - ang- rang = (1.5*pi) + ang-+ rp = anaTrailPath zeroPt $ semiellipse_trail rx ry --------------------------------------------------------------------------------@@ -206,10 +155,7 @@ -- semiellipse :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Semiellipse u-semiellipse rx ry = - let props = synthesizeProps ry- in makeShape (mkSemiellipse rx ry) - (mkSemiellipsePath rx ry (se_hminor props))+semiellipse rx ry = makeShape (mkSemiellipse rx ry) (mkSemiellipsePath rx ry) @@ -224,46 +170,7 @@ mkSemiellipsePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> u -> LocThetaQuery u (AbsPath u)-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 ---bezierSemiellipsePoints :: Floating u- => u -> u -> Point2 u -> [Point2 u]-bezierSemiellipsePoints rx ry pt = [ p0, c1,c2,p3, c4,c5,p6 ]- where - (BezierCurve p0 c1 c2 p3, BezierCurve _ c4 c5 p6) = bezierSemiellipse rx ry pt----- For Geometry?---- | Generate the bezier arcs for quadrants I and II. ------ Drawing is expected to proceed CCW.--- --- Note - Point is the (full) ellipse center.----bezierSemiellipse :: Floating u- => u -> u -> Point2 u -> (BezierCurve u, BezierCurve u)-bezierSemiellipse rx ry (P2 x y) = - (BezierCurve p00 c01 c02 p03, BezierCurve p03 c04 c05 p06)- where- lrx = rx * kappa- lry = ry * kappa- p00 = P2 (x + rx) y- c01 = p00 .+^ vvec lry- c02 = p03 .+^ hvec lrx-- p03 = P2 x (y + ry) - c04 = p03 .+^ hvec (-lrx)- c05 = p06 .+^ vvec lry-- p06 = P2 (x - rx) y--+ => u -> u -> LocThetaQuery u (AbsPath u)+mkSemiellipsePath rx ry = qpromoteLocTheta $ \ctr theta ->+ return $ anaTrailPath ctr $ rsemiellipse_trail rx ry theta -kappa :: Floating u => u-kappa = 4 * ((sqrt 2 - 1) / 3)
src/Wumpus/Drawing/Shapes/Trapezium.hs view
@@ -25,11 +25,12 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry -- package: wumpus-basic-import Wumpus.Basic.Kernel+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core @@ -46,10 +47,11 @@ -- | A trapezium. -- data Trapezium u = Trapezium - { tz_ctm :: ShapeCTM u- , tz_base_width :: !u- , tz_top_width :: !u- , tz_height :: !u+ { tz_ctm :: ShapeCTM u+ , tz_base_width :: !u+ , tz_top_width :: !u+ , tz_height :: !u+ , tz_bottom_left_ang :: Radian } type instance DUnit (Trapezium u) = u@@ -57,7 +59,8 @@ type DTrapezium = Trapezium Double instance Functor Trapezium where- fmap f (Trapezium ctm bw tw h) = Trapezium (fmap f ctm) (f bw) (f tw) (f h)+ fmap f (Trapezium ctm bw tw h ang) = + Trapezium (fmap f ctm) (f bw) (f tw) (f h) ang -------------------------------------------------------------------------------- -- Affine trans@@ -83,20 +86,34 @@ -- Anchors ---- | 'runDisplaceCenter' : @ ( half_base_width --- * half_top_width--- * half_height -> Vec ) * trapezium -> Point @+-- | 'runDisplaceCenter' : @ ( base_width +-- * height+-- * bl_ang -> Vec ) * trapezium -> Point @ -- runDisplaceCenter :: (Real u, Floating u)- => (u -> u -> u -> Vec2 u) + => (u -> u -> Radian -> Vec2 u) -> Trapezium u -> Anchor u-runDisplaceCenter fn (Trapezium { tz_ctm = ctm- , tz_base_width = bw- , tz_top_width = tw- , tz_height = h }) =+runDisplaceCenter fn (Trapezium { tz_ctm = ctm+ , tz_base_width = bw+ , tz_height = h + , tz_bottom_left_ang = bl_ang }) =+ projectFromCtr (fn bw h bl_ang) ctm+++-- | 'runDisplaceCenterHalves' : @ ( half_base_width +-- * half_top_width+-- * half_height -> Vec ) * trapezium -> Point @+--+runDisplaceCenterHalves :: (Real u, Floating u)+ => (u -> u -> u -> Vec2 u) + -> Trapezium u -> Anchor u+runDisplaceCenterHalves fn (Trapezium { tz_ctm = ctm+ , tz_base_width = bw+ , 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@@ -105,8 +122,8 @@ instance (Real u, Floating u) => BottomCornerAnchor (Trapezium u) where- bottomLeftCorner = runDisplaceCenter $ \hbw _ hh -> V2 (-hbw) (-hh)- bottomRightCorner = runDisplaceCenter $ \hbw _ hh -> V2 hbw (-hh)+ bottomLeftCorner = runDisplaceCenterHalves $ \hbw _ hh -> V2 (-hbw) (-hh)+ bottomRightCorner = runDisplaceCenterHalves $ \hbw _ hh -> V2 hbw (-hh) @@ -114,8 +131,8 @@ instance (Real u, Floating u) => TopCornerAnchor (Trapezium u) where- topLeftCorner = runDisplaceCenter $ \_ htw hh -> V2 (-htw) hh- topRightCorner = runDisplaceCenter $ \_ htw hh -> V2 htw hh+ topLeftCorner = runDisplaceCenterHalves $ \_ htw hh -> V2 (-htw) hh+ topRightCorner = runDisplaceCenterHalves $ \_ htw hh -> V2 htw hh instance (Real u, Floating u, Tolerance u) => @@ -131,39 +148,36 @@ instance (Real u, Floating u, Tolerance u) => CardinalAnchor (Trapezium u) where- north = runDisplaceCenter $ \_ _ hh -> V2 0 hh- south = runDisplaceCenter $ \_ _ hh -> V2 0 (-hh)- east = tzRadialAnchor 0- west = tzRadialAnchor pi+ north = radialAnchor half_pi+ south = radialAnchor (1.5 * pi)+ east = radialAnchor 0+ west = radialAnchor pi instance (Real u, Floating u, Tolerance u) => CardinalAnchor2 (Trapezium u) where- northeast = tzRadialAnchor (0.25*pi)- southeast = tzRadialAnchor (1.75*pi)- southwest = tzRadialAnchor (1.25*pi)- northwest = tzRadialAnchor (0.75*pi)+ northeast = radialAnchor (0.25*pi)+ southeast = radialAnchor (1.75*pi)+ southwest = radialAnchor (1.25*pi)+ northwest = radialAnchor (0.75*pi) instance (Real u, Floating u, Tolerance u) => RadialAnchor (Trapezium u) where- radialAnchor = tzRadialAnchor+ radialAnchor ang = runDisplaceCenter $ \bw h bl_ang -> + maybe zeroVec id $ trapeziumRadialAnchor bw h bl_ang ang + -- -tzRadialAnchor :: (Real u, Floating u, Tolerance u) - => Radian -> Trapezium u -> Anchor u-tzRadialAnchor theta (Trapezium { tz_ctm = ctm- , tz_base_width = bw- , tz_top_width = tw- , tz_height = h }) =- post $ findIntersect zeroPt theta $ polygonLineSegments ps- where - 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- +trapeziumRadialAnchor :: (Real u, Floating u, Tolerance u) + => u -> u -> Radian -> Radian -> Maybe (Vec2 u)+trapeziumRadialAnchor bw h bl_ang ang =+ fmap (pvec zeroPt) $ rayPathIntersection (inclinedRay zeroPt ang) rp + where+ rp = anaTrailPath zeroPt $ trapezium_trail bw h bl_ang++ -------------------------------------------------------------------------------- -- Construction@@ -174,9 +188,9 @@ -- -- trapezium :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> u -> Shape Trapezium u-trapezium bw tw h = - makeShape (mkTrapezium bw tw h) (mkTrapeziumPath 0 bw tw h)+ => u -> u -> Radian -> Shape Trapezium u+trapezium bw h base_ang = + makeShape (mkTrapezium bw h base_ang) (mkTrapeziumPath bw h base_ang) @@ -185,19 +199,22 @@ mkTrapezium :: (Real u, Fractional u, InterpretUnit u) - => 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+ => u -> u -> Radian -> LocThetaQuery u (Trapezium u)+mkTrapezium bw h base_ang = qpromoteLocTheta $ \ctr theta -> + pure $ Trapezium { tz_ctm = makeShapeCTM ctr theta+ , tz_base_width = bw+ , tz_top_width = tw+ , tz_height = h+ , tz_bottom_left_ang = base_ang }+ where+ base_minor = h / (fromRadian $ tan base_ang)+ tw = bw - (2 * base_minor) mkTrapeziumPath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => 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+ => u -> u -> Radian -> LocThetaQuery u (AbsPath u)+mkTrapeziumPath bw h bl_ang = qpromoteLocTheta $ \ctr theta -> + return $ anaTrailPath ctr $ rtrapezium_trail bw h bl_ang theta
src/Wumpus/Drawing/Shapes/Triangle.hs view
@@ -24,11 +24,13 @@ ) where +import Wumpus.Drawing.Basis.ShapeTrails+import Wumpus.Drawing.Basis.Geometry import Wumpus.Drawing.Paths+import Wumpus.Drawing.Paths.Intersection import Wumpus.Drawing.Shapes.Base -import Wumpus.Basic.Geometry -- package: wumpus-basic-import Wumpus.Basic.Kernel+import Wumpus.Basic.Kernel -- package: wumpus-basic import Wumpus.Core -- package: wumpus-core @@ -49,36 +51,21 @@ } type instance DUnit (Triangle u) = u- -data SyntheticProps u = SyntheticProps- { tri_hmajor :: u - , tri_hminor :: u- , tri_base_ang :: Radian- , tri_apex_ang :: Radian- } - type DTriangle = Triangle Double instance Functor Triangle where fmap f (Triangle ctm bw h) = Triangle (fmap f ctm) (f bw) (f h) -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)+hminor :: Fractional u => u -> u +hminor h = h / 3 +hmajor :: Fractional u => u -> u +hmajor h = 2 * (h / 3) ++ -------------------------------------------------------------------------------- -- Affine trans @@ -107,33 +94,29 @@ -- * base_ang -> Vec ) * traingle -> Point @ -- runDisplaceCenter :: (Real u, Floating u)- => (u -> u -> u -> Radian -> Vec2 u) -> Triangle u -> Anchor u+ => (u -> u -> Vec2 u) -> Triangle u -> Anchor u runDisplaceCenter fn (Triangle { tri_ctm = ctm , tri_base_width = bw , tri_height = h }) = - projectFromCtr (fn (0.5*bw) hminor hmajor base_ang) ctm- where- props = synthesizeProps bw h- hminor = tri_hminor props - hmajor = tri_hmajor props- base_ang = tri_base_ang props-+ projectFromCtr (fn bw h) ctm instance (Real u, Floating u) => CenterAnchor (Triangle u) where- center = runDisplaceCenter $ \_ _ _ _ -> V2 0 0+ center = runDisplaceCenter $ \_ _ -> V2 0 0 instance (Real u, Floating u) => ApexAnchor (Triangle u) where- apex = runDisplaceCenter $ \_ _ hmaj _ -> V2 0 hmaj+ apex = runDisplaceCenter $ \_ h -> V2 0 (hmajor h) instance (Real u, Floating u) => BottomCornerAnchor (Triangle u) where- bottomLeftCorner = runDisplaceCenter $ \hbw hmin _ _ -> V2 (-hbw) (-hmin)- bottomRightCorner = runDisplaceCenter $ \hbw hmin _ _ -> V2 hbw (-hmin)+ bottomLeftCorner = runDisplaceCenter $ \bw h -> + V2 (negate $ 0.5 * bw) (negate $ hminor h)+ bottomRightCorner = runDisplaceCenter $ \bw h -> + V2 (0.5 * bw) (negate $ hminor h) -- east and west should be parallel to the centroid.@@ -141,10 +124,10 @@ instance (Real u, Floating u) => CardinalAnchor (Triangle u) where- north = runDisplaceCenter $ \_ _ hmaj _ -> V2 0 hmaj- south = runDisplaceCenter $ \_ hmin _ _ -> V2 0 (-hmin)- east = runDisplaceCenter $ \hbw hmin _ ang -> findEast hbw hmin ang- west = runDisplaceCenter $ \hbw hmin _ ang -> findWest hbw hmin ang+ north = runDisplaceCenter $ \_ h -> V2 0 (hmajor h)+ south = runDisplaceCenter $ \_ h -> V2 0 (negate $ hminor h)+ east = runDisplaceCenter $ \bw h -> findEast bw h+ west = runDisplaceCenter $ \bw h -> findWest bw h instance (Real u, Floating u) => @@ -156,18 +139,20 @@ step _ = midpoint (bottomRightCorner a) (apex a) -findEast :: Fractional u => u -> u -> Radian -> Vec2 u-findEast half_base_width hminor base_ang = V2 xdist 0+findEast :: (Real u, Fractional u) => u -> u -> Vec2 u+findEast bw h = V2 xdist 0 where- b1 = hminor / (fromRadian $ tan base_ang)- xdist = half_base_width - b1+ half_base = 0.5 * bw + base_ang = atan $ toRadian (h / half_base)+ b1 = (hminor h) / (fromRadian $ tan base_ang)+ xdist = (0.5 * bw) - b1 -findWest :: Fractional u => u -> u -> Radian -> Vec2 u-findWest hbw hm ang = let (V2 xdist 0) = findEast hbw hm ang in V2 (-xdist) 0 +findWest :: (Real u, Fractional u) => u -> u -> Vec2 u+findWest bw h = let (V2 xdist 0) = findEast bw h in V2 (-xdist) 0 -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => CardinalAnchor2 (Triangle u) where northeast = radialAnchor (0.25*pi) southeast = radialAnchor (1.75*pi)@@ -176,11 +161,14 @@ -instance (Real u, Floating u) => +instance (Real u, Floating u, InterpretUnit u, Tolerance u) => RadialAnchor (Triangle u) where- radialAnchor theta = runDisplaceCenter $ \hbw hmin hmaj _ -> - triangleRadialVector hbw hmin hmaj theta- + radialAnchor ang = runDisplaceCenter $ \bw h -> + maybe zeroVec id $ isoscelesTriangleRadialIntersect bw h ang++++ -------------------------------------------------------------------------------- -- Construction@@ -190,11 +178,7 @@ -- triangle :: (Real u, Floating u, InterpretUnit u, Tolerance u) => u -> u -> Shape Triangle u-triangle bw h =- let props = synthesizeProps bw h- hminor = tri_hminor props- hmajor = tri_hmajor props- in makeShape (mkTriangle bw h) (mkTrianglePath 0 bw hminor hmajor)+triangle bw h = makeShape (mkTriangle bw h) (mkTrianglePath bw h) @@ -213,19 +197,7 @@ mkTrianglePath :: (Real u, Floating u, InterpretUnit u, Tolerance u) - => u -> u -> u -> u -> LocThetaQuery u (AbsPath u)-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 -> Vertices3 u-trianglePath bw hminor hmajor = (br, apx, bl)- where- half_base = 0.5 * bw- br = V2 half_base (-hminor)- apx = V2 0 hmajor- bl = V2 (-half_base) (-hminor)+ => u -> u -> LocThetaQuery u (AbsPath u)+mkTrianglePath bw h = qpromoteLocTheta $ \ctr theta -> + return $ anaTrailPath ctr $ risosceles_triangle_trail bw h theta
src/Wumpus/Drawing/Text/Base/DocTextZero.hs view
@@ -72,7 +72,7 @@ newtype GenDoc st u a = GenDoc { getGenDoc :: DocEnv -> GenPosObject st u a } type instance DUnit (GenDoc st u a) = u-type instance UState (GenDoc st u) = st+type instance UState (GenDoc st u a) = st type GenDocGraphic st u = GenDoc st u (UNil u) @@ -243,20 +243,20 @@ strikethrough :: (Fractional u, InterpretUnit u) => GenDoc st u a -> GenDoc st u a-strikethrough = decorateDoc SUPERIOR drawStrikethrough +strikethrough = decorateDoc ZABOVE drawStrikethrough underline :: (Fractional u, InterpretUnit u) => GenDoc st u a -> GenDoc st u a-underline = decorateDoc SUPERIOR drawUnderline+underline = decorateDoc ZABOVE drawUnderline highlight :: (Fractional u, InterpretUnit u) => RGBi -> GenDoc st u a -> GenDoc st u a-highlight rgb = decorateDoc ANTERIOR (drawBackfill rgb) +highlight rgb = decorateDoc ZBELOW (drawBackfill rgb) decorateDoc :: InterpretUnit u - => ZDeco -> (Orientation u -> LocGraphic u) -> GenDoc st u a + => ZOrder -> (Orientation u -> LocGraphic u) -> GenDoc st u a -> GenDoc st u a decorateDoc zdec fn ma = GenDoc $ \env -> decoratePosObject zdec fn $ getGenDoc ma env
src/Wumpus/Drawing/Text/Base/Label.hs view
@@ -59,7 +59,7 @@ -> LocImage u a -> LocImage u a locImageLabel fn rpos mklabel obj = promoteLoc $ \pt -> - selaborate (obj `at` pt) (\a -> ignoreAns $ mklabel rpos `at` fn a)+ elaborateAbove (obj `at` pt) (\a -> ignoreAns $ mklabel rpos `at` fn a) @@ -96,7 +96,7 @@ -> Image u (AbsPath u) -> Image u (AbsPath u) connectorPathLabel fn rpos lbl img = - selaborate img (\a -> ignoreAns $ lbl rpos `at` (fn a))+ elaborateAbove img (\a -> ignoreAns $ lbl rpos `at` (fn a)) label_midway_of :: (Real u, Floating u, InterpretUnit u)
src/Wumpus/Drawing/Text/DocSymbols.hs view
@@ -44,7 +44,7 @@ ocircle = embedPosObject $ makePosObject qy gf where qy = (\h -> let hh = 0.5 * h in Orientation hh hh 0 h) <$> capHeight- gf = capHeight >>= \h -> moveStart (go_up $ 0.5 * h) (S.ocircle $ 0.5 * h)+ gf = capHeight >>= \h -> moveStart (go_up $ 0.5 * h) (S.scircle $ 0.5 * h) @@ -52,7 +52,7 @@ small_ocircle = embedPosObject $ makePosObject qy gf where qy = (\h -> let hw = 0.33 * h in Orientation hw hw 0 h) <$> capHeight- gf = capHeight >>= \h -> moveStart (go_up $ 0.33 * h) (S.ocircle $ 0.25 * h)+ gf = capHeight >>= \h -> moveStart (go_up $ 0.33 * h) (S.scircle $ 0.25 * h) empty_box :: (Fractional u, InterpretUnit u) => GenDocGraphic st u empty_box = embedPosObject $ makePosObject qy gf@@ -66,13 +66,13 @@ left_slice = embedPosObject $ makePosObject qy gf where qy = (\h -> let hw = 0.66 * h in Orientation hw hw 0 h) <$> capHeight- gf = capHeight >>= \h -> moveStart (go_up $ 0.33 * h) (S.left_slice h)+ gf = capHeight >>= \h -> moveStart (go_up $ 0.33 * h) (S.sleft_slice h) right_slice :: (Real u, Floating u, InterpretUnit u) => GenDocGraphic st u right_slice = embedPosObject $ makePosObject qy gf where qy = (\h -> let hw = 0.66 * h in Orientation hw hw 0 h) <$> capHeight- gf = capHeight >>= \h -> moveStart (go_up $ 0.33 * h) (S.right_slice h)+ gf = capHeight >>= \h -> moveStart (go_up $ 0.33 * h) (S.sright_slice h) -- More to follow...
src/Wumpus/Drawing/VersionNumber.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Drawing.VersionNumber--- Copyright : (c) Stephen Tetley 2010-2011+-- Copyright : (c) Stephen Tetley 2010-2012 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -23,7 +23,7 @@ -- | Version number ----- > (0,7,0)+-- > (0,9,0) -- wumpus_drawing_version :: (Int,Int,Int)-wumpus_drawing_version = (0,7,0)+wumpus_drawing_version = (0,9,0)
wumpus-drawing.cabal view
@@ -1,5 +1,5 @@ name: wumpus-drawing-version: 0.7.0+version: 0.9.0 license: BSD3 license-file: LICENSE copyright: Stephen Tetley <stephen.tetley@gmail.com>@@ -38,8 +38,23 @@ . Changelog: .- v0.6.0 to v0.7.0+ v0.8.0 to v0.9.0:+ . + * Updated to work with wumpus-basic-0.24.0. .+ * Removed monoid mappend alias @(<>)@ as it is now defined by+ Data.Monoid. + .+ v0.7.0 to v0.8.0:+ .+ * Changed API to make Connectors.+ .+ * Added InclineTrails to Drawing.Basis.+ . + * Reworked @Extras.Loop@.+ .+ v0.6.0 to v0.7.0:+ . * Changed paths - @RelPath@ has been removed and there are now only absolute paths. @PathBuilder@ builds absolute paths. Pen updating in @PathBuilder@ now works like a State monad @@ -53,7 +68,7 @@ . * Added a tube box connector. .- v0.5.0 to v0.6.0+ v0.5.0 to v0.6.0: . * Removed @LocTrace@ and @RefTrace@ from @Wumpus.Drawing.Basis@, they are superseded by @LocDrawing@ in Wumpus-Basic.@@ -91,11 +106,15 @@ containers >= 0.3 && <= 0.6, vector-space >= 0.6 && < 1.0, wumpus-core >= 0.52.0 && < 0.53.0,- wumpus-basic == 0.22.0+ wumpus-basic == 0.24.0 exposed-modules:+ Wumpus.Drawing.Basis.BezierCurve, Wumpus.Drawing.Basis.DrawingPrimitives,+ Wumpus.Drawing.Basis.Geometry,+ Wumpus.Drawing.Basis.InclineTrails,+ Wumpus.Drawing.Basis.ShapeTrails, Wumpus.Drawing.Basis.Symbols, Wumpus.Drawing.Colour.SVGColours, Wumpus.Drawing.Colour.X11Colours,@@ -113,6 +132,8 @@ Wumpus.Drawing.Extras.Loop, Wumpus.Drawing.Paths, Wumpus.Drawing.Paths.Base,+ Wumpus.Drawing.Paths.Illustrate,+ Wumpus.Drawing.Paths.Intersection, Wumpus.Drawing.Paths.PathBuilder, Wumpus.Drawing.Paths.Vamps, Wumpus.Drawing.Shapes,