-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Basic objects and system code built on Wumpus-Core. -- -- Kernel code for higher-level drawing built on Wumpus-Core. This -- package provides font loader code (currently limited to AFM font -- files) and a various drawing objects intended to be a -- higher-level basis to make vector drawings than the primitives (paths, -- text labels) provided by Wumpus-Core. -- -- ** WARNING ** - this package is alpha grade and it is strongly coupled -- to the package Wumpus-Drawing which is sub-alpha grade. The -- packages are split as it is expected they will have different -- development speeds - Wumpus-Basic needs polishing and -- refinement; Wumpus-Drawing simply needs a lot of work to move -- its components from proof-of-concept ideas to being readily -- usable. -- -- NOTE - the demos that were previously included are now in the package -- Wumpus-Drawing. -- -- Changelog: -- -- v0.17.0 to v0.18.0: -- --
-- (0,18,0) --wumpus_basic_version :: (Int, Int, Int) -- | A "join list" datatype and operations. -- -- A join list is implemented a binary tree, so joining two lists -- (catenation, aka (++)) is a cheap operation. -- -- This constrasts with the regular list datatype which is a cons list: -- while consing on a regular list is by nature cheap, joining (++) is -- expensive. module Wumpus.Basic.Utils.JoinList data JoinList a data ViewL a EmptyL :: ViewL a (:<) :: a -> (JoinList a) -> ViewL a data ViewR a EmptyR :: ViewR a (:>) :: (JoinList a) -> a -> ViewR a -- | Build a join list from a regular list. -- -- This builds a tall skinny list. -- -- WARNING - throws an error on empty list. fromList :: [a] -> JoinList a fromListF :: (a -> b) -> [a] -> JoinList b -- | Convert a join list to a regular list. toList :: JoinList a -> [a] toListF :: (a -> b) -> JoinList a -> [b] toListM :: Monad m => (a -> m b) -> JoinList a -> m [b] zipWithIntoList :: (a -> b -> c) -> JoinList a -> [b] -> [c] -- | Create an empty join list. empty :: JoinList a -- | Create a singleton join list. one :: a -> JoinList a -- | Cons an element to the front of the join list. cons :: a -> JoinList a -> JoinList a -- | Snoc an element to the tail of the join list. snoc :: JoinList a -> a -> JoinList a join :: JoinList a -> JoinList a -> JoinList a -- | Extract the first element of a join list - i.e. the leftmost element -- of the left spine. An error is thrown if the list is empty. -- -- This function performs a traversal down the left spine, so unlike -- head on regular lists this function is not performed in -- constant time. -- -- This function throws a runtime error on the empty list. head :: JoinList a -> a takeL :: Int -> JoinList a -> JoinList a length :: JoinList a -> Int takeWhileL :: (a -> Bool) -> JoinList a -> JoinList a accumMapL :: (x -> st -> (y, st)) -> JoinList x -> st -> (JoinList y, st) null :: JoinList a -> Bool -- | Access the left end of a sequence. -- -- Unlike the corresponing operation on Data.Sequence this is not a cheap -- operation, the joinlist must be traversed down the left spine to find -- the leftmost node. -- -- Also the traversal may involve changing the shape of the underlying -- binary tree. viewl :: JoinList a -> ViewL a -- | Access the right end of a sequence. -- -- Unlike the corresponing operation on Data.Sequence this is not a cheap -- operation, the joinlist must be traversed down the left spine to find -- the leftmost node. -- -- Also the traversal may involve changing the shape of the underlying -- binary tree. viewr :: JoinList a -> ViewR a unViewL :: ViewL a -> JoinList a unViewR :: ViewR a -> JoinList a instance Eq a => Eq (JoinList a) instance Eq a => Eq (ViewL a) instance Show a => Show (ViewL a) instance Eq a => Eq (ViewR a) instance Show a => Show (ViewR a) instance Functor ViewR instance Functor ViewL instance Traversable JoinList instance Foldable JoinList instance Functor JoinList instance Monoid (JoinList a) instance Show a => Show (JoinList a) -- | Formatting combinators - pretty printers without the fitting. -- -- Note - indentation support is very limited. Generally one should use a -- proper pretty printing library. module Wumpus.Basic.Utils.FormatCombinators -- | Doc is a Join List ... data Doc type DocS = Doc -> Doc class Format a format :: Format a => a -> Doc -- | Create an empty, zero length document. empty :: Doc -- | Create a document from a ShowS function. showsDoc :: ShowS -> Doc -- | Horizontally concatenate two documents with no space between them. (<>) :: Doc -> Doc -> Doc -- | Horizontally concatenate two documents with a single space between -- them. (<+>) :: Doc -> Doc -> Doc -- | Vertical concatenate two documents with a line break. vconcat :: Doc -> Doc -> Doc separate :: Doc -> [Doc] -> Doc -- | Horizontally concatenate a list of documents with (<>). hcat :: [Doc] -> Doc -- | Horizontally concatenate a list of documents with -- (<+>). hsep :: [Doc] -> Doc -- | Vertically concatenate a list of documents, with a line break between -- each doc. vcat :: [Doc] -> Doc -- | Create a document from a literal string. -- -- The string should not contain newlines (though this is not enforced). text :: String -> Doc -- | Create a document from a literal character. -- -- The char should not be a tab or newline. char :: Char -> Doc -- | Show the Int as a Doc. -- --
-- int = text . show --int :: Int -> Doc -- | Show the Integer as a Doc. integer :: Integer -> Doc -- | Show an "integral value" as a Doc via fromIntegral. integral :: Integral a => a -> Doc -- | Show the Float as a Doc. float :: Double -> Doc -- | Show the Double as a Doc. double :: Double -> Doc -- | Show the Int as hexadecimal, padding up to 4 digits if necessary. -- -- No trucation occurs if the value has more than 4 digits. hex4 :: Int -> Doc -- | Create a Doc containing a single space character. space :: Doc -- | Create a Doc containing a comma, ",". comma :: Doc -- | Create a Doc containing a semi colon, ";". semicolon :: Doc -- | Create a Doc containing newline, "\n". line :: Doc -- | Fill a doc to the supplied length, padding the right-hand side with -- spaces. -- -- Note - this function is expensive - it unrolls the functional -- representation of the String. -- -- Also it should only be used for single line Doc's. fill :: Int -> Doc -> Doc -- | String version of fill. -- -- This is more efficient than fill as the input is a string so -- its length is more accesible. -- -- Padding is the space character appended to the right. fillStringR :: Int -> String -> Doc -- | Left-padding version of fillStringR. fillStringL :: Int -> String -> Doc -- | Punctuate the Doc list with the separator, producing a Doc. punctuate :: Doc -> [Doc] -> Doc -- | Enclose the final Doc within the first two. -- -- There are no spaces between the documents: -- --
-- enclose l r d = l <> d <> r --enclose :: Doc -> Doc -> Doc -> Doc -- | Enclose the Doc within single quotes. squotes :: Doc -> Doc -- | Enclose the Doc within double quotes. dquotes :: Doc -> Doc -- | Enclose the Doc within parens (). parens :: Doc -> Doc -- | Enclose the Doc within square brackets []. brackets :: Doc -> Doc -- | Enclose the Doc within curly braces {}. braces :: Doc -> Doc -- | Enclose the Doc within angle brackets <>. angles :: Doc -> Doc -- | Create a Doc containing a left paren, '('. lparen :: Doc -- | Create a Doc containing a right paren, ')'. rparen :: Doc -- | Create a Doc containing a left square bracket, '['. lbracket :: Doc -- | Create a Doc containing a right square bracket, ']'. rbracket :: Doc -- | Create a Doc containing a left curly brace, '{'. lbrace :: Doc -- | Create a Doc containing a right curly brace, '}'. rbrace :: Doc -- | Create a Doc containing a left angle bracket, '<'. langle :: Doc -- | Create a Doc containing a right angle bracket, '>'. rangle :: Doc -- | Comma separate the list of documents and enclose in square brackets. list :: [Doc] -> Doc -- | Comma separate the list of documents and enclose in parens. tupled :: [Doc] -> Doc -- | Separate the list with a semicolon and enclose in curly braces. semiBraces :: [Doc] -> Doc -- | Horizontally indent a Doc. -- -- Note - this space-prefixes the Doc on the current line. It does -- not indent subsequent lines if the Doc spans multiple lines. indent :: Int -> Doc -> Doc -- | Write a Doc to file. writeDoc :: FilePath -> Doc -> IO () instance Monoid Doc instance Show Doc -- | Two continuation parser combinators. module Wumpus.Basic.Utils.ParserCombinators data Parser s r data Result s ans Fail :: String -> [s] -> Result s ans Okay :: ans -> [s] -> Result s ans type CharParser a = Parser Char a type CharResult a = Result Char a type ParseError = String runParser :: Parser s a -> [s] -> Result s a runParserEither :: Show s => Parser s a -> [s] -> Either ParseError a apply :: Functor f => f a -> (a -> b) -> f b failure :: Parser s a throwError :: String -> Parser s a (>) :: Parser s a -> String -> Parser s a -- | This one is from Chris Okasaki's "Even Higher-Order Functions for -- Parsing". lookahead :: Parser s a -> (a -> Parser s b) -> Parser s b -- | Peek tries the supplied parse, but does not consume input ** even when -- the parse succeeds **. peek :: Parser s a -> Parser s a eof :: Parser s () equals :: Eq s => s -> Parser s s satisfy :: (s -> Bool) -> Parser s s oneOf :: Eq s => [s] -> Parser s s noneOf :: Eq s => [s] -> Parser s s chainl1 :: MonadPlus m => m a -> m (a -> a -> a) -> m a chainr1 :: MonadPlus m => m a -> m (a -> a -> a) -> m a chainl :: MonadPlus m => m a -> m (a -> a -> a) -> a -> m a chainr :: MonadPlus m => m a -> m (a -> a -> a) -> a -> m a choice :: Alternative f => [f a] -> f a count :: Applicative f => Int -> f a -> f [a] between :: Applicative f => f open -> f close -> f a -> f a option :: Alternative f => a -> f a -> f a optionMaybe :: Alternative f => f a -> f (Maybe a) optionUnit :: Alternative f => f a -> f () skipOne :: Applicative f => f a -> f () skipMany :: Alternative f => f a -> f () skipMany1 :: Alternative f => f a -> f () -- | many1 an alias for Control.Applicative some. many1 :: Alternative f => f a -> f [a] sepBy :: Alternative f => f a -> f b -> f [a] sepBy1 :: Alternative f => f a -> f b -> f [a] sepEndBy :: Alternative f => f a -> f b -> f [a] sepEndBy1 :: Alternative f => f a -> f b -> f [a] manyTill :: Alternative f => f a -> f b -> f [a] manyTill1 :: Alternative f => f a -> f b -> f [a] char :: Char -> CharParser Char string :: String -> CharParser String anyChar :: CharParser Char upper :: CharParser Char lower :: CharParser Char letter :: CharParser Char alphaNum :: CharParser Char digit :: CharParser Char hexDigit :: CharParser Char octDigit :: CharParser Char newline :: CharParser Char tab :: CharParser Char space :: CharParser Char instance (Eq s, Eq ans) => Eq (Result s ans) instance (Ord s, Ord ans) => Ord (Result s ans) instance (Show s, Show ans) => Show (Result s ans) instance MonadPlus (Parser s) instance Monad (Parser s) instance Alternative (Parser s) instance Applicative (Parser s) instance Functor (Parser s) -- | Generally you should expect to import this module qualified and define -- versions to consume trailing white-space. -- --
-- lexDef :: P.LexemeParser -- lexDef = P.commentLineLexemeParser "Comment" [' ', '\t'] -- -- lexeme :: CharParser a -> CharParser a -- lexeme = P.lexeme lexDef -- -- integer :: CharParser Int -- integer = lexeme P.integer --module Wumpus.Basic.Utils.TokenParsers -- | Opaque type representing a parser that consumes arbitrary space. -- -- Unlike Parsec's lexeme parser, this can be customized so that e.g. -- newlines are not consumed as white space. data LexemeParser -- | Build a lexeme parser that handles space. -- -- Space is zero or more elements matching the isSpace -- predicate from Data.Char. spaceLexemeParser :: LexemeParser -- | Build a lexeme parser that handles arbitrary space. -- -- space is parametric, for instance this can manufacture a lexeme -- parser that consumes space and tab chars but not newline. spaceCharLexemeParser :: [Char] -> LexemeParser -- | Build a lexeme parser that handles start-and-end delimited comments -- and arbitrary space. commentLexemeParser :: String -> (String, String) -> [Char] -> LexemeParser -- | Build a lexeme parser that handles line spanning comments an arbitrary -- space. commentLineLexemeParser :: String -> [Char] -> LexemeParser -- | Build a lexeme parser that handles start-and-end delimited comments, -- line comments and arbitrary space. commentMultiLexemeParser :: String -> String -> [Char] -> LexemeParser -- | Wrap a CharParser with a lexeme parser, the CharParser will consume -- trailing space according to the strategy of the LexemeParser. lexeme :: LexemeParser -> CharParser a -> CharParser a whiteSpace :: LexemeParser -> CharParser () octBase :: CharParser Int octHask :: CharParser Int hexBase :: CharParser Int natural :: CharParser Integer integer :: CharParser Integer double :: CharParser Double -- | Hughes list, ... module Wumpus.Basic.Utils.HList type H a = [a] -> [a] emptyH :: H a wrapH :: a -> H a consH :: a -> H a -> H a snocH :: H a -> a -> H a appendH :: H a -> H a -> H a unfoldrH :: (b -> Maybe (a, b)) -> b -> H a -- | velo consumes the list as per map, but builds it back as a Hughes list -- - so items can be dropped replaced, repeated, etc... veloH :: (a -> H b) -> [a] -> H b concatH :: [H a] -> H a toListH :: H a -> [a] prefixListH :: H a -> [a] -> [a] fromListH :: [a] -> H a -- | Anchor points on shapes, bounding boxes, etc. -- -- Anchors are addressable positions, an examplary use is taking anchors -- on node shapes to get the start and end points for connectors in a -- network (graph) diagram. -- -- ** WARNING ** - The API here needs some thought as to a good balance -- of the type classes - in a nutshell "are corners better than -- cardinals". Originally I tried to follow how I understand the TikZ -- anchors to work, but this is perhaps not ideal for dividing into -- type-classes. module Wumpus.Basic.Kernel.Objects.Anchors -- | Note an Anchor is just a Point2. type Anchor u = Point2 u -- | Center of an object. class CenterAnchor a center :: (CenterAnchor a, u ~ (DUnit a)) => a -> Anchor u -- | Apex of an object. class ApexAnchor a apex :: (ApexAnchor a, u ~ (DUnit a)) => a -> Anchor u -- | Cardinal (compass) positions on an object. -- -- Cardinal anchors should be at their equivalent radial position. -- However, some shapes may not be able to easily define radial positions -- or may be able to provide more efficient definitions for the cardinal -- anchors. Hence the redundancy seems justified. class CardinalAnchor a north :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u south :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u east :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u west :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u -- | Secondary group of cardinal (compass) positions on an object for the -- diagonal positions. -- -- It seems possible that for some objects defining the primary compass -- points (north, south,...) will be straight-forward whereas defining -- the secondary compass points may be problematic, hence the compass -- points are split into two classes. class CardinalAnchor2 a northeast :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u southeast :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u southwest :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u northwest :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u -- | Anchor on a border that can be addressed by an angle. -- -- The angle is counter-clockwise from the right-horizontal, i.e. 0 is -- east. class RadialAnchor a radialAnchor :: RadialAnchor a => Radian -> u ~ (DUnit a) => a -> Anchor u -- | Anchors at the top left and right corners of a shape. -- -- For some shapes (Rectangle) the TikZ convention appears to be have -- cardinals as the corner anchors, but this doesn't seem to be uniform. -- Wumpus will need to reconsider anchors at some point... class TopCornerAnchor a topLeftCorner :: (TopCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u topRightCorner :: (TopCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u -- | Anchors at the bottom left and right corners of a shape. class BottomCornerAnchor a bottomLeftCorner :: (BottomCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u bottomRightCorner :: (BottomCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u -- | Anchors in the center of a side. -- -- Sides are addressable by index. Following TikZ, side 1 is expected to -- be the top of the shape. If the shape has an apex instead of a side -- then side 1 is expected to be the first side left of the apex. -- -- Implementations are also expected to modulo the side number, rather -- than throw an out-of-bounds error. class SideMidpointAnchor a sideMidpoint :: SideMidpointAnchor a => Int -> u ~ (DUnit a) => a -> Anchor u -- | projectAnchor : extract_func * dist * object -> Point -- -- -- Derive a anchor by projecting a line from the center of an object -- through the intermediate anchor (produced by the extraction function). -- The final answer point is located along the projected line at the -- supplied distance dist. -- -- E.g. take the north of a rectangle and project it 10 units further on: -- --
-- projectAnchor north 10 my_rect ---- -- If the distance is zero the answer with be whatever point the the -- extraction function produces. -- -- If the distance is negative the answer will be along the projection -- line, between the center and the intermediate anchor. -- -- If the distance is positive the anchor will be extend outwards from -- the intermediate anchor. projectAnchor :: (Real u, Floating u, CenterAnchor a, u ~ (DUnit a)) => (a -> Anchor u) -> u -> a -> Anchor u -- | radialConnectorPoints : object_a * object_b -> -- (Point_a, Point_b) -- -- Find the radial connectors points for objects a and -- b along the line joining their centers. radialConnectorPoints :: (Real u, Floating u, CenterAnchor a, RadialAnchor a, CenterAnchor b, RadialAnchor b, u ~ (DUnit a), u ~ (DUnit b)) => a -> b -> (Point2 u, Point2 u) instance Fractional u => CardinalAnchor2 (BoundingBox u) instance Fractional u => CardinalAnchor (BoundingBox u) instance Fractional u => CenterAnchor (BoundingBox u) -- | Data types representing font metrics. module Wumpus.Basic.Kernel.Base.FontSupport type FontName = String -- | A Unicode code-point. type CodePoint = Int -- | FontDef wraps FontFace from Wumpus-Core with file name -- information for the font loaders. data FontDef FontDef :: FontFace -> String -> String -> FontDef font_def_face :: FontDef -> FontFace gs_file_name :: FontDef -> String afm_file_name :: FontDef -> String -- | A family group of FontDefs (regular, bold, italic and bold-italic). -- -- It is convenient for some higher-level text objects in Wumpus -- (particularly Doc in Wumpus-Drawing) to treat a font and its -- standard weights as the same entity. This allows Doc API to -- provide a bold operation to simply change to the the bold -- weight of the current family, rather than use the primitive -- set_font operation to change to an explicitly named font. data FontFamily FontFamily :: FontDef -> Maybe FontDef -> Maybe FontDef -> Maybe FontDef -> FontFamily ff_regular :: FontFamily -> FontDef ff_bold :: FontFamily -> Maybe FontDef ff_italic :: FontFamily -> Maybe FontDef ff_bold_italic :: FontFamily -> Maybe FontDef -- | Extract the regular weight FontDef from a FontFamily. regularWeight :: FontFamily -> FontDef -- | Extract the bold weight FontDef from a FontFamily. -- -- Note - this falls back to the regular weight if the font family has no -- bold weight. To get the bold weight or Nothing if it is not -- present use the record selector ff_bold. boldWeight :: FontFamily -> FontDef -- | Extract the italic weight FontDef from a -- FontFamily. -- -- Note - this falls back to the regular weight if the font family has no -- italic weight. To get the italic weight or Nothing if it is -- not present use the record selector ff_italic. italicWeight :: FontFamily -> FontDef -- | Extract the bold-italic weight FontDef from a -- FontFamily. -- -- Note - this falls back to the regular weight if the font family has no -- bold-italic weight. To get the bold-italic weight or Nothing -- if it is not present use the record selector ff_bold_italic. boldItalicWeight :: FontFamily -> FontDef -- | A lookup function from code point to width vector. -- -- The unit is always stored as a Double representing PostScript points. -- -- Note - in PostScript terminology a width vector is not obliged to be -- left-to-right (writing direction 0). It could be top-to-bottom -- (writing direction 1). type CharWidthLookup = CodePoint -> Vec2 Double -- | FontMetrics store a subset of the properties available in a -- font file - enough to calculate accurate bounding boxes and positions -- for text. -- --
-- Bounding box representing the maximum glyph area. -- Width vectors for each character. -- Cap height -- Descender depth. ---- -- Because Wumpus always needs font metrics respective to the current -- point size, the actual fields are all functions. data FontMetrics FontMetrics :: (FontSize -> BoundingBox Double) -> (FontSize -> CharWidthLookup) -> (FontSize -> Double) -> (FontSize -> Double) -> FontMetrics get_bounding_box :: FontMetrics -> FontSize -> BoundingBox Double get_cw_table :: FontMetrics -> FontSize -> CharWidthLookup get_cap_height :: FontMetrics -> FontSize -> Double get_descender :: FontMetrics -> FontSize -> Double -- | A map between a font name and the respective FontMetrics. data FontTable emptyFontTable :: FontTable -- | lookupFont : name * font_table -> Maybe FontMetrics -- -- -- Lookup a font in the font_table. lookupFont :: FontName -> FontTable -> Maybe FontMetrics -- | insertFont : name * font_metrics * font_table -> -- FontTable -- -- Insert a named font into the font_table. insertFont :: FontName -> FontMetrics -> FontTable -> FontTable -- | FontLoadMsg - type synonym for String. type FontLoadMsg = String -- | FontLoadLog is a Hughes list of Strings, so it supports -- efficient append. data FontLoadLog fontLoadMsg :: String -> FontLoadLog data FontLoadResult FontLoadResult :: FontTable -> FontLoadLog -> FontLoadResult loaded_font_table :: FontLoadResult -> FontTable loader_errors :: FontLoadResult -> FontLoadLog -- | Print the loader errors from the FontLoadResult to std-out. printLoadErrors :: FontLoadResult -> IO () -- | This ignores the Char code lookup and just returns the default advance -- vector. monospace_metrics :: FontMetrics instance Eq FontDef instance Ord FontDef instance Show FontDef instance Monoid FontLoadLog instance Monoid FontTable -- | Datatypes module Wumpus.Basic.System.FontLoader.Datatypes -- | Afm files index glyphs by PostScript character code. This is -- not the same as Unicode, ASCII... -- -- It is expected to be determined by EncodingScheme in the -- Global Font Information Section. type PSCharCode = Int type PSEncodingScheme = String type AfmBoundingBox = BoundingBox AfmUnit type AfmKey = String type GlobalInfo = Map AfmKey String -- | Wumpus needs a very small subset of AFM files, common to both version -- 2.0 and version 4.1. -- -- Note - Bounding Box is mandatory for AFM versions 3.0 and 4.1 -- -- Cap Height is optional in AFM versions 3.0 and 4.1. As Wumpus uses cap -- height in calculations, glyph metrics must be build with an arbitrary -- value if it is not present. -- -- Encoding Scheme is optional in AFM files. data AfmFile AfmFile :: Maybe String -> Maybe AfmBoundingBox -> Maybe AfmUnit -> Maybe AfmUnit -> [AfmGlyphMetrics] -> AfmFile afm_encoding :: AfmFile -> Maybe String afm_letter_bbox :: AfmFile -> Maybe AfmBoundingBox afm_cap_height :: AfmFile -> Maybe AfmUnit afm_descender :: AfmFile -> Maybe AfmUnit afm_glyph_metrics :: AfmFile -> [AfmGlyphMetrics] data AfmGlyphMetrics AfmGlyphMetrics :: !PSCharCode -> !Vec2 AfmUnit -> !String -> AfmGlyphMetrics afm_char_code :: AfmGlyphMetrics -> !PSCharCode afm_width_vector :: AfmGlyphMetrics -> !Vec2 AfmUnit afm_char_name :: AfmGlyphMetrics -> !String -- | Monospace defaults are used if the font loader fails to extract the -- necessary fields. -- -- The values are taken from the font correpsonding to Courier in the -- distributed font files. data MonospaceDefaults cu MonospaceDefaults :: BoundingBox cu -> cu -> cu -> Vec2 cu -> MonospaceDefaults cu default_letter_bbox :: MonospaceDefaults cu -> BoundingBox cu default_cap_height :: MonospaceDefaults cu -> cu default_descender :: MonospaceDefaults cu -> cu default_char_width :: MonospaceDefaults cu -> Vec2 cu -- | The metrics read from a font file by a font loader. -- -- NOTE - FontProps is parametric on cu - Character Unit -- and not on the usual u. A typical character unit is -- AfmUnit, the unit of measurement for AFM files (1000th of a -- point). -- -- The is the initial representation used by Wumpus-Basic as an syntax -- tree when loading font files. data FontProps cu FontProps :: BoundingBox cu -> Vec2 cu -> IntMap (Vec2 cu) -> cu -> cu -> FontProps cu fp_bounding_box :: FontProps cu -> BoundingBox cu fp_default_adv_vec :: FontProps cu -> Vec2 cu fp_adv_vecs :: FontProps cu -> IntMap (Vec2 cu) fp_cap_height :: FontProps cu -> cu fp_descender :: FontProps cu -> cu -- | Build a MetricsOps function table, from a character unit scaling -- function and FontProps read from a file. buildMetricsOps :: (FontSize -> cu -> Double) -> FontProps cu -> FontMetrics instance Eq AfmGlyphMetrics instance Show AfmGlyphMetrics instance Show AfmFile instance (Ord cu, Tolerance cu) => Eq (MonospaceDefaults cu) instance Show cu => Show (MonospaceDefaults cu) -- | Common parsers for AFM files. module Wumpus.Basic.System.FontLoader.AfmParserBase afmFileParser :: CharParser AfmGlyphMetrics -> CharParser AfmFile runQuery :: String -> CharParser a -> GlobalInfo -> Maybe a textQuery :: String -> GlobalInfo -> Maybe String -- | Strictly speaking a fontBBox is measured in integer units. getFontBBox :: GlobalInfo -> Maybe AfmBoundingBox getEncodingScheme :: GlobalInfo -> Maybe String getCapHeight :: GlobalInfo -> Maybe AfmUnit charBBox :: CharParser AfmBoundingBox metric :: String -> a -> CharParser a -> CharParser a keyStringPair :: CharParser (AfmKey, String) versionNumber :: CharParser String startCharMetrics :: CharParser Int keyName :: CharParser AfmKey newlineOrEOF :: CharParser () name :: CharParser String name1 :: CharParser String semi :: CharParser Char uptoNewline :: CharParser String number :: CharParser AfmUnit cint :: CharParser Int hexInt :: CharParser Int octInt :: CharParser Int lexeme :: CharParser a -> CharParser a symbol :: String -> CharParser String integer :: CharParser Integer int :: CharParser Int double :: CharParser Double -- | AFM file parser for Version 4.1. -- -- Adobe distributes font metrics for the Core 14 fonts as AFM -- Version 4.1 files. module Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser afmV4Dot1Parser :: CharParser AfmFile -- | AFM file parser for Version 2.0. -- -- Note - AFM Version 2.0 used by GhostScript and Version 3.0+ have -- numerous differences. module Wumpus.Basic.System.FontLoader.AfmV2Parser afmV2Parser :: CharParser AfmFile -- | The elementary base types and classes. module Wumpus.Basic.Kernel.Base.BaseDefs -- | Type family to access the unit parameter of a TraceDrawing or a -- promoted TraceDrawingT transformer. -- | A Semigroup class. -- -- The perhaps unusual name is the TeX name for the circled plus glyph. -- It would be nice if there was a semigroup class in the Haskell Base -- libraries... class OPlus t oplus :: OPlus t => t -> t -> t -- | oconcat : list_head * [rest] -> Ans -- -- Semigroup version of mconcat from the module -- Data.Monoid. -- -- As a semigroup cannot build a zero value, concat cannot handle -- the empty list. So to make oconcat a safe function the input -- list is already destructured by one cons cell. -- -- Effectively this means that client code must handle the empty list -- case, before calling oconcat. oconcat :: OPlus t => t -> [t] -> t -- | altconcat : alternative * [list] -> Ans -- -- altconcat uses oplus to create a summary value from a -- list of values. -- -- When supplied the empty list altconcat returns the supplied -- alternative value. If the list is inhabited, the alternative -- value is discarded. -- -- This contrasts to oconcat where the single value represents the -- head of an already destructured list. altconcat :: OPlus a => a -> [a] -> a -- | A Bifunctor class. -- -- Again, it would be nice if there was a Bifunctor class in the Haskell -- Base libraries... class Bimap f bimap :: Bimap f => (a -> p) -> (b -> q) -> f a b -> f p q bimapL :: Bimap f => (a -> p) -> f a b -> f p b bimapR :: Bimap f => (b -> q) -> f a b -> f a q replaceL :: Bimap f => p -> f a b -> f p b replaceR :: Bimap f => q -> f a b -> f a q -- | The empty data type - i.e. () - wrapped with a phantom unit -- parameter. data UNil u UNil :: UNil u class ScalarUnit a fromPsPoint :: ScalarUnit a => Double -> a toPsPoint :: ScalarUnit a => a -> Double class Num u => InterpretUnit u normalize :: InterpretUnit u => FontSize -> u -> Double dinterp :: InterpretUnit u => FontSize -> Double -> u -- | dinterp an object that gives access to its unit at the functor -- position. dinterpF :: (Functor t, InterpretUnit u) => FontSize -> t Double -> t u -- | normalize an object that gives access to its unit at the -- functor position. normalizeF :: (Functor t, InterpretUnit u) => FontSize -> t u -> t Double -- | Convert a scalar value from one unit to another. uconvert1 :: (InterpretUnit u, InterpretUnit u1) => FontSize -> u -> u1 -- | Unit convert an object that gives access to its unit at the Functor -- position. -- -- In practive this will be *all* Image answers. uconvertF :: (Functor t, InterpretUnit u, InterpretUnit u1) => FontSize -> t u -> t u1 intraMapPoint :: InterpretUnit u => FontSize -> (DPoint2 -> DPoint2) -> Point2 u -> Point2 u intraMapFunctor :: (Functor f, InterpretUnit u) => FontSize -> (f Double -> f Double) -> f u -> f u data DrawStyle FILL :: DrawStyle STROKE :: DrawStyle FILL_STROKE :: DrawStyle -- | Decorating with resepct to the Z-order -- --
-- SUPERIOR - in front. ---- --
-- ANTERIOR - behind. --data ZDeco SUPERIOR :: ZDeco ANTERIOR :: ZDeco -- | Horizontal alignment - align to the top, center or bottom. data HAlign HTop :: HAlign HCenter :: HAlign HBottom :: HAlign -- | Vertical alignment - align to the left, center or bottom. data VAlign VLeft :: VAlign VCenter :: VAlign VRight :: VAlign -- | An enumeratied type representing the compass positions. data Cardinal NORTH :: Cardinal NORTH_EAST :: Cardinal EAST :: Cardinal SOUTH_EAST :: Cardinal SOUTH :: Cardinal SOUTH_WEST :: Cardinal WEST :: Cardinal NORTH_WEST :: Cardinal -- | An enumerated type representing horizontal and vertical directions. data Direction UP :: Direction DOWN :: Direction LEFT :: Direction RIGHT :: Direction -- | Sum a list of Vectors. -- -- Note - this function is a candidate to go in Wumpus-Core, but it will -- be added when there is an intrinsic reason to to update Core (bug fix, -- or API change). vsum :: Num u => [Vec2 u] -> Vec2 u instance Eq (UNil u) instance Ord (UNil u) instance Read (UNil u) instance Show (UNil u) instance Bounded DrawStyle instance Enum DrawStyle instance Eq DrawStyle instance Ord DrawStyle instance Show DrawStyle instance Bounded ZDeco instance Enum ZDeco instance Eq ZDeco instance Ord ZDeco instance Show ZDeco instance Enum HAlign instance Eq HAlign instance Ord HAlign instance Show HAlign instance Enum VAlign instance Eq VAlign instance Ord VAlign instance Show VAlign instance Enum Cardinal instance Eq Cardinal instance Ord Cardinal instance Show Cardinal instance Enum Direction instance Eq Direction instance Ord Direction instance Show Direction instance InterpretUnit AfmUnit instance InterpretUnit Double instance ScalarUnit Double instance Translate (UNil u) instance Scale (UNil u) instance RotateAbout (UNil u) instance Rotate (UNil u) instance OPlus (UNil u) instance Monoid (UNil u) instance Functor UNil instance Bimap Either instance Bimap (,) instance Num u => OPlus (Vec2 u) instance OPlus a => OPlus (r -> a) instance (OPlus a, OPlus b, OPlus c, OPlus d) => OPlus (a, b, c, d) instance (OPlus a, OPlus b, OPlus c) => OPlus (a, b, c) instance (OPlus a, OPlus b) => OPlus (a, b) instance OPlus Primitive instance Ord u => OPlus (BoundingBox u) instance OPlus a => OPlus (Const a b) instance OPlus () -- | Units cm, pica and "contextual" units - em, -- en. module Wumpus.Basic.Kernel.Base.Units -- | Wrapped Double representing Centimeter. data Centimeter -- | Cast a value in Centimeters to some Fractional type. -- -- Note - this casting should only be used for non-contextual units such -- as Double. cm :: Fractional u => Centimeter -> u -- | Convert Double to Centimer. dcm :: Double -> Centimeter -- | Wrapped Double Pica unit type. -- -- Pica is 12 Points. data Pica -- | Cast a value in Pica to some Fractional type. -- -- Note - this casting should only be used for non-contextual units such -- as Double. pica :: Fractional u => Pica -> u -- | Convert a Double to a Pica. dpica :: Double -> Pica -- | Wrapped Double representing an Em. data Em -- | Wrapped Double representing an En. data En instance Eq Centimeter instance Ord Centimeter instance Num Centimeter instance Floating Centimeter instance Fractional Centimeter instance Real Centimeter instance RealFrac Centimeter instance RealFloat Centimeter instance Eq Pica instance Ord Pica instance Num Pica instance Floating Pica instance Fractional Pica instance Real Pica instance RealFrac Pica instance RealFloat Pica instance Eq Em instance Ord Em instance Num Em instance Floating Em instance Fractional Em instance Real Em instance RealFrac Em instance RealFloat Em instance Eq En instance Ord En instance Num En instance Floating En instance Fractional En instance Real En instance RealFrac En instance RealFloat En instance Tolerance En instance Tolerance Em instance InterpretUnit En instance Show En instance Tolerance Centimeter instance InterpretUnit Em instance Show Em instance InterpretUnit Pica instance ScalarUnit Pica instance Tolerance Pica instance Show Pica instance InterpretUnit Centimeter instance ScalarUnit Centimeter instance Show Centimeter -- | Drawing attributes -- -- ** WARNING ** - The drawing context modules need systematic naming -- schemes both for update functions (primaryColour, ...) and for -- synthesized selectors (e.g. lowerxHeight). The current names in -- QueryDC and UpdateDC are expected to change. module Wumpus.Basic.Kernel.Base.DrawingContext -- | DrawingContext - the "graphics state" of Wumpus-Basic. -- DrawingContext is operated on within a Reader monad rather than a -- State monad so "updates" are delineated within a local -- operation (called localize in Wumpus), rather than permanent -- until overridden as per set of a State monad. -- -- Note - in contrast to most other drawing objects in Wumpus, none of -- the types of measurement values are parameteric (usually notated with -- the type variable u in Wumpus). Types are either -- Double representing PostScript points or Em - a contextual size -- that is interpreted according to the current font size. -- -- It is easier to specialize all the measurement types and within the -- DrawingContext and add parametricity to the getters and -- setters instead. data DrawingContext DrawingContext :: FontTable -> FontLoadLog -> FontMetrics -> FontFace -> !FontSize -> (Double, Double) -> StrokeAttr -> RGBi -> RGBi -> RGBi -> Double -> TextMargin -> ConnectorProps -> DrawingContext dc_font_metrics_table :: DrawingContext -> FontTable dc_font_load_log :: DrawingContext -> FontLoadLog dc_fallback_metrics :: DrawingContext -> FontMetrics dc_font_face :: DrawingContext -> FontFace dc_font_size :: DrawingContext -> !FontSize dc_snap_grid_factors :: DrawingContext -> (Double, Double) dc_stroke_props :: DrawingContext -> StrokeAttr dc_stroke_colour :: DrawingContext -> RGBi dc_fill_colour :: DrawingContext -> RGBi dc_text_colour :: DrawingContext -> RGBi dc_line_spacing_factor :: DrawingContext -> Double dc_text_margin :: DrawingContext -> TextMargin dc_connector_props :: DrawingContext -> ConnectorProps -- | Type synonym for DrawingContext update functions. type DrawingContextF = DrawingContext -> DrawingContext -- | The text margin is measured in Em so it is relative to the -- current font size. -- -- The default value is 0.5. data TextMargin TextMargin :: !Em -> !Em -> TextMargin text_margin_x :: TextMargin -> !Em text_margin_y :: TextMargin -> !Em -- | ConnectorProps control the drawing of connectors in Wumpus-Drawing. -- --
-- conn_src_space :: Em -- conn_dst_space :: Em ---- -- Source and destination spacers - these add spacing between the -- respective connector points and the tips of the drawn connector. -- --
-- conn_src_offset :: Em -- conn_dst_offset :: Em ---- -- Source and destination offsets - these offset the drawing of the -- connector perpendicular to the direction of line formed between the -- connector points (a positive offset is drawn above, a negative offset -- below). The main use of offsets is to draw parallel line connectors. -- --
-- conn_arc_ang :: Radian ---- -- Control the bend of an arc connector. -- --
-- conn_src_arm :: Em -- conn_dst_arm :: Em ---- -- Control the arm length of a jointed connector - arms are the -- initial segments of the connector. -- --
-- conn_loop_size :: Em ---- -- Control the height of a loop connector. -- --
-- conn_box_halfsize :: Em ---- -- Control the size of a connector box. Connector boxes are drawn with -- the exterior lines projected out from the connector points a halfsize -- above and below. data ConnectorProps ConnectorProps :: !Em -> !Em -> !Em -> !Em -> !Radian -> !Em -> !Em -> !Em -> !Em -> ConnectorProps dc_conn_src_space :: ConnectorProps -> !Em dc_conn_dst_space :: ConnectorProps -> !Em dc_conn_src_offset :: ConnectorProps -> !Em dc_conn_dst_offset :: ConnectorProps -> !Em dc_conn_arc_ang :: ConnectorProps -> !Radian dc_conn_src_arm :: ConnectorProps -> !Em dc_conn_dst_arm :: ConnectorProps -> !Em dc_conn_loop_size :: ConnectorProps -> !Em dc_conn_box_halfsize :: ConnectorProps -> !Em -- | standardContext : font_size -> DrawingContext -- -- Create a DrawingContext. -- -- Note - font_size is used for sizing more than just text -- labels. Arrowheads, plot marks and other elements have their metrics -- derived from the font size. -- -- No real font metrics are present in the DrawingContext created -- by standardContext. Static, hard-coded fallback metrics derived -- from the Courier font are available but these metrics might -- not accurately correspond to the Courier available to the the -- final renderer (GhostScript, an SVG viewer, etc.). -- -- Use this constructor for drawings that make primitive use of text. -- --
-- font_metrics_table: empty -- font_load_log: empty -- fallback_metrics: monospace_metrics -- font_face: Courier -- font_size: @supplied_font_size@ -- stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter. -- stroke_colour: black -- fill_colour: light_gray -- text_colour: black -- line_spacing_factor: 0.2 -- round_corner_factor: 0 -- text_margin: (0.5 em, 0.5 em) ---- --
-- conn_src_sep: 0 -- conn_dst_sep: 0 -- conn_src_offset: 0 -- conn_dst_offset: 0 -- conn_arc_ang: pi / 12 -- conn_src_arm: 1 -- conn_dst_arm: 1 -- conn_loop_size: 2 --standardContext :: FontSize -> DrawingContext -- | metricsContext : font_size * font_metrics -> -- DrawingContext -- -- Create a DrawingContext with font metrics loaded from the file -- system. -- -- Note - font_size is used for sizing more than just text -- labels. Arrowheads, plot marks and other elements have their metrics -- derived from the font size. -- -- Use this constructor for drawings that make use of the text objects -- provided by Wumpus-Drawing (DocText and RotText). metricsContext :: FontSize -> FontLoadResult -> DrawingContext -- | addFontTables : font_load_result -> DrawinContextUpdate -- -- -- Add the font metrics from the FontLoadResult, if a font with the same -- name alreay exists in the DrawingContext it will be replaced. -- Error and warning messages in the font_load_result will be -- appended to the font_load_log. addFontTables :: FontLoadResult -> DrawingContextF -- | reset_drawing_properties : DrawingContextF -- -- Reset the drawing properties in the DrawingContext to their -- default values. This changes the following fields: -- --
-- stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter. -- stroke_colour: black -- fill_colour: light_gray -- text_colour: black -- line_spacing_factor: 0.2 -- round_corner_factor: 0 -- text_margin: (0.5 em, 0.5 em) --reset_drawing_properties :: DrawingContextF -- | reset_drawing_metrics : DrawingContextF -- -- Reset the drawing metrics in the DrawingContext to their -- default values. This is a more limited version of -- reset_drawing_properties and changes the following fields: -- --
-- stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter. -- line_spacing_factor: 0.2 -- round_corner_factor: 0 -- text_margin: (0.5 em, 0.5 em) --reset_drawing_metrics :: DrawingContextF -- | DrawingCtxM is equivalent to the to the MonadReader -- class, but the environment type is fixed to DrawingContext. -- -- To avoid name clashes with mtl this scheme is used: -- --
-- askDC = ask -- asksDC = asks -- localize = local ---- -- Note, because the derived operation query (aka asks) -- is expected to be used more often than queryCtx (aka ask) it -- gets the more convenient name. class (Applicative m, Monad m) => DrawingCtxM m :: (* -> *) askDC :: DrawingCtxM m => m DrawingContext asksDC :: DrawingCtxM m => (DrawingContext -> a) -> m a localize :: DrawingCtxM m => (DrawingContext -> DrawingContext) -> m a -> m a withFontMetrics :: (FontMetrics -> FontSize -> u) -> DrawingContext -> u -- | Querying the Drawing Context. -- -- ** WARNING ** - parts of this module especially the mono-space glyph -- metrics need a re-think and will change or be dropped. module Wumpus.Basic.Kernel.Base.QueryDC normalizeCtx :: (DrawingCtxM m, InterpretUnit u) => u -> m Double normalizeCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u) => t u -> m (t Double) dinterpCtx :: (DrawingCtxM m, InterpretUnit u) => Double -> m u dinterpCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u) => t Double -> m (t u) uconvertCtx1 :: (DrawingCtxM m, InterpretUnit u, InterpretUnit u1) => u -> m u1 uconvertCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u, InterpretUnit u1) => t u -> m (t u1) pointSize :: DrawingCtxM m => m FontSize strokeAttr :: DrawingCtxM m => m (RGBi, StrokeAttr) fillAttr :: DrawingCtxM m => m RGBi borderedAttr :: DrawingCtxM m => m (RGBi, StrokeAttr, RGBi) textAttr :: DrawingCtxM m => m (RGBi, FontAttr) -- | Get the Point corresponding the grid coordinates scaled by the -- snap-grid scaling factors. position :: (DrawingCtxM m, Fractional u) => (Int, Int) -> m (Point2 u) -- | Scale a vector coordinate by the snap-grid scaling factors. -- -- Absolute units. snapmove :: (DrawingCtxM m, Fractional u) => (Int, Int) -> m (Vec2 u) -- | Get the (x,y) margin around text. -- -- Note - not all text operations in Wumpus are drawn with text margin. textMargin :: (DrawingCtxM m, InterpretUnit u) => m (u, u) getLineWidth :: DrawingCtxM m => m Double getFontAttr :: DrawingCtxM m => m FontAttr getFontSize :: DrawingCtxM m => m Int getFontFace :: DrawingCtxM m => m FontFace getTextColour :: DrawingCtxM m => m RGBi -- | Vertical distance between descender of a line and the cap-height of -- the line below. textlineSpace :: (DrawingCtxM m, Fractional u, InterpretUnit u) => m u -- | Get the font bounding box - this is the maximum boundary of the glyphs -- in the font. The span of the height is expected to be bigger than the -- cap_height plus descender depth. glyphBoundingBox :: (DrawingCtxM m, InterpretUnit u) => m (BoundingBox u) -- | Height of a capital letter. capHeight :: (DrawingCtxM m, InterpretUnit u) => m u -- | Note - descender is expected to be negative. descender :: (DrawingCtxM m, InterpretUnit u) => m u -- | This is the distance from cap_height to descender. verticalSpan :: (DrawingCtxM m, InterpretUnit u) => m u -- | Note the CharWidthLookup is not parameteric on units. -- -- CharWidth is always Double representing PostScript points. -- Client code must convert this value accordingly. cwLookupTable :: DrawingCtxM m => m CharWidthLookup connectorSrcSpace :: (DrawingCtxM m, InterpretUnit u) => m u connectorDstSpace :: (DrawingCtxM m, InterpretUnit u) => m u connectorSrcOffset :: (DrawingCtxM m, InterpretUnit u) => m u connectorDstOffset :: (DrawingCtxM m, InterpretUnit u) => m u connectorArcAngle :: DrawingCtxM m => m Radian connectorSrcArm :: (DrawingCtxM m, InterpretUnit u) => m u connectorDstArm :: (DrawingCtxM m, InterpretUnit u) => m u connectorLoopSize :: (DrawingCtxM m, InterpretUnit u) => m u connectorBoxHalfSize :: (DrawingCtxM m, InterpretUnit u) => m u -- | Customize drawing attributes. The functions here are -- DrawingContext modifiers to be run within a the scope of a -- localize block (cf. local of the Reader monad). -- -- By convention, underscore-separated names are used for DrawingContext -- modifiers in this module. This is because the modifiers defined here -- are expected to be used mostly as static "properties" resembling -- constants in drawings. module Wumpus.Basic.Kernel.Base.UpdateDC -- | snap_grid_factors : x_unit * y_unit -> DrawingContextF -- -- -- Set the snap grid factors - a snap grid is an alternative -- coordinate space, it can be convenient for drawing "box and arrow" -- diagrams. snap_grid_factors :: Double -> Double -> DrawingContextF -- | set_line_width : width_in_points -> DrawingContextF -- -- Set the line_width to the supplied point size. -- -- Initially the line width is 1.0. -- -- Constant variations of the function maybe be more convenient: -- --
-- line_default, line_thin, line_thick, line_ultra_thick --set_line_width :: Double -> DrawingContextF -- | Set the line_width to default - 1.0. line_default :: DrawingContextF -- | Set the line_width to thin - 0.5. line_thin :: DrawingContextF -- | Set the line_width to thick - 2.0. line_thick :: DrawingContextF -- | Set the line_width to ultra_thick - 4.0. line_ultra_thick :: DrawingContextF -- | Set the line width to a size relative to the current font size. The -- size is calculated with the supplied function. relative_line_width :: (FontSize -> Double) -> DrawingContextF -- | Set the line_cap to the default which is butt. -- -- This is a synonym for cap_butt. cap_default :: DrawingContextF -- | Set the line_cap to butt. -- -- Butt chamfers off the stroke, flush to the end point. -- -- This is the default. -- --
-- .-------. -- |=======| -- '-------' --cap_butt :: DrawingContextF -- | Set the line_cap to round. -- -- This rounds the end of the stroke and the visually the rounding -- slightly extends the length of the line. -- --
-- .-------. -- ( ======= ) -- '-------' --cap_round :: DrawingContextF -- | Set the line_cap to square. -- -- This squares off the end of the stroke, but visual extends the stroke -- by half the line width. -- --
-- .---------. -- | ======= | -- '---------' --cap_square :: DrawingContextF -- | Set the line_join to the default which is miter. -- -- This is a synonym for join_miter. join_default :: DrawingContextF -- | Set the line_join to miter. -- -- This extends the joining line segments to form a sharp miter. -- -- This is the default. -- --
-- /\ -- /..\ -- /./\.\ -- /./ \.\ -- /./ \.\ --join_miter :: DrawingContextF -- | Set the line_join to round. -- -- This rounds off the corner of the joined line segments. -- --
-- \.\ -- \.\ -- ,.) -- /./ -- /./ --join_round :: DrawingContextF -- | Set the line_join to round. -- -- This bevels off the corner of the joined line segments with a notch. -- --
-- __ -- /..\ -- /./\.\ -- /./ \.\ -- /./ \.\ --join_bevel :: DrawingContextF -- | Set the dash pattern. -- -- Initially the dash pattern is Solid. set_dash_pattern :: DashPattern -> DrawingContextF -- | Set the dash_pattern to solid - i.e. no dash pattern. -- -- This is the default. solid_line :: DrawingContextF -- | Set the dash pattern to draw a dotted line. -- -- A dot is actually a square - side length is equal to the line width. -- -- The spacing between dots is 2 times the dot width. dotted_line :: DrawingContextF -- | Set the dash pattern to draw a tightly packed dotted line. -- -- A dot is actually a square - side length is equal to the line width. -- -- The spacing between dots is equal to the dot width. packed_dotted :: DrawingContextF -- | Set the dash pattern to draw a loosely dotted line. -- -- A dot is actually a square - side length is equal to the line width. -- -- The spacing between dots is 4 times the dot width. loose_dotted :: DrawingContextF -- | Set the dash pattern to draw a dashed line. -- -- The dash length is 3 times the line width, the spacing is 2 times the -- line width. dashed_line :: DrawingContextF -- | Set the dash pattern to draw a tightly packed, dashed line. -- -- The dash length is 3 times the line width, the spacing is equal to the -- line width. packed_dashed :: DrawingContextF -- | Set the dash pattern to draw a loosely dashed line. -- -- The dash length is 3 times the line width, the spacing is 4 times the -- line width. loose_dashed :: DrawingContextF -- | Set the font attributes, point size and font face. font_attr :: FontDef -> Int -> DrawingContextF -- | Set the font face. set_font :: FontDef -> DrawingContextF -- | Set the point size. -- -- This controls the drawing size of both text labels and marks (e.g. -- dots and arrowheads). set_font_size :: Int -> DrawingContextF -- | Scale the current point size by the supplied ratio. -- -- Note - as fonts can only be drawn at integral sizes this operation is -- not exact - for instance scaling 15pt by (1%2) results in 7pt. scale_point_size :: Double -> DrawingContextF -- | Set the point size (font and mark size) to double the current size. double_point_size :: DrawingContextF -- | Set the point size to half the current size, note the point size also -- controls the size of dots, arrowsheads etc. -- -- Note - as fonts can only be drawn at integral sizes this operation is -- not exact - half size of 15pt type is 7pt. half_point_size :: DrawingContextF -- | text_margin : x_sep * y_sep -> DrawingContextF -- -- Note - this is in Em units. text_margin :: Em -> Em -> DrawingContextF -- | Set the text margin to (0,0). -- -- This produces a tight box around the text vertically measured to the -- cap-height and descender. Therefore some characters may extend outside -- the margin (e.g. accented capitals like A-grave). text_margin_none :: DrawingContextF -- | Set the text margin to (0.25 em, 0.25 em). text_margin_tight :: DrawingContextF -- | Set the text margin to (0.5 em, 0.5 em). text_margin_default :: DrawingContextF -- | Set the text margin to (1.0 em, 1.0 em). text_margin_loose :: DrawingContextF -- | Set the stroke colour. stroke_colour :: RGBi -> DrawingContextF -- | Set the fill colour. fill_colour :: RGBi -> DrawingContextF -- | Set the text colour. text_colour :: RGBi -> DrawingContextF -- | Set the stroke, fill and text colours to a single colour. single_colour :: RGBi -> DrawingContextF -- | Swap the stroke colour and fill colours. swap_colours :: DrawingContextF -- | Set the fill colour to use the current stroke colour. fill_use_stroke_colour :: DrawingContextF -- | Set the stroke colour to use the current fill colour. stroke_use_fill_colour :: DrawingContextF -- | Set the fill colour to use the current text colour. fill_use_text_colour :: DrawingContextF -- | Set the stroke colour to use the current fill colour. stroke_use_text_colour :: DrawingContextF -- | Set the text colour to use the current stroke colour. text_use_stroke_colour :: DrawingContextF -- | Set the text colour to use the current fill colour. text_use_fill_colour :: DrawingContextF -- | Set the connector source spacing. -- -- The spacing is used as a projection along the line formed between -- connector points making the connection looser if required. -- -- The default value is 0. Negative values are not allowed, they are -- normalized to 0. source_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF -- | Set the connector destination spacing. -- -- The spacing is used as a projection along the line formed between -- connector points making the connection looser if required. -- -- The default value is 0. Negative values are not allowed, they are -- normalized to 0. dest_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF -- | Set the connector source offset. -- -- The offset is used to shift the start point upwards -- perpendicular to its true origin (negative values are downwards). This -- can be used to draw a connector with two parallel lines, for example. -- -- Upwards and downwards in this description are dependent on the -- direction of the line, of course. Generally the documentations -- consider lines are left-to-right unless specifically noted. source_offset :: (Ord u, InterpretUnit u) => u -> DrawingContextF -- | Set the connector destination offset. -- -- See source_offset for an explanation. dest_offset :: (Ord u, InterpretUnit u) => u -> DrawingContextF -- | Set the connector source and destination spacings to the same length. uniform_conn_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF -- | Set the connector arc angle. conn_arc_angle :: Radian -> DrawingContextF -- | Set the connector source arm length. source_arm_len :: InterpretUnit u => u -> DrawingContextF -- | Set the connector destination arm length. dest_arm_len :: InterpretUnit u => u -> DrawingContextF -- | Set the connector source and destination arms to the same length. uniform_arm_len :: InterpretUnit u => u -> DrawingContextF -- | Set the connector loop size. conn_loop_size :: InterpretUnit u => u -> DrawingContextF -- | Set the connector box halfsize. conn_box_halfsize :: InterpretUnit u => u -> DrawingContextF -- | Wrapped versions of the Primitive type from Wumpus-Core. -- -- This file is essentially internal to Wumpus-Basic. module Wumpus.Basic.Kernel.Base.WrappedPrimitive -- | A wrapped version of Primitive from Wumpus-Core that supports -- Monoid. -- -- This type is essentially internal to Wumpus-Basic. data CatPrim prim1 :: Primitive -> CatPrim -- | Map cpmap :: (Primitive -> Primitive) -> CatPrim -> CatPrim -- | Graphics objects, even simple ones (line, arrow, dot) might need more -- than one primitive (path or text label) for their construction. Hence, -- the primary representation that all the others are built upon must -- support concatenation of primitives. -- -- Wumpus-Core has a type Picture - made from one or more Primitives - -- but Pictures include support for affine frames. For drawing many -- simple graphics (dots, connector lines...) that do not need individual -- affine transformations this is a penalty. A list of Primitives is -- therefore more suitable representation, and a Hughes list which -- supports efficient concatenation is wise. -- -- This type is essentially internal to Wumpus-Basic. data HPrim u -- | Extract the internal list of Primitive from a HPrim. hprimToList :: HPrim u -> [Primitive] -- | Form a HPrim from a CatPrim. singleH :: CatPrim -> HPrim u instance Monoid (HPrim u) instance Translate CatPrim instance Scale CatPrim instance RotateAbout CatPrim instance Rotate CatPrim instance Monoid CatPrim instance OPlus CatPrim -- | Common types and operations. module Wumpus.Basic.Kernel.Objects.Basis -- | Unit u is a phantom. data PrimW u a PrimW :: CatPrim -> a -> PrimW u a primAnswer :: PrimW u a -> a data Image u a type Graphic u = Image u (UNil u) data Query u a -- | Type specialized version of Image. type DImage a = Image Double a -- | Type specialized version of Graphic. type DGraphic = Graphic Double runImage :: DrawingContext -> Image u a -> PrimW u a runQuery :: DrawingContext -> Query u a -> a zapQuery :: Query u a -> Image u a -- | Constructor for Primtive graphics. primGraphic :: CatPrim -> Graphic u -- | Clip an Image. clipImage :: PrimPath -> Image u a -> Image u a class UConvert f :: (* -> * -> *) uconvF :: (UConvert f, Functor t, InterpretUnit u, InterpretUnit u1) => f u (t u) -> f u1 (t u1) uconvZ :: (UConvert f, InterpretUnit u, InterpretUnit u1) => f u a -> f u1 a uconvImageF :: (Functor t, InterpretUnit u, InterpretUnit u1) => Image u (t u) -> Image u1 (t u1) uconvImageZ :: (InterpretUnit u, InterpretUnit u1) => Image u a -> Image u1 a -- | Having empty at the specific Image type is useful. emptyImage :: Monoid a => Image u a both :: Applicative f => f a -> f b -> f (a, b) -- | Note - the kind of f allows fo unit annotation. ignoreAns :: Functor (f u) => f u a -> f u (UNil u) -- | Replace the answer produced by a graphic object. replaceAns :: Functor (f u) => a -> f u z -> f u a -- | Decorate an object -- -- oliterate - drops the graphic from the first object replacing it with -- the graphic from the second. class Decorate f :: (* -> * -> *) decorate :: Decorate f => f u a -> f u z -> f u a elaborate :: Decorate f => f u a -> (a -> f u z) -> f u a obliterate :: Decorate f => f u a -> f u z -> f u a hyperlink :: Decorate f => XLink -> f u a -> f u a instance (u ~ DUnit a, Translate a, InterpretUnit u) => Translate (Image u a) instance Scale a => Scale (Image u a) instance (u ~ DUnit a, RotateAbout a, InterpretUnit u) => RotateAbout (Image u a) instance Rotate a => Rotate (Image u a) instance (u ~ DUnit a, Translate a, ScalarUnit u) => Translate (PrimW u a) instance Scale a => Scale (PrimW u a) instance (u ~ DUnit a, RotateAbout a, ScalarUnit u) => RotateAbout (PrimW u a) instance Rotate a => Rotate (PrimW u a) instance Decorate Image instance UConvert Image instance DrawingCtxM (Query u) instance DrawingCtxM (Image u) instance Monoid a => Monoid (Query u a) instance Monoid a => Monoid (Image u a) instance Monad (Query u) instance Monad (Image u) instance Applicative (Query u) instance Applicative (Image u) instance Functor (Query u) instance Functor (Image u) instance Monad (PrimW u) instance Applicative (PrimW u) instance Functor (PrimW u) instance Monoid a => Monoid (PrimW u a) -- | Classes for concatenation. module Wumpus.Basic.Kernel.Objects.Concat -- | Minimal defintion is superior, anterior is usually -- flip superior. -- --
-- `superior` (infixr 6) ---- --
-- `anterior` (infixr 6) --class ZConcat o anterior :: ZConcat o => o -> o -> o superior :: ZConcat o => o -> o -> o cat :: (Monoid o, ZConcat o) => [o] -> o -- | Concatenation with movement - the second object is moved next -- to the first. -- --
-- hconcat is equivalent to @(<>)@ in WL-PPrint. -- (infixr 6) ---- --
-- vconcat is equivalent to @(<$>)@ in WL_PPrint. -- (infixr 5) --class Concat o hconcat :: Concat o => o -> o -> o vconcat :: Concat o => o -> o -> o -- | Horizontally concatenate a list of objects. -- -- Note - the first argument is an alternative - this is drawn if -- the list is empty, otherwise it is not drawn. hcat :: (Monoid o, Concat o) => [o] -> o -- | Vertically concatenate a list of objects. -- -- Note - the first argument is an alternative - this is drawn if -- the list is empty, otherwise it is not drawn. vcat :: (Monoid o, Concat o) => [o] -> o class CatSpace o hspace :: (CatSpace o, u ~ (DUnit o)) => u -> o -> o -> o vspace :: (CatSpace o, u ~ (DUnit o)) => u -> o -> o -> o hsep :: (Monoid o, CatSpace o, u ~ (DUnit o)) => u -> [o] -> o vsep :: (Monoid o, CatSpace o, u ~ (DUnit o)) => u -> [o] -> o class Align o halign :: Align o => HAlign -> o -> o -> o valign :: Align o => VAlign -> o -> o -> o alignRow :: (Monoid o, Align o) => HAlign -> [o] -> o alignColumn :: (Monoid o, Align o) => VAlign -> [o] -> o class AlignSpace o halignSpace :: (AlignSpace o, u ~ (DUnit o)) => HAlign -> u -> o -> o -> o valignSpace :: (AlignSpace o, u ~ (DUnit o)) => VAlign -> u -> o -> o -> o alignRowSep :: (Monoid o, AlignSpace o, u ~ (DUnit o)) => HAlign -> u -> [o] -> o alignColumnSep :: (Monoid o, AlignSpace o, u ~ (DUnit o)) => VAlign -> u -> [o] -> o -- | ConnImage and ConnGraphic types - these are functional types from the -- DrawingContext plus start point and end point to a graphic -- primitive. module Wumpus.Basic.Kernel.Objects.Connector -- | ConnectorImage - function from DrawingContext and start and end points -- to a polymorphic answer and a graphic primitive. data ConnectorImage u a type ConnectorGraphic u = ConnectorImage u (UNil u) -- | Type specialized version of ConnectorImage. type DConnectorImage a = ConnectorImage Double a -- | Type specialized version of ConnectorGraphic. type DConnectorGraphic = ConnectorGraphic Double data ConnectorQuery u a runConnectorImage :: Point2 u -> Point2 u -> DrawingContext -> ConnectorImage u a -> PrimW u a runConnectorQuery :: Point2 u -> Point2 u -> DrawingContext -> ConnectorQuery u a -> a connect :: Point2 u -> Point2 u -> ConnectorImage u a -> Image u a promoteConn :: (Point2 u -> Point2 u -> Image u a) -> ConnectorImage u a applyConn :: ConnectorImage u a -> Point2 u -> Point2 u -> Image u a qpromoteConn :: (Point2 u -> Point2 u -> Query u a) -> ConnectorQuery u a qapplyConn :: ConnectorQuery u a -> Point2 u -> Point2 u -> Query u a -- | "zero-apply" a Connector. zapConnectorQuery :: ConnectorQuery u a -> Point2 u -> Point2 u -> Image u a -- | Having empty at the specific ConnectorImage type is -- useful. emptyConnectorImage :: Monoid a => ConnectorImage u a instance UConvert ConnectorImage instance Decorate ConnectorImage instance DrawingCtxM (ConnectorQuery u) instance DrawingCtxM (ConnectorImage u) instance Monoid a => Monoid (ConnectorQuery u a) instance Monoid a => Monoid (ConnectorImage u a) instance Monad (ConnectorQuery u) instance Monad (ConnectorImage u) instance Applicative (ConnectorQuery u) instance Applicative (ConnectorImage u) instance Functor (ConnectorQuery u) instance Functor (ConnectorImage u) -- | Displacing points - often start points. module Wumpus.Basic.Kernel.Objects.Displacement -- | PointDisplace is a type representing functions from Point -- to Point. -- -- It is especially useful for building composite graphics where one part -- of the graphic is drawn from a different start point to the other -- part. type PointDisplace u = Point2 u -> Point2 u -- | ThetaPointDisplace is a type representing functions from -- Radian * Point to Point. -- -- It is useful for building arrowheads which are constructed with an -- implicit angle representing the direction of the line at the arrow -- tip. type ThetaPointDisplace u = Radian -> Point2 u -> Point2 u -- | displace : Vec2 -> PointDisplace -- -- Alias for .+^ from Data.AffineSpace. displace :: Num u => Vec2 u -> PointDisplace u -- | dispParallel : dist -> ThetaPointDisplace -- -- Build a combinator to move Points in parallel to the -- direction of the implicit angle by the supplied distance -- dist. dispParallel :: Floating u => u -> ThetaPointDisplace u -- | dispParallel : dist -> ThetaPointDisplace -- -- Build a combinator to move Points perpendicular to the -- inclnation of the implicit angle by the supplied distance -- dist. dispPerpendicular :: Floating u => u -> ThetaPointDisplace u -- | dispOrtho : vec -> ThetaPointDisplace -- -- This is a combination of displaceParallel and -- displacePerpendicular, with the x component of the vector -- displaced in parallel and the y component displaced perpendicular. dispOrtho :: Floating u => Vec2 u -> ThetaPointDisplace u -- | Angular version of dispDirection. -- -- The displacement direction is with respect to implicit angle of -- inclination, so: -- --
-- up == perpendicular -- down == perdendicular . negate -- left == parallel . negate -- right == parallel --dispDirectionTheta :: Floating u => Direction -> u -> ThetaPointDisplace u -- | Angular version of dispCardinal. -- -- The displacement direction is with respect to implicit angle of -- inclination, so: -- --
-- north == perpendicular -- east == parallel -- south == perdendicular . negate -- etc. --dispCardinalTheta :: Floating u => Cardinal -> u -> ThetaPointDisplace u go_up :: Num u => u -> Vec2 u go_down :: Num u => u -> Vec2 u go_left :: Num u => u -> Vec2 u go_right :: Num u => u -> Vec2 u go_north :: Num u => u -> Vec2 u go_south :: Num u => u -> Vec2 u go_east :: Num u => u -> Vec2 u go_west :: Num u => u -> Vec2 u go_north_east :: Floating u => u -> Vec2 u go_north_west :: Floating u => u -> Vec2 u go_south_east :: Floating u => u -> Vec2 u go_south_west :: Floating u => u -> Vec2 u go_up_left :: Num u => u -> Vec2 u go_up_right :: Num u => u -> Vec2 u go_down_left :: Num u => u -> Vec2 u go_down_right :: Num u => u -> Vec2 u -- | LocImage and LocGraphic types - these are functional types from the -- DrawingContext and start point to a graphic primitive. module Wumpus.Basic.Kernel.Objects.LocImage -- | LocThetaImage - function from start point and DrawingContext -- to a polymorphic answer and a graphic primitive (PrimW). data LocImage u a type LocGraphic u = LocImage u (UNil u) -- | Type specialized version of LocImage. type DLocImage a = LocImage Double a -- | Type specialized version of LocGraphic. type DLocGraphic = LocGraphic Double data LocQuery u a runLocImage :: Point2 u -> DrawingContext -> LocImage u a -> PrimW u a runLocQuery :: Point2 u -> DrawingContext -> LocQuery u a -> a promoteLoc :: (Point2 u -> Image u a) -> LocImage u a applyLoc :: LocImage u a -> Point2 u -> Image u a qpromoteLoc :: (Point2 u -> Query u a) -> LocQuery u a qapplyLoc :: LocQuery u a -> Point2 u -> Query u a -- | "zero-apply" a LocQuery. zapLocQuery :: LocQuery u a -> Point2 u -> Image u a -- | Having empty at the specific LocImage type is useful. emptyLocImage :: Monoid a => LocImage u a moveStart :: Num u => Vec2 u -> LocImage u a -> LocImage u a -- | Downcast a LocImage function by applying it to the supplied -- point, making an Image. at :: LocImage u a -> Point2 u -> Image u a distrib :: (Monoid a, InterpretUnit u) => Vec2 u -> [LocImage u a] -> LocImage u a distribH :: (Monoid a, InterpretUnit u) => u -> [LocImage u a] -> LocImage u a distribV :: (Monoid a, InterpretUnit u) => u -> [LocImage u a] -> LocImage u a -- | This is analogue to replicate in the Prelude. duplicate :: (Monoid a, InterpretUnit u) => Int -> Vec2 u -> LocImage u a -> LocImage u a duplicateH :: (Monoid a, InterpretUnit u) => Int -> u -> LocImage u a -> LocImage u a duplicateV :: (Monoid a, InterpretUnit u) => Int -> u -> LocImage u a -> LocImage u a instance UConvert LocImage instance (u ~ DUnit a, Num u, Translate a, ScalarUnit u) => Translate (LocImage u a) instance (Fractional u, Scale a) => Scale (LocImage u a) instance (u ~ DUnit a, Real u, Floating u, RotateAbout a, ScalarUnit u) => RotateAbout (LocImage u a) instance (Real u, Floating u, Rotate a) => Rotate (LocImage u a) instance Decorate LocImage instance DrawingCtxM (LocQuery u) instance DrawingCtxM (LocImage u) instance Monoid a => Monoid (LocQuery u a) instance Monoid a => Monoid (LocImage u a) instance Monad (LocQuery u) instance Monad (LocImage u) instance Applicative (LocQuery u) instance Applicative (LocImage u) instance Functor (LocQuery u) instance Functor (LocImage u) -- | Extended Graphic object - an AdvanceGraphic is a Graphic twinned with -- and advance vector. module Wumpus.Basic.Kernel.Objects.AdvObject -- | Advance vectors provide an idiom for drawing consecutive graphics. -- PostScript uses them to draw left-to-right text - each character has -- an advance vector for the width and as characters are drawn they -- successively displace the start point for the next character with -- their advance vector. -- -- Type alias for Vec2. type AdvanceVec u = Vec2 u -- | Extract the horizontal component of an advance vector. -- -- For left-to-right latin text, the vertical component of an advance -- vector is expected to be 0. Ingoring it seems permissible when drawing -- text. advanceH :: AdvanceVec u -> u -- | Extract the verticall component of an advance vector. advanceV :: AdvanceVec u -> u -- | Advance vector graphic - this partially models the PostScript -- show command which moves the current point by the -- advance (width) vector as each character is drawn. data AdvObject u type DAdvObject = AdvObject Double -- | Run an AdvObject turning it into an LocImage. runAdvObject :: AdvObject u -> LocImage u (Vec2 u) -- | makeAdvObject : loc_context_function * graphic -> -- AdvObject -- -- Build an AdvObject from a context function (CF) that -- generates the answer displacement vector and a LocGraphic that -- draws the AdvObject. makeAdvObject :: Query u (Vec2 u) -> LocGraphic u -> AdvObject u -- | emptyAdvObjectAU : AdvObject -- -- Build an empty AdvObject. -- -- The emptyAdvObject is treated as a null primitive by -- Wumpus-Core and is not drawn, the answer vector generated is -- the zero vector (V2 0 0). emptyAdvObject :: InterpretUnit u => AdvObject u blankAdvObject :: Vec2 u -> AdvObject u -- | Draw the first AdvObject and use the advance vector to displace the -- second AdvObject. -- -- The final answer is the sum of both advance vectors. advance :: Num u => AdvObject u -> AdvObject u -> AdvObject u -- | Concatenate the list of AdvObjects with advance. advances :: InterpretUnit u => [AdvObject u] -> AdvObject u -- | Combine the AdvObjects using the answer vector of the first object -- plus the separator to move the start of the second object. advspace :: Num u => Vec2 u -> AdvObject u -> AdvObject u -> AdvObject u -- | List version of nextSpace. evenspace :: InterpretUnit u => Vec2 u -> [AdvObject u] -> AdvObject u -- | Repeat the AdvObject n times, moving each time with -- advance. advrepeat :: InterpretUnit u => Int -> AdvObject u -> AdvObject u -- | Concatenate the list of AdvObjects, going next and adding the -- separator at each step. punctuate :: InterpretUnit u => AdvObject u -> [AdvObject u] -> AdvObject u -- | Render the supplied AdvObject, but swap the result advance for the -- supplied vector. This function has behaviour analogue to fill -- in the wl-pprint library. advfill :: Num u => Vec2 u -> AdvObject u -> AdvObject u instance InterpretUnit u => Monoid (AdvObject u) -- | Chaining moveable LocGraphics. module Wumpus.Basic.Kernel.Objects.Chain -- | Chain algorithm. -- -- Linear simply iterates points. -- -- Prefix runs the left chain n times then runs the -- right chain from the end point of the left chain. data ChainAlg u data IterationScheme u -- | Returns the end point... chain :: InterpretUnit u => ChainAlg u -> [LocImage u a] -> LocImage u (Point2 u) -- | Returns no answer, just a LocGraphic. chain_ :: InterpretUnit u => ChainAlg u -> [LocImage u a] -> LocGraphic u linearChain :: IterationScheme u -> ChainAlg u prefixChain :: Int -> ChainAlg u -> ChainAlg u -> ChainAlg u iterationScheme :: (Point2 u -> st) -> (st -> (st, Point2 u)) -> IterationScheme u chainIterate :: (Point2 u -> Point2 u) -> ChainAlg u chainH :: Num u => u -> ChainAlg u chainV :: Num u => u -> ChainAlg u tableRight :: Num u => Int -> (u, u) -> ChainAlg u tableDown :: Num u => Int -> (u, u) -> ChainAlg u radialChain :: Floating u => u -> Radian -> Radian -> ChainAlg u -- | LocThetaImage and LocThetaGraphic types - these are functional types -- from the DrawingContext, start point and angle of inclination to a -- graphic primitive. module Wumpus.Basic.Kernel.Objects.LocThetaImage type LocThetaGraphic u = LocThetaImage u (UNil u) -- | LocThetaImage - function from start point, inclination and -- DrawingContext to a polymorphic answer and a graphic -- primitive (PrimW). data LocThetaImage u a -- | Type specialized version of LocThetaGraphic. type DLocThetaGraphic = LocThetaGraphic Double -- | Type specialized version of LocThetaImage. type DLocThetaImage a = LocThetaImage Double a data LocThetaQuery u a runLocThetaImage :: Point2 u -> Radian -> DrawingContext -> LocThetaImage u a -> PrimW u a runLocThetaQuery :: Point2 u -> Radian -> DrawingContext -> LocThetaQuery u a -> a promoteLocTheta :: (Point2 u -> Radian -> Image u a) -> LocThetaImage u a applyLocTheta :: LocThetaImage u a -> Point2 u -> Radian -> Image u a qpromoteLocTheta :: (Point2 u -> Radian -> Query u a) -> LocThetaQuery u a qapplyLocTheta :: LocThetaQuery u a -> Point2 u -> Radian -> Query u a -- | "zero-apply" a LocThetaQuery. zapLocThetaQuery :: LocThetaQuery u a -> Point2 u -> Radian -> Image u a -- | Having empty at the specific LocThetaImage type is -- useful. emptyLocThetaImage :: Monoid a => LocThetaImage u a -- | Downcast a LocThetaImage function by applying it to the -- supplied angle, making a LocImage. incline :: LocThetaImage u a -> Radian -> LocImage u a atIncline :: LocThetaImage u a -> Point2 u -> Radian -> Image u a instance UConvert LocThetaImage instance Decorate LocThetaImage instance DrawingCtxM (LocThetaQuery u) instance DrawingCtxM (LocThetaImage u) instance Monoid a => Monoid (LocThetaQuery u a) instance Monoid a => Monoid (LocThetaImage u a) instance Monad (LocThetaQuery u) instance Monad (LocThetaImage u) instance Applicative (LocThetaQuery u) instance Applicative (LocThetaImage u) instance Functor (LocThetaQuery u) instance Functor (LocThetaImage u) -- | Graphic type - this is largely equivalent to Primitive in Wumpus-Core, -- but drawing attributes are implicitly supplied by the DrawingContext. module Wumpus.Basic.Kernel.Objects.DrawingPrimitives -- | locPP : [next_vector] -> LocImage PrimPath -- -- Create a path query - i.e. a functional type from Point to -- PrimPath. -- -- This is the analogue to vectorPath in Wumpus-Core, -- but the result is produced within the DrawingContext. locPP :: InterpretUnit u => [Vec2 u] -> LocQuery u PrimPath -- | emptyLocPP : (Point ~> PrimPath) -- -- Create an empty path query - i.e. a functional type from -- Point to PrimPath. -- -- This is the analogue to emptyPath in Wumpus-Core, -- but the result is produced within the DrawingContext. emptyLocPP :: InterpretUnit u => LocQuery u PrimPath -- | vertexPP : (Point ~> PrimPath) -- -- Create a PrimPath made of straight line segments joining the supplied -- points. -- -- This is the analogue to vertexPrimPath in Wumpus-Core, -- but it is polymorphic on unit. vertexPP :: InterpretUnit u => [Point2 u] -> Query u PrimPath -- | curvePP : (Point ~> PrimPath) -- -- Create a path made of curve segments joining the supplied points. -- -- This is the analogue to curvedPrimPath in Wumpus-Core, -- but it is polymorphic on unit. curvePP :: InterpretUnit u => [Point2 u] -> Query u PrimPath -- | dcOpenPath : path -> Graphic -- -- This is the analogue to the ostroke function in -- Wumpus-Core, but the drawing properties (colour, line width, -- etc.) are taken from the implicit DrawingContext. dcOpenPath :: PrimPath -> Graphic u -- | dcClosedPath : DrawStyle * path -> Graphic -- -- Draw a closed path according to the supplied DrawStyle ( fill | stroke -- | fill_stroke). dcClosedPath :: DrawStyle -> PrimPath -> Graphic u -- | dcTextlabel : string -> LocGraphic -- -- Create a text LocGraphic - i.e. a functional type from Point -- to Graphic. -- -- The implicit point of the LocGraphic is the baseline left. -- -- This is the analogue to textlabel in Wumpus-core, but -- the text properties (font family, font size, colour) are taken from -- the implicit DrawingContext. dcTextlabel :: InterpretUnit u => String -> LocGraphic u -- | dcRTextlabel : string -> LocThetaGraphic -- -- Create a text LocThetaGraphic - i.e. a functional type from -- Point and Angle to Graphic. -- -- The implicit point of the LocGraphic is the baseline left, the -- implicit angle is rotation factor of the text. -- -- Note - rotated text often does not render well in PostScript or SVG. -- Rotated text should be used sparingly. -- -- This is the analogue to rtextlabel in Wumpus-core. dcRTextlabel :: InterpretUnit u => String -> LocThetaGraphic u -- | dcEscapedlabel : escaped_text -> LocGraphic -- -- Create a text LocGraphic - i.e. a functional type from Point -- to Graphic. -- -- The implicit point of the LocGraphic is the baseline left. -- -- This is the analogue to escapedlabel in Wumpus-core, -- but the text properties (font family, font size, colour) are taken -- from the implicit DrawingContext. dcEscapedlabel :: InterpretUnit u => EscapedText -> LocGraphic u -- | dcREscapedlabel : escaped_text -> LocThetaGraphic -- -- Create a text LocThetaGraphic - i.e. a functional type from -- Point and Angle to Graphic. -- -- The implicit point of the LocGraphic is the baseline left, the -- implicit angle is rotation factor of the text. -- -- Note - rotated text often does not render well in PostScript or SVG. -- Rotated text should be used sparingly. -- -- This is the analogue to rescapedlabel in Wumpus-core, -- but the text properties (font family, font size, colour) are taken -- from the implicit DrawingContext. dcREscapedlabel :: InterpretUnit u => EscapedText -> LocThetaGraphic u -- | Unit parametric version of KerningChar from Wumpus-Core. type KernChar u = (u, EscapedChar) -- | hkernLine : [kern_char] -> LocGraphic -- -- Create a horizontally kerned text LocGraphic - i.e. a -- functional type from Point to Graphic. -- -- The implicit point of the LocGraphic is the baseline left. -- -- This is the analogue to hkernlabel in Wumpus-core, but -- the text properties (font family, font size, colour) are taken from -- the implicit DrawingContext. hkernLine :: InterpretUnit u => [KernChar u] -> LocGraphic u -- | vkernLine : [kern_char] -> LocGraphic -- -- Create a vertically kerned text LocGraphic - i.e. a functional -- type from Point to Graphic. -- -- The implicit point of the LocGraphic is the baseline left. -- -- This is the analogue to vkernlabel in Wumpus-core, but -- the text properties (font family, font size, colour) are taken from -- the implicit DrawingContext. vkernLine :: InterpretUnit u => [KernChar u] -> LocGraphic u -- | straightLine : start_point * end_point -> LocGraphic -- -- -- Create a straight line Graphic, the start and end point are -- supplied explicitly. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. straightLine :: InterpretUnit u => Point2 u -> Point2 u -> Graphic u -- | locStraightLine : vec_to -> LocGraphic -- -- Create a stright line LocGraphic - i.e. a functional type -- from Point to Graphic. -- -- The implicit point of the LocGraphic is the start point, the end point -- is calculated by displacing the start point with the supplied vector. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. locStraightLine :: InterpretUnit u => Vec2 u -> LocGraphic u -- | curveLine : start_point * control_point1 * -- control_point2 * end_point -> Graphic -- -- Create a Bezier curve Graphic, all control points are supplied -- explicitly. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. curvedLine :: InterpretUnit u => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u -- | straightConnector : start_point * end_point -> -- Connector -- -- Create a straight line Graphic, the start and end point are -- supplied implicitly. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. straightConnector :: InterpretUnit u => ConnectorGraphic u -- | dcCircle : DrawStyle * radius -> LocGraphic -- -- Create a circle LocGraphic - the implicit point is center. The -- circle is drawn with four Bezier curves. -- -- The respective line or fill properties for the DrawStyle are -- taken from the implicit DrawingContext. dcCircle :: InterpretUnit u => DrawStyle -> u -> LocGraphic u -- | strokedEllipse : x_radius * y_radius -> LocGraphic -- -- -- Create a stroked ellipse LocGraphic - the implicit point is -- center. The ellipse is drawn with four Bezier curves. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. dcEllipse :: InterpretUnit u => DrawStyle -> u -> u -> LocGraphic u -- | dcREllipse : x_radius * y_radius -> LocGraphic -- -- Create a bordered ellipse LocThetaGraphic - the implicit point -- is center and the angle is rotation about the center. The ellipse is -- drawn with four Bezier curves. -- -- The background fill colour and the outline stroke properties are taken -- from the implicit DrawingContext. dcREllipse :: InterpretUnit u => DrawStyle -> u -> u -> LocThetaGraphic u -- | strokedRectangle : width * height -> LocGraphic -- -- Create a stroked rectangle LocGraphic - the implicit point is -- bottom-left. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. dcRectangle :: InterpretUnit u => DrawStyle -> u -> u -> LocGraphic u -- | dcDisk : radius -> LocGraphic -- -- Create a circle LocGraphic - the implicit point is the center. -- -- This is a efficient representation of circles using PostScript's -- arc or SVG's circle in the generated output. -- However, stroked-circles do not draw well after non-uniform scaling - -- the pen width is scaled as well as the shape. -- -- For stroked circles that can be adequately scaled, use dcCircle -- instead. -- -- The fill or stroke properties for the respective DrawStyle are taken -- from the implicit DrawingContext. dcDisk :: InterpretUnit u => DrawStyle -> u -> LocGraphic u -- | strokeEllipseDisk : x_radius * y_radius -> LocGraphic -- -- -- Create a stroked ellipse LocGraphic - the implicit point is the -- center. -- -- This is a efficient representation of circles using PostScript's -- arc or SVG's ellipse in the generated output. -- However, stroked ellipses do not draw well after non-uniform scaling - -- the pen width is scaled as well as the shape. -- -- For stroked ellipses that can be adequately scaled, use -- strokedEllipse instead. -- -- The line properties (colour, pen thickness, etc.) are taken from the -- implicit DrawingContext. dcEllipseDisk :: InterpretUnit u => DrawStyle -> u -> u -> LocGraphic u -- | Helpers for working with Images and LocImages that produce bounding -- boxes. module Wumpus.Basic.Kernel.Objects.Bounded type BoundedGraphic u = Image u (BoundingBox u) type BoundedLocGraphic u = LocImage u (BoundingBox u) type BoundedLocThetaGraphic u = LocThetaImage u (BoundingBox u) -- | centerOrthoBBox : theta * bbox -> BBox -- -- Rotate a bounding box by theta about its center. Take the new -- bounding box. -- -- Remember that bounding boxes are always orthonormal rectangles, so the -- dimensions as well as the positions may change under rotation. centerOrthoBBox :: (Real u, Floating u, Ord u) => Radian -> BoundingBox u -> BoundingBox u -- | Build an empty LocGraphic returning a bounding box. -- -- The emptyBoundedLocGraphic is treated as a null -- primitive by Wumpus-Core and is not drawn, although it -- does generate the minimum bounding box with both the bottom-left and -- upper-right corners at the implicit start point. emptyBoundedLocGraphic :: InterpretUnit u => LocImage u (BoundingBox u) -- | Build an empty LocThetaGraphic returning a bounding box. -- -- The emptyBoundedLocThetaGraphic is treated as a null -- primitive by Wumpus-Core and is not drawn, although it -- does generate the minimum bounding box with both the bottom-left and -- upper-right corners at the implicit start point emptyBoundedLocThetaGraphic :: InterpretUnit u => LocThetaImage u (BoundingBox u) -- | Draw a BoundedGraphic, illustrating the bounding box. illustrateBoundedGraphic :: InterpretUnit u => Image u (BoundingBox u) -> Image u (BoundingBox u) -- | Draw a BoundedLocGraphic, illustrating the bounding box. illustrateBoundedLocGraphic :: InterpretUnit u => LocImage u (BoundingBox u) -> LocImage u (BoundingBox u) -- | Draw a BoundedLocThetaGraphic, illustrating the bounding box. illustrateBoundedLocThetaGraphic :: InterpretUnit u => LocThetaImage u (BoundingBox u) -> LocThetaImage u (BoundingBox u) bbrectangle :: InterpretUnit u => BoundingBox u -> Graphic u -- | Graphic objects RectAddress and Orientation to model rectangular -- positioning. module Wumpus.Basic.Kernel.Objects.Orientation -- | Datatype enumerating the addressable positions of a rectangle that can -- be derived for a PosObject. data RectAddress CENTER :: RectAddress NN :: RectAddress SS :: RectAddress EE :: RectAddress WW :: RectAddress NE :: RectAddress NW :: RectAddress SE :: RectAddress SW :: RectAddress BLL :: RectAddress BLC :: RectAddress BLR :: RectAddress -- | Utility datatype representing orientation within a rectangular -- frame. RectPos is useful for graphics such as text where the -- start point is not necessarily at the center (or bottom left). -- --
-- x_minor is the horizontal distance from the left to the start point -- -- x_major is the horizontal distance from the start point to the right -- -- y_minor is the vertical distance from the bottom to the start point -- -- y_major is the vertical distance from the start point to the top ---- -- Values should be not be negative! data Orientation u Orientation :: !u -> !u -> !u -> !u -> Orientation u or_x_minor :: Orientation u -> !u or_x_major :: Orientation u -> !u or_y_minor :: Orientation u -> !u or_y_major :: Orientation u -> !u -- | The vector from a RectAddress to the start point. orientationStart :: Fractional u => RectAddress -> Orientation u -> Vec2 u -- | Calculate the bounding box formed by locating the Orientation -- at the supplied point. orientationBounds :: Num u => Orientation u -> Point2 u -> BoundingBox u extendOrientation :: Num u => u -> u -> u -> u -> Orientation u -> Orientation u extendOLeft :: Num u => u -> Orientation u -> Orientation u extendORight :: Num u => u -> Orientation u -> Orientation u extendODown :: Num u => u -> Orientation u -> Orientation u extendOUp :: Num u => u -> Orientation u -> Orientation u padHEven :: (Fractional u, Ord u) => u -> Orientation u -> Orientation u padXMinor :: (Num u, Ord u) => u -> Orientation u -> Orientation u padXMajor :: (Num u, Ord u) => u -> Orientation u -> Orientation u padVEven :: (Fractional u, Ord u) => u -> Orientation u -> Orientation u padYMajor :: (Num u, Ord u) => u -> Orientation u -> Orientation u padYMinor :: (Num u, Ord u) => u -> Orientation u -> Orientation u -- | Second Orientation is moved to the right of the first along the -- spine i.e the baseline. spineRight :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | Second Orientation is moved below the first along the spine -- i.e. the vertical point between the left minor and right major (not -- the same as the horizontal center). spineBelow :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | xmin and xmaj same as left. halignBottomO :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | xmin same as left. halignCenterO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | xmin and ymaj same as left. halignTopO :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | Align second below - xmin and ymaj are same as left. valignLeftO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | Align second below - ymaj same as left. valignCenterO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | Align second below - xmaj and ymaj are same as left. valignRightO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u -- | Move second right. spinemoveH :: Num u => Orientation u -> Orientation u -> Vec2 u -- | Move second below. spinemoveV :: Num u => Orientation u -> Orientation u -> Vec2 u binmoveHBottom :: Num u => Orientation u -> Orientation u -> Vec2 u binmoveHCenter :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Vec2 u binmoveHTop :: Num u => Orientation u -> Orientation u -> Vec2 u binmoveVLeft :: Num u => Orientation u -> Orientation u -> Vec2 u binmoveVCenter :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Vec2 u binmoveVRight :: Num u => Orientation u -> Orientation u -> Vec2 u instance Enum RectAddress instance Eq RectAddress instance Ord RectAddress instance Show RectAddress instance Eq u => Eq (Orientation u) instance Ord u => Ord (Orientation u) instance Show u => Show (Orientation u) instance (Fractional u, Ord u) => Monoid (Orientation u) instance (Fractional u, Ord u) => OPlus (Orientation u) instance Functor Orientation -- | Extended Graphic object - a rectangular positionable Image. -- -- This graphic object has a more flexible API for positioning than other -- graphic objects. Rather than a LocGraphic which supports a single -- method of positioning at some start-point, a PosGraphic can -- be drawn at its center or locations on its outer rectangle. module Wumpus.Basic.Kernel.Objects.PosObject -- | A positionable "Object" that is drawn as a BoundedLocGraphic. data PosObject u -- | Version of PosObject specialized to Double for the unit type. type DPosObject = PosObject Double -- | Version of runPosObject that produces a LocImage that -- returns a bounding box. -- -- The PosObject is run with only rect-address as an explicit -- argument (start-point is implicit). The corresponding answer is an -- arity one Graphic that needs drawing with the start-point. runPosObject :: Fractional u => RectAddress -> PosObject u -> LocImage u (BoundingBox u) -- | makePosObject : object_pos * loc_image -> PosObject -- -- -- Create a PosObject from an Orientation describing how it -- is orientated within a border rectangle and a LocImage that -- draws it. -- -- This is the primary constructor for PosObjects. Because the -- PosObject type is considered as a specialized object it does not have -- the range of functions of LocImage or LocThetaImage. makePosObject :: Query u (Orientation u) -> LocGraphic u -> PosObject u -- | emptyPosObject : PosObject -- -- Build an empty PosGraphicObject. emptyPosObject :: InterpretUnit u => PosObject u -- | Apply a DrawingContext update to a PosObject. localPosObject :: DrawingContextF -> PosObject u -> PosObject u decoPosObject :: (Orientation u -> LocGraphic u) -> ZDeco -> PosObject u -> PosObject u -- | Extend the orientation. extendPosObject :: Num u => u -> u -> u -> u -> PosObject u -> PosObject u mapOrientation :: (Orientation u -> Orientation u) -> PosObject u -> PosObject u -- | Illustrate a PosObject by super-imposing its -- Orientation. -- -- This turns the PosObject into a LocImage drawn at the -- locus of the PosObject. illustratePosObject :: InterpretUnit u => PosObject u -> LocGraphic u instance (Fractional u, Ord u) => AlignSpace (PosObject u) instance (Fractional u, Ord u) => Align (PosObject u) instance (Num u, Ord u) => CatSpace (PosObject u) instance (Num u, Ord u) => Concat (PosObject u) instance (Fractional u, Ord u, InterpretUnit u) => ZConcat (PosObject u) instance (Fractional u, Ord u, InterpretUnit u) => Monoid (PosObject u) -- | Drawing with trace - a Writer like monad collecting -- intermediate graphics - and drawing context - a reader monad of -- attributes - font_face, fill_colour etc. module Wumpus.Basic.Kernel.Objects.TraceDrawing -- | Collect elementary graphics as part of a larger drawing. -- -- TraceM works much like a writer monad. class TraceM m :: (* -> *) trace :: (TraceM m, (MonUnit (m ())) ~ u) => HPrim u -> m () fontDelta :: TraceM m => m a -> m a data TraceDrawing u a type DTraceDrawing a = TraceDrawing Double a data TraceDrawingT u m a type DTraceDrawingT m a = TraceDrawingT Double m a runTraceDrawing :: DrawingContext -> TraceDrawing u a -> (a, HPrim u) -- | Run the drawing returning only the output it produces, drop any answer -- from the monadic computation. execTraceDrawing :: DrawingContext -> TraceDrawing u a -> HPrim u -- | Run the drawing ignoring the output it produces, return the answer -- from the monadic computation. -- -- Note - this useful for testing, generally one would want the opposite -- behaviour (return the drawing, ignore than the answer). evalTraceDrawing :: DrawingContext -> TraceDrawing u a -> a runTraceDrawingT :: Monad m => DrawingContext -> TraceDrawingT u m a -> m (a, HPrim u) execTraceDrawingT :: Monad m => DrawingContext -> TraceDrawingT u m a -> m (HPrim u) evalTraceDrawingT :: Monad m => DrawingContext -> TraceDrawingT u m a -> m a -- | Unsafe promotion of HPrim to Picture. -- -- If the HPrim is empty, a run-time error is thrown. liftToPictureU :: HPrim u -> Picture -- | Safe promotion of HPrim to (Maybe Picture). -- -- If the HPrim is empty, then Nothing is returned. liftToPictureMb :: HPrim u -> Maybe Picture -- | Unsafe promotion of (Maybe Picture) to -- Picture. -- -- This is equivalent to: -- --
-- fromMaybe (error "empty") $ pic ---- -- This function is solely a convenience, using it saves one import and a -- few characters. -- -- If the supplied value is Nothing a run-time error is thrown. mbPictureU :: Maybe Picture -> Picture evalQuery :: DrawingCtxM m => Query u a -> m a -- | Draw a Graphic taking the drawing style from the drawing -- context. -- -- This function is the forgetful version of drawi. -- Commonly, it is used to draw Graphic objects which have no -- answer. draw :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Image u a -> m () -- | Draw an Image taking the drawing style from the drawing -- context. -- -- The graphic representation of the Image is drawn in the Trace monad, -- and the result is returned. drawi :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Image u a -> m a -- | Draw a LocImage at the supplied Anchor taking the drawing style from -- the drawing context. -- -- This function is the forgetful version of drawli. -- Commonly, it is used to draw LocGraphic objects which have no -- answer. drawl :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> LocImage u a -> m () -- | Draw a LocImage at the supplied Point taking the drawing style from -- the drawing context. -- -- The graphic representation of the Image is drawn in the Trace monad, -- and the result is returned. drawli :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> LocImage u a -> m a -- | Draw a ConnectorGraphic with the supplied Anchors taking the drawing -- style from the drawing context. -- -- This function is the forgetful version of drawci. -- Commonly, it is used to draw ConnectorGraphic objects which -- have no answer. drawc :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> Anchor u -> ConnectorImage u a -> m () -- | Draw a ConnectorImage with the supplied Points taking the drawing -- style from the drawing context. -- -- The graphic representation of the Image is drawn in the Trace monad, -- and the result is returned. drawci :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> Anchor u -> ConnectorImage u a -> m a -- | Draw the object with the supplied grid coordinate. The actual position -- is scaled according to the snap_grid_factors in the -- drawing context. -- -- This function is the forgetful version of nodei. -- Commonly, it is used to draw LocGraphic objects which have no -- answer. node :: (Fractional u, TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => (Int, Int) -> LocImage u a -> m () -- | Draw the object with the supplied grid coordinate. The actual position -- is scaled according to the snap_grid_factors in the -- drawing context. nodei :: (Fractional u, TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => (Int, Int) -> LocImage u a -> m a -- | Draw a connector between two objects. The projection of the connector -- line is drawn on the line from center to center of the objects, the -- actual start and end points of the drawn line are the radial points on -- the objects borders that cross the projected line. -- -- This function is the forgetful version of drawrci. -- Commonly, it is used to draw LocGraphic objects which have no -- answer. drawrc :: (Real u, Floating u, DrawingCtxM m, TraceM m, CenterAnchor a, RadialAnchor a, CenterAnchor b, RadialAnchor b, u ~ (MonUnit (m ())), u ~ (DUnit a), u ~ (DUnit b)) => a -> b -> ConnectorImage u ans -> m () -- | Draw a connector between two objects. The projection of the connector -- line is drawn on the line from center to center of the objects, the -- actual start and end points of the drawn line are the radial points on -- the objects borders that cross the projected line. drawrci :: (Real u, Floating u, DrawingCtxM m, TraceM m, CenterAnchor a, RadialAnchor a, CenterAnchor b, RadialAnchor b, u ~ (MonUnit (m ())), u ~ (DUnit a), u ~ (DUnit b)) => a -> b -> ConnectorImage u ans -> m ans instance Monad m => DrawingCtxM (TraceDrawingT u m) instance DrawingCtxM (TraceDrawing u) instance Monad m => TraceM (TraceDrawingT u m) instance TraceM (TraceDrawing u) instance Monad m => Monad (TraceDrawingT u m) instance Monad (TraceDrawing u) instance Monad m => Applicative (TraceDrawingT u m) instance Applicative (TraceDrawing u) instance Monad m => Functor (TraceDrawingT u m) instance Functor (TraceDrawing u) -- | A Picture-with-implicit-context object. -- -- This is the corresponding type to Picture in the Wumpus-Core. -- -- Note - many of the composition functions are in destructor -- form. As Wumpus cannot make a Picture from an empty list of -- Pictures, destructor form decomposes the list into the -- head and rest as arguments in the function -- signature, rather than take a possibly empty list and have to throw an -- error. -- -- TODO - PosImage no longer supports composition operators, so better -- names are up for grabs... module Wumpus.Basic.Kernel.Objects.CtxPicture -- | A Contextual Picture. -- --
-- CtxPicture = DrawingContext -> Maybe Picture ---- -- This type corresponds to the Picture type in Wumpus-Core, but -- it is embedded with a DrawingContext (for font properties, fill -- colour etc.). The DrawingContext is embedded so that font metrics - -- loaded in IO can be passed into the pure world of -- TraceDrawing. -- -- Internally a context picture is a function from -- DrawingContext to (Maybe Picture). The Maybe -- represents that it is possible to construct empty Pictures, even -- though Wumpus-Core cannot render them. Just as the -- DrawingContext pushes font-metrics from the IO to the pure world, the -- Maybe lifts the problem of unrenderable Pictures into the API where -- client code must deal with it explicitly. -- -- (In practice, it is very unlikely a program will create empty pictures -- and runCtxPictureU can be used without worry). -- -- Note - pictures are fixed to the unit Double (representing -- PostScript points). Pictures are intentionally unsophisticated, any -- fine grained control of units should be delegated to the elements that -- build the picture (Graphics, LocGraphics, etc.). data CtxPicture -- | runCtxPicture : drawing_ctx * ctx_picture -> Maybe -- Picture -- -- Run a CtxPicture with the supplied DrawingContext -- producing a Picture. -- -- The resulting Picture may be empty. Wumpus-Core cannot generate empty -- pictures as they have no bounding box, so the result is wrapped within -- a Maybe. This delegates reponsibility for handling empty pictures to -- client code. runCtxPicture :: DrawingContext -> CtxPicture -> Maybe Picture -- | runCtxPictureU : drawing_ctx * ctx_picture -> Picture -- -- -- Unsafe version of runCtxPicture. -- -- This function throws a runtime error when supplied with an empty -- CtxPicture. runCtxPictureU :: DrawingContext -> CtxPicture -> Picture -- | drawTracing : trace_drawing -> CtxPicture -- -- Transform a TraceDrawing into a CtxPicture. drawTracing :: TraceDrawing u a -> CtxPicture -- | udrawTracing : scalar_unit_value * trace_drawing -> -- CtxPicture -- -- Variant of drawTracing with a phantom first argument - the -- phantom identifies the unit type of the TraceDrawing. It is not -- scurtinized at the value level. udrawTracing :: u -> TraceDrawing u a -> CtxPicture -- | mapCtxPicture : trafo * ctx_picture -> CtxPicture -- -- Apply a picture transformation function to the Picture warpped -- in a CtxPicture. mapCtxPicture :: (Picture -> Picture) -> CtxPicture -> CtxPicture -- | Draw a, move b so its center is at the same center -- as a, b is drawn over underneath in the zorder. -- --
-- a `cxpUniteCenter` b --uniteCenter :: CtxPicture -> CtxPicture -> CtxPicture -- | Center the picture at the supplied point. centeredAt :: CtxPicture -> DPoint2 -> CtxPicture instance AlignSpace CtxPicture instance Align CtxPicture instance CatSpace CtxPicture instance Concat CtxPicture instance ZConcat CtxPicture instance OPlus CtxPicture instance Monoid CtxPicture instance Translate CtxPicture instance Scale CtxPicture instance RotateAbout CtxPicture instance Rotate CtxPicture -- | Import shim for Wumpus.Basic.Kernel modules. module Wumpus.Basic.Kernel -- | Font load monad handling IO (file system access), failure and logging. module Wumpus.Basic.System.FontLoader.FontLoadMonad data FontLoadIO a runFontLoadIO :: FontLoadIO a -> IO (Either FontLoadMsg a, FontLoadLog) evalFontLoadIO :: FontLoadIO a -> IO (Either FontLoadMsg a) loadError :: FontLoadMsg -> FontLoadIO a tellLoadMsg :: String -> FontLoadIO () -- | Promote an IO action into the the FontLoadIO monad. -- -- This function is equivalent to liftIO. promoteIO :: IO a -> FontLoadIO a promoteEither :: Either FontLoadMsg a -> FontLoadIO a runParserFLIO :: FilePath -> Parser Char a -> FontLoadIO a -- | The standard monadic sequence would finish on first fail for -- the FontLoadIO monad. As we want to be able to sequence the loading of -- a list of fonts, this is not really the behaviour we want for Wumpus. -- Instead we prefer to use fallback metrics and produce an inaccurate -- drawing on a font load error rather than fail and produce no drawing. sequenceAll :: [FontLoadIO a] -> FontLoadIO [a] -- | Afm files do not have a default advance vec so use the monospace -- default. -- -- Afm files hopefully have CapHeight and FontBBox -- properties in the header. Use the monospace default only if they are -- missing. buildAfmFontProps :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO (FontProps AfmUnit) checkFontPath :: FilePath -> FilePath -> FontLoadIO FilePath instance Monad FontLoadIO instance Functor FontLoadIO -- | Top-level AFM V4.1 font loader. -- -- Use this module to build a font loader if you want to work with the -- Adobe metrics sets, but find the simpleFontLoader in -- Wumpus.Basic.System.FontLoader too inflexible. module Wumpus.Basic.System.FontLoader.AfmTopLevel -- | loadAfmFontMetrics : path_to_afm_fonts * [font_name] -> -- IO FontLoadResult -- -- Load the supplied list of fonts. -- -- Note - if a font fails to load a message is written to the log and -- monospaced fallback metrics are used. loadAfmFontMetrics :: FilePath -> [FontDef] -> IO FontLoadResult -- | loadAfmFont1 : path_to_afm_fonts * font_def -> IO -- FontLoadResult -- -- Load a single AFM font. -- -- Note - if the font fails to load a message is written to the log and -- monospaced fallback metrics are used. loadAfmFont1 :: FilePath -> FontDef -> IO FontLoadResult -- | Top-level GhostScript font loader. -- -- Use this module to build a font loader if you want to work with -- GhostScript, but find the simpleFontLoader in -- Wumpus.Basic.System.FontLoader too inflexible. module Wumpus.Basic.System.FontLoader.GSTopLevel -- | loadGSFontMetrics : path_to_gs_fonts * [font_name] -> -- IO FontLoadResult -- -- Load the supplied list of fonts. -- -- Note - if a font fails to load a message is written to the log and -- monospaced fallback metrics are used. loadGSFontMetrics :: FilePath -> [FontDef] -> IO FontLoadResult -- | loadGSFont1 : path_to_gs_fonts * font_name -> IO -- FontLoadResult -- -- Load a single GhostScript font. -- -- Note - if the font fails to load a message is written to the log and -- monospaced fallback metrics are used. loadGSFont1 :: FilePath -> FontDef -> IO FontLoadResult -- | Top level module for font loading... module Wumpus.Basic.System.FontLoader -- | A FontLoader is an action from a list of fonts to a -- FontLoadResult returned in IO. -- -- Fonts are supplied in a list of Either FontDef FontFamily, -- this is a little cumbersome but it allows the loader to load -- individual fonts and / or a whole families with a single API call. type FontLoader = [Either FontDef FontFamily] -> IO FontLoadResult afmLoaderByEnv :: IO (Maybe FontLoader) gsLoaderByEnv :: IO (Maybe FontLoader) -- | Tries to find the GhostScript metrics first... -- -- Runs the IO action on the loader if it finds one. -- -- Either of one of the environment variables -- WUMPUS_AFM_FONT_DIR or WUMPUS_GS_FONT_DIR must be -- defined and point to their respective directory. simpleFontLoader :: (FontLoader -> IO a) -> IO (Maybe a) default_font_loader_help :: String -- | Vertices generators for elementary objects - triangles. module Wumpus.Basic.Geometry.Vertices type Vertices2 u = (Vec2 u, Vec2 u) type Vertices3 u = (Vec2 u, Vec2 u, Vec2 u) type Vertices4 u = (Vec2 u, Vec2 u, Vec2 u, Vec2 u) runVertices2 :: Num u => Point2 u -> Vertices2 u -> [Point2 u] runVertices3 :: Num u => Point2 u -> Vertices3 u -> [Point2 u] runVertices4 :: Num u => Point2 u -> Vertices4 u -> [Point2 u] -- | Vertices are from the center to (bl, br, tr, tl). rectangleVertices :: Num u => u -> u -> Vertices4 u -- |
-- base_width * height -> (BL,BR,Apex) ---- -- Vertices are from the centeriod to (bl, br,apex). -- --
-- height -> (BL,BR,Apex) ---- -- Point is centroid (not incenter). isoscelesTriangleVertices :: Floating u => u -> u -> Vertices3 u -- |
-- side_length -> (BL,BR,Apex) --equilateralTriangleVertices :: Floating u => u -> Vertices3 u parallelogramVertices :: Floating u => u -> u -> Radian -> Vertices4 u isoscelesTrapeziumVertices :: Floating u => u -> u -> u -> Vertices4 u -- | Base geometric types and operations. module Wumpus.Basic.Geometry.Base quarter_pi :: Floating u => u half_pi :: Floating u => u two_pi :: Floating u => u -- | 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 -> Matrix2'2 u type DMatrix2'2 = Matrix2'2 Double -- | Construct the identity 2x2 matrix: -- --
-- (M2'2 1 0 -- 0 1 ) --identity2'2 :: Num u => Matrix2'2 u -- | Determinant of a 2x2 matrix. det2'2 :: Num u => Matrix2'2 u -> u -- | Transpose a 2x2 matrix. transpose2'2 :: Matrix2'2 u -> Matrix2'2 u -- | Infinite line represented by two points. data Line u Line :: (Point2 u) -> (Point2 u) -> Line 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 -- | Line in equational form, i.e. Ax + By + C = 0. data LineEquation u LineEquation :: !u -> !u -> !u -> LineEquation u line_eqn_A :: LineEquation u -> !u line_eqn_B :: LineEquation u -> !u line_eqn_C :: LineEquation u -> !u type DLineEquation = LineEquation Double -- | lineEquation : point1 * point2 -> LineEquation -- -- Construct a line in equational form bisecting the supplied points. lineEquation :: Num u => Point2 u -> Point2 u -> LineEquation u -- | pointViaX : x * line_equation -> Point -- -- Calculate the point on the line for the supplied x value. pointViaX :: Fractional u => u -> LineEquation u -> Point2 u -- | pointViaY : y * line_equation -> Point -- -- Calculate the point on the line for the supplied y value. pointViaY :: Fractional u => u -> LineEquation u -> Point2 u -- | 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 data LineSegment u LineSegment :: (Point2 u) -> (Point2 u) -> LineSegment u type DLineSegment = LineSegment Double -- | rectangleLineSegments : half_width * half_height -> -- [LineSegment] -- -- Compute the line segments of a rectangle. rectangleLineSegments :: Num u => u -> u -> Point2 u -> [LineSegment u] -- | polygonLineSegments : [point] -> [LineSegment] -- -- Build the line segments of a polygon fome a list of its vertices. polygonLineSegments :: [Point2 u] -> [LineSegment u] -- | A Strict cubic Bezier curve. data BezierCurve u BezierCurve :: !Point2 u -> !Point2 u -> !Point2 u -> !Point2 u -> BezierCurve u type DBezierCurve = BezierCurve Double -- | 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 -- | Curve subdivision via de Casteljau's algorithm. subdivide :: Fractional u => BezierCurve u -> (BezierCurve u, BezierCurve u) -- | subdivide with an affine weight along the line... subdividet :: Real u => u -> BezierCurve u -> (BezierCurve u, BezierCurve u) -- | bezierArcPoints : apex_angle * radius * inclination * -- center -> [Point] -- --
-- ang should be in the range 0 < ang < 360deg. ---- --
-- if 0 < ang <= 90 returns 4 points -- if 90 < ang <= 180 returns 7 points -- if 180 < ang <= 270 returns 10 points -- if 270 < ang < 360 returns 13 points --bezierArcPoints :: Floating u => Radian -> u -> Radian -> Point2 u -> [Point2 u] -- | bezierMinorArc : apex_angle * radius * rotation * center -- -> BezierCurve -- --
-- ang should be in the range 0 < ang <= 90deg. --bezierMinorArc :: Floating u => Radian -> u -> Radian -> Point2 u -> BezierCurve u -- | Affine combination... affineComb :: Real u => u -> Point2 u -> Point2 u -> Point2 u -- | 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 -- | lineAngle : start_point * end_point -> Angle -- -- Calculate the counter-clockwise angle between the line formed by the -- two points and the horizontal plane. lineAngle :: (Floating u, Real u) => Point2 u -> Point2 u -> Radian instance Eq u => Eq (Matrix2'2 u) instance (Ord u, Tolerance u) => Eq (Line u) instance Show u => Show (Line u) instance Eq u => Eq (LineEquation u) instance Show u => Show (LineEquation u) instance (Ord u, Tolerance u) => Eq (LineSegment u) instance (Ord u, Tolerance u) => Ord (LineSegment u) instance Show u => Show (LineSegment u) instance (Ord u, Tolerance u) => Eq (BezierCurve u) instance (Ord u, Tolerance u) => Ord (BezierCurve u) instance Show u => Show (BezierCurve u) instance Num u => Num (Matrix2'2 u) instance Show u => Show (Matrix2'2 u) instance Functor Matrix2'2 -- | Draw the geometrical objects. module Wumpus.Basic.Geometry.Illustrate illustrateLine :: (Real u, Floating u, InterpretUnit u) => Line u -> Graphic u illustrateLineSegment :: InterpretUnit u => LineSegment u -> Graphic u -- | Intersection of line to line and line to plane. -- -- ** - WARNING ** - this uses quite a high tolerance for floating point -- equality. module Wumpus.Basic.Geometry.Intersection -- | 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. interLineLine :: Fractional u => Line u -> Line u -> Maybe (Point2 u) -- | interLinesegLineseg : line_segment1 * line_segment2 -> -- Maybe Point -- -- Find the intersection of two line segments, if there is one. -- -- An answer of Nothing indicates that the line segments -- coincide, or that there is no intersection. interLinesegLineseg :: (Fractional u, Ord u, Tolerance u) => LineSegment u -> LineSegment u -> Maybe (Point2 u) -- | interLinesegLine : line_segment * line -> Maybe Point -- -- -- Find the intersection of a line and a line segment, if there is one. -- -- An answer of Nothing indicates that the the line and line -- segment coincide, or that there is no intersection. interLinesegLine :: (Fractional u, Ord u, Tolerance u) => LineSegment u -> Line u -> Maybe (Point2 u) interCurveLine :: (Floating u, Ord u, Tolerance u) => BezierCurve u -> Line u -> Maybe (Point2 u) -- | findIntersect :: radial_origin * theta * [line_segment] -- -> Maybe Point -- -- Find the first intersection of a line through radial_origin -- at angle theta and the supplied line segments, if there is -- one. findIntersect :: (Floating u, Real u, Ord u, Tolerance u) => Point2 u -> Radian -> [LineSegment u] -> Maybe (Point2 u) -- | Path algorithms for elementary shapes - rectangle, diamond, -- polygon. module Wumpus.Basic.Geometry.Paths -- | A vector chain building a path. -- -- The vectors are relative to the predecessor, so the rendering of a -- PathAlg iterates the start point. -- -- A polygon PathAlg should have steps for all sides of the polygon with -- the end point generated by the last vector coinciding with thet start -- point. data PathAlg u runPathAlgPoint :: Num u => Point2 u -> PathAlg u -> [Point2 u] runPathAlgVec :: PathAlg u -> (Maybe (Vec2 u), [Vec2 u]) drawVertexPathAlg :: InterpretUnit u => DrawStyle -> PathAlg u -> LocGraphic u -- | Create a PathAlg from the vertex list. -- -- When the PathAlg is run the supplied point will be the start of the -- path. pathStartIsStart :: [Vec2 u] -> PathAlg u -- | Create a PathAlg from the vector list - the first vector displaces the -- start point the subsequent vectors displace the current -- tip. Figuratively, this is rather like Logo turtle drawing. -- -- When the PathAlg is run, the supplied point is the locus of the -- path and it does not form part of the path proper. -- -- This constructor is typically used to make shape paths where -- the supplied point is the center and the generated path is the border. pathStartIsLocus :: [Vec2 u] -> PathAlg u -- | Note this creates a path where the first vector represents a -- moveto, then the subsequence vectors represent -- linetos. -- -- Create a PathAlg from the vector list - each vector in the input list -- iterates to the start point rather then the cumulative tip. -- -- When the PathAlg is run, the supplied point is the locus of the -- path and it does not form part of the path proper. -- -- Like pathStartIsLocus, this constructor is typically used to -- make shape paths. Some shapes are easier to express as iterated -- displacements of the center rather than turtle drawing. pathIterateLocus :: Num u => [Vec2 u] -> PathAlg u -- | Implicit start point is center, the genearated moves are -- counter-clockwise so the move-list is -- --
-- [ moveto_bl, moveto_br, moveto_tr, moveto_tl ] --rectanglePathAlg :: Fractional u => u -> u -> PathAlg u -- | Implicit start point is bottom-left, subsequent moves are -- counter-clockwise so the move-list is: -- --
-- [ moveto_br, moveto_tr, moveto_tl, moveto_bl ] --blRectanglePathAlg :: Num u => u -> u -> PathAlg u -- | diamondPathAlg : half_width * half_height -> PathAlg -- diamondPathAlg :: Num u => u -> u -> PathAlg u -- | isoscelesTriPathAlg : base_width * height -> PathAlg -- -- -- Start point is centtroid not incenter. isoscelesTriPathAlg :: Floating u => u -> u -> PathAlg u -- | polygonPathAlg : num_points * radius -> PathAlg polygonPathAlg :: Floating u => Int -> u -> PathAlg u -- | arcPathAlg : radius * angle1 * angle2 -> PathAlg arcPathAlg :: Floating u => u -> Radian -> Radian -> PathAlg u circlePathAlg :: (Fractional u, Floating u) => u -> PathAlg u -- |
-- width * height * bottom_left_angle --parallelogramPathAlg :: Floating u => u -> u -> Radian -> PathAlg u -- |
-- base_width * top_width * height --isoscelesTrapeziumPathAlg :: Floating u => u -> u -> u -> PathAlg u instance Enum PathAlgScheme instance Eq PathAlgScheme instance Ord PathAlgScheme instance Show PathAlgScheme -- | Quadrants and trigonometric calculations. -- -- ** - WARNING ** - in progress. module Wumpus.Basic.Geometry.Quadrant data Quadrant QUAD_NE :: Quadrant QUAD_NW :: Quadrant QUAD_SW :: Quadrant QUAD_SE :: Quadrant -- | quadrant : ang -> Quadrant -- -- Get the quadrant of an angle. quadrant :: Radian -> Quadrant type RadialIntersect u = Radian -> Vec2 u -- | A Quadrant algorithm. data QuadrantAlg u QuadrantAlg :: RadialIntersect u -> RadialIntersect u -> RadialIntersect u -> RadialIntersect u -> QuadrantAlg u calc_quad1 :: QuadrantAlg u -> RadialIntersect u calc_quad2 :: QuadrantAlg u -> RadialIntersect u calc_quad3 :: QuadrantAlg u -> RadialIntersect u calc_quad4 :: QuadrantAlg u -> RadialIntersect u runQuadrantAlg :: Radian -> QuadrantAlg u -> Vec2 u -- | triangleQI : dx * dy -> RadialIntersect -- -- Find where a line from (0,0) with elevation ang intersects -- the hypotenuse a right triangle in QI (the legs of the triangle take -- the x and y-axes). -- --
-- ang must be in the @range 0 < ang <= 90@. -- -- width and height must be positive. --hypotenuseQI :: (Real u, Floating u) => u -> u -> RadialIntersect u -- | rectangleQI : width * height * ang -> Vec -- -- Find where a line from (0,0) in direction ang intersects the -- top or right side of a rectangle in QI (left side is the y-axis, -- bottom is the x-axis). -- --
-- ang must be in the @range 0 < ang <= 90 deg@. -- -- width and height must be positive. --rectangleQI :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u -- | hquadrilAcuteQI : dx * dy * ang -> RadialIntersect -- -- -- Find where a line from (0,0) with elevation ang intersects a -- quadrilateral in H acute form in QI. -- --
-- ang must be in the @range 0 < ang <= 90@. -- -- dx (top width @bc@) and dy (height @ab) must be positive. ---- -- Horizontal acute quadrilateral (H because one of the two -- "sides of interest" is horizontal, acute because the angle of -- interest bcd is acute: -- --
-- -- b---*----c -- | / -- | % -- | / -- a----d --hquadrilAcuteQI :: (Real u, Floating u) => u -> u -> Radian -> RadialIntersect u -- | hquadrilObtusQI : dx * dy * ang -> RadialIntersect -- -- -- Find where a line from (0,0) with elevation ang intersects a -- quadrilateral in H obtus form in QI. -- --
-- ang must be in the @range 0 < ang <= 90@. -- -- dx (top width @bc@) and dy (height @ab) must be positive. ---- -- H Obtus quadrilateral (H because one of the two "sides of -- interest" is horizontal, obtus because the angle interest -- bcd is obtuse: -- --
-- -- b---*----c -- | \ -- | % -- | \ -- a------------d --hquadrilObtusQI :: (Real u, Floating u) => u -> u -> Radian -> RadialIntersect u -- | rectangleQuadrantAlg : width * height -> QuadrantAlg -- -- -- Find where a radial line extended from (0,0) with the elevation -- ang intersects with an enclosing rectangle. The rectangle is -- centered at (0,0). -- -- Internally the calculation is made in quadrant I (north east), -- symmetry is used to translate result to the other quadrants. rectangleQuadrantAlg :: (Real u, Floating u) => u -> u -> QuadrantAlg u -- | diamondQuadrantAlg : width * height -> QuadrantAlg -- -- -- Find where a radial line extended from (0,0) with the elevation -- ang intersects with an enclosing diamond. The diamond is -- centered at (0,0). -- -- Internally the calculation is made in quadrant I (north east), -- symmetry is used to translate result to the other quadrants. diamondQuadrantAlg :: (Real u, Floating u) => u -> u -> QuadrantAlg u -- | isoscelesTriQuadrantAlg : base_width * height -> -- QuadrantAlg -- -- Find where a radial line extended from (0,0) with the elevation -- ang intersects with an enclosing isosceles triangle. -- -- Note the center of the triangle (0,0) is the centroid not the -- incenter. -- -- Internally the calculation is made in quadrant I (north east), -- symmetry is used to translate result to the other quadrants. isoscelesTriQuadrantAlg :: (Real u, Floating u) => u -> u -> QuadrantAlg u -- | rectRadialVector : half_width * half_height * ang -> -- Vec -- -- Find where a radial line extended from (0,0) with the elevation -- ang intersects with an enclosing rectangle. The rectangle is -- centered at (0,0). -- -- Internally the calculation is made in quadrant I (north east), -- symmetry is used to translate result to the other quadrants. rectRadialVector :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u -- | diamondRadialVector : half_width * half_height * ang -> -- Vec -- -- Find where a radial line extended from (0,0) with the elevation -- ang intersects with an enclosing diamond. The diamond is -- centered at (0,0). -- -- Internally the calculation is made in quadrant I (north east), -- symmetry is used to translate result to the other quadrants. diamondRadialVector :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u -- | triangleRadialVector : half_base_width * height_minor * -- height_minor * ang -> Vec -- -- Find where a radial line extended from (0,0) with the elevation -- ang intersects with an enclosing triangle. The triangle has -- the centroid at (0,0), so solutions in quadrants I and II are -- intersections with a simple line. Intersections in quadrants III and -- IV can intersect either the respective side or the base. triangleRadialVector :: (Real u, Floating u) => u -> u -> u -> Radian -> Vec2 u -- | triangleQI : width * height * ang -> Vec -- -- Find where a line from (0,0) with elevation ang intersects -- the hypotenuse a right triangle in QI (the legs of the triangle take -- the x and y-axes). -- --
-- ang must be in the @range 0 < ang <= 90@. -- -- width and height must be positive. --triangleQI :: (Real u, Floating u) => u -> u -> Radian -> Vec2 u -- | rightTrapezoidQI : top_width * height * top_right_ang -- -> Vec -- -- Find where a line from (0,0) with elevation ang intersects -- the either the lines A_B or B_D in a right trapezoid in QI. -- -- The right trapezoid has a variable right side. Left side is the y-axis -- (C_A), bottom side is the x-axis (C_D), top side is parallel to the -- x-axis (A_B). -- --
-- A B -- ----- -- | \ -- | \ -- ------- -- C D ---- --
-- A B -- ------- -- | / -- | / -- ----- -- C D ---- --
-- ang must be in the range 0 < ang <= 90. -- -- top_width and height must be positive. --rightTrapezoidQI :: (Real u, Floating u) => u -> u -> Radian -> Radian -> Vec2 u -- | rightTrapeziumBaseWidth : top_width * height * -- top_right_ang -> Length -- -- Find the length of the line C_D: -- --
-- A B -- ----- -- | \ -- | \ -- ------- -- C D ---- --
-- A B -- ------- -- | / -- | / -- ----- -- C D --rightTrapeziumBaseWidth :: Fractional u => u -> u -> Radian -> u instance Enum Quadrant instance Eq Quadrant instance Ord Quadrant instance Show Quadrant -- | Import shim for Wumpus.Basic.Geometry modules. module Wumpus.Basic.Geometry