{-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Dots.Primitive -- Copyright : (c) Stephen Tetley 2010 -- License : BSD3 -- -- Maintainer : Stephen Tetley -- Stability : highly unstable -- Portability : GHC -- -- Marks - dots without anchor handles. -- -- \*\* WARNING \*\* - names are expected to change - filled and -- background-filled marks need a naming convention. -- -------------------------------------------------------------------------------- module Wumpus.Basic.Dots.Primitive ( -- * Marks markChar , markText , markHLine , markVLine , markX , markPlus , markCross , markDiamond , markFDiamond , markBDiamond , markDisk , markSquare , markCircle , markPentagon , markStar , markAsterisk , markOPlus , markOCross , markFOCross ) where import Wumpus.Basic.Graphic import Wumpus.Core -- package: wumpus-core import Data.AffineSpace -- package: vector-space import Data.VectorSpace import Control.Applicative import Data.List import Data.Monoid -- Marks should be the height of a lower-case letter... -- NOTES -- -- TikZ has both stroked and bordered (filled and outline-stroked) -- marks e.g. square and square* -- -- | 'polygonPoints' : @ num_points * radius * center -> [point] @ -- polygonPoints :: Floating u => Int -> u -> Point2 u -> [Point2 u] polygonPoints n radius ctr = unfoldr phi (0,(pi*0.5)) where theta = (pi*2) / fromIntegral n phi (i,ang) | i < n = Just (ctr .+^ avec ang radius, (i+1,ang+theta)) | otherwise = Nothing -- | A mark is the height of a lowercase \'x\'. -- standardSize :: FromPtSize u => (u -> LocGraphic u) -> LocGraphic u standardSize f = \pt -> markHeight >>= \h -> f h pt halfHeightSize :: (Fractional u, FromPtSize u) => (u -> LocGraphic u) -> LocGraphic u halfHeightSize f = \pt -> markHeight >>= \h -> f (h * 0.5) pt shiftOrigin :: Num u => u -> u -> LocGraphic u -> LocGraphic u shiftOrigin dx dy f = \pt -> f (displace dx dy pt) markChar :: (Fractional u, Ord u, FromPtSize u) => Char -> LocGraphic u markChar ch = markText [ch] -- Note - eta-expanded (?) -- markText :: (Fractional u, Ord u, FromPtSize u) => String -> LocGraphic u markText ss = centermonoTextline ss -- | Supplied point is the center. -- axialLine :: Fractional u => Vec2 u -> LocGraphic u axialLine v = localPoint (\ctr -> ctr .-^ (0.5 *^ v)) (straightLine v) markHLine :: (Fractional u, FromPtSize u) => LocGraphic u markHLine = standardSize $ \h -> axialLine (hvec h) markVLine :: (Fractional u, FromPtSize u) => LocGraphic u markVLine = standardSize $ \h -> axialLine (vvec h) markX :: (Fractional u, FromPtSize u) => LocGraphic u markX = standardSize $ \h -> let w = 0.75 * h in mappend <$> axialLine (vec w h) <*> axialLine (vec (-w) h) markPlus :: (Fractional u, FromPtSize u) => LocGraphic u markPlus = mappend <$> markVLine <*> markHLine markCross :: (Floating u, FromPtSize u) => LocGraphic u markCross = standardSize $ \h -> mappend <$> axialLine (avec ang h) <*> axialLine (avec (-ang) h) where ang = pi*0.25 -- needs horizontal pinch... pathDiamond :: (Fractional u, FromPtSize u) => Point2 u -> DrawingR (PrimPath u) pathDiamond pt = (\h -> let hh = 0.66 * h; hw = 0.5 * h in vertexPath [dvs hh, dve hw,dvn hh, dvw hw]) <$> markHeight where dvs hh = pt .+^ vvec (-hh) dve hw = pt .+^ hvec hw dvn hh = pt .+^ vvec hh dvw hw = pt .+^ hvec (-hw) markDiamond :: (Fractional u, FromPtSize u) => LocGraphic u markDiamond = \pt -> pathDiamond pt >>= closedStroke markFDiamond :: (Fractional u, FromPtSize u) => LocGraphic u markFDiamond = \pt -> pathDiamond pt >>= filledPath markBDiamond :: (Fractional u, FromPtSize u) => LocGraphic u markBDiamond = \pt -> pathDiamond pt >>= borderedPath -- | Note disk is filled. -- markDisk :: (Fractional u, FromPtSize u) => LocGraphic u markDisk = halfHeightSize filledDisk markSquare :: (Fractional u, FromPtSize u) => LocGraphic u markSquare = standardSize (\h -> let d = 0.5*(-h) in shiftOrigin d d $ strokedRectangle h h) markCircle :: (Fractional u, FromPtSize u) => LocGraphic u markCircle = halfHeightSize strokedDisk markBCircle :: (Fractional u, FromPtSize u) => LocGraphic u markBCircle = halfHeightSize borderedDisk markPentagon :: (Floating u, FromPtSize u) => LocGraphic u markPentagon pt = markHeight >>= \h -> closedStroke $ vertexPath $ polygonPoints 5 (0.5*h) pt markStar :: (Floating u, FromPtSize u) => LocGraphic u markStar pt = markHeight >>= \h -> let ps = polygonPoints 5 (0.5*h) pt in mconcat $ map fn ps where fn p1 = openStroke $ path pt [lineTo p1] markAsterisk :: (Floating u, FromPtSize u) => LocGraphic u markAsterisk = standardSize $ \h -> (\a b c -> a `mappend` b `mappend` c) <$> lineF1 h <*> lineF2 h <*> lineF3 h where ang = (pi*2) / 6 lineF1 z = axialLine (vvec z) lineF2 z = axialLine (avec ((pi*0.5) + ang) z) lineF3 z = axialLine (avec ((pi*0.5) + ang + ang) z) markOPlus :: (Fractional u, FromPtSize u) => LocGraphic u markOPlus = mappend <$> markCircle <*> markPlus markOCross :: (Floating u, FromPtSize u) => LocGraphic u markOCross = mappend <$> markCircle <*> markCross markFOCross :: (Floating u, FromPtSize u) => LocGraphic u markFOCross = liftA2 mappend markCross markBCircle -- bkCircle :: (Fractional u, FromPtSize u) => LocGraphic u -- bkCircle = disk (fillAttr attr) (0.5*markHeight attr)