diagrams-lib 0.7.1.1 → 1.0
raw patch · 142 files changed
+4679/−975 lines, 142 filesdep +MemoTriedep +filepathdep +lensdep −newtypedep ~diagrams-coredep ~intervalssetup-changed
Dependencies added: MemoTrie, filepath, lens, optparse-applicative, safe, tagged, vector-space-points
Dependencies removed: newtype
Dependency ranges changed: diagrams-core, intervals
Files
- CHANGES.markdown +103/−0
- LICENSE +5/−0
- Setup.hs +2/−29
- diagrams-lib.cabal +24/−6
- diagrams/besideEx.svg +0/−4
- diagrams/closeLineEx.svg +0/−4
- diagrams/cubicOffsetExample.svg +0/−4
- diagrams/cubicSplineEx.svg +0/−4
- diagrams/decagonEx.svg +0/−4
- diagrams/diagramA.svg +0/−4
- diagrams/diagramNeg.svg +0/−4
- diagrams/diagramPos.svg +0/−4
- diagrams/diagramZero.svg +0/−4
- diagrams/dodecagonEx.svg +0/−4
- diagrams/glueLineEx.svg +0/−4
- diagrams/hendecagonEx.svg +0/−4
- diagrams/hexagonEx.svg +0/−4
- diagrams/hruleEx.svg +0/−4
- diagrams/lineFromOffsetsEx.svg +0/−4
- diagrams/lineFromVerticesEx.svg +0/−4
- diagrams/nonagonEx.svg +0/−4
- diagrams/octagonEx.svg +0/−4
- diagrams/pentagonEx.svg +0/−4
- diagrams/rectEx.svg +0/−4
- diagrams/roundedRectEx.svg +0/−4
- diagrams/septagonEx.svg +0/−4
- diagrams/squareEx.svg +0/−4
- diagrams/src_Diagrams_Combinators_appendsEx.svg +4/−0
- diagrams/src_Diagrams_Combinators_besideEx.svg +4/−0
- diagrams/src_Diagrams_Combinators_positionEx.svg +4/−0
- diagrams/src_Diagrams_Combinators_strutEx.svg +4/−0
- diagrams/src_Diagrams_Combinators_withEnvelopeEx.svg +4/−0
- diagrams/src_Diagrams_CubicSpline_cubicSplineEx.svg +4/−0
- diagrams/src_Diagrams_TrailLike_explodeTrailEx.svg +4/−0
- diagrams/src_Diagrams_TrailLike_fromOffsetsEx.svg +4/−0
- diagrams/src_Diagrams_TrailLike_fromSegmentsEx.svg +4/−0
- diagrams/src_Diagrams_TrailLike_fromVerticesEx.svg +4/−0
- diagrams/src_Diagrams_TrailLike_twiddleEx.svg +4/−0
- diagrams/src_Diagrams_Trail_closeLineEx.svg +4/−0
- diagrams/src_Diagrams_Trail_glueLineEx.svg +4/−0
- diagrams/src_Diagrams_Trail_lineFromOffsetsEx.svg +4/−0
- diagrams/src_Diagrams_Trail_lineFromVerticesEx.svg +4/−0
- diagrams/src_Diagrams_Trail_trailOffsetEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arc_annularWedgeEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arc_arc'Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arc_arcBetweenEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arc_wedgeEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrow_example1.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrow_example2.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_blockEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_dart'Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_dartEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_missile'Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_missileEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_quillEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_spike'Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_spikeEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_thorn'Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_thornEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_tri'Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_tri25Ex.svg +4/−0
- diagrams/src_Diagrams_TwoD_Arrowheads_triEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Curvature_diagramA.svg +4/−0
- diagrams/src_Diagrams_TwoD_Curvature_diagramNeg.svg +4/−0
- diagrams/src_Diagrams_TwoD_Curvature_diagramPos.svg +4/−0
- diagrams/src_Diagrams_TwoD_Curvature_diagramZero.svg +4/−0
- diagrams/src_Diagrams_TwoD_Offset_cubicOffsetExample.svg +4/−0
- diagrams/src_Diagrams_TwoD_Offset_expandLoopExample.svg +4/−0
- diagrams/src_Diagrams_TwoD_Offset_expandTrailExample.svg +4/−0
- diagrams/src_Diagrams_TwoD_Offset_offsetTrailExample.svg +4/−0
- diagrams/src_Diagrams_TwoD_Offset_offsetTrailLeftExample.svg +4/−0
- diagrams/src_Diagrams_TwoD_Offset_offsetTrailOuterExample.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_decagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_dodecagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_hendecagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_heptagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_hexagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_hruleEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_nonagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_octagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_pentagonEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_rectEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_roundedRectEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_squareEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_triangleEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_unitSquareEx.svg +4/−0
- diagrams/src_Diagrams_TwoD_Shapes_vruleEx.svg +4/−0
- diagrams/trailOffsetEx.svg +0/−4
- diagrams/triangleEx.svg +0/−4
- diagrams/unitSquareEx.svg +0/−4
- diagrams/vruleEx.svg +0/−4
- src/Diagrams/Align.hs +87/−22
- src/Diagrams/Animation.hs +4/−2
- src/Diagrams/Animation/Active.hs +2/−4
- src/Diagrams/Attributes.hs +67/−22
- src/Diagrams/Backend/CmdLine.hs +534/−0
- src/Diagrams/Backend/Show.hs +0/−1
- src/Diagrams/BoundingBox.hs +30/−30
- src/Diagrams/Combinators.hs +74/−29
- src/Diagrams/Coordinates.hs +44/−17
- src/Diagrams/CubicSpline.hs +6/−9
- src/Diagrams/Located.hs +20/−8
- src/Diagrams/Names.hs +1/−0
- src/Diagrams/Parametric.hs +4/−68
- src/Diagrams/Parametric/Adjust.hs +101/−0
- src/Diagrams/Path.hs +26/−20
- src/Diagrams/Points.hs +5/−13
- src/Diagrams/Prelude.hs +19/−8
- src/Diagrams/Segment.hs +44/−23
- src/Diagrams/Tangent.hs +190/−0
- src/Diagrams/ThreeD.hs +48/−0
- src/Diagrams/ThreeD/Camera.hs +131/−0
- src/Diagrams/ThreeD/Light.hs +55/−0
- src/Diagrams/ThreeD/Transform.hs +159/−0
- src/Diagrams/ThreeD/Types.hs +116/−24
- src/Diagrams/ThreeD/Vector.hs +84/−0
- src/Diagrams/Trace.hs +9/−5
- src/Diagrams/Trail.hs +194/−30
- src/Diagrams/TrailLike.hs +48/−4
- src/Diagrams/TwoD.hs +55/−12
- src/Diagrams/TwoD/Adjust.hs +0/−2
- src/Diagrams/TwoD/Align.hs +81/−27
- src/Diagrams/TwoD/Arc.hs +83/−12
- src/Diagrams/TwoD/Arrow.hs +513/−0
- src/Diagrams/TwoD/Arrowheads.hs +338/−0
- src/Diagrams/TwoD/Combinators.hs +7/−4
- src/Diagrams/TwoD/Curvature.hs +14/−21
- src/Diagrams/TwoD/Ellipse.hs +0/−1
- src/Diagrams/TwoD/Image.hs +12/−8
- src/Diagrams/TwoD/Model.hs +20/−19
- src/Diagrams/TwoD/Offset.hs +452/−42
- src/Diagrams/TwoD/Path.hs +101/−71
- src/Diagrams/TwoD/Polygons.hs +21/−18
- src/Diagrams/TwoD/Segment.hs +5/−2
- src/Diagrams/TwoD/Shapes.hs +58/−48
- src/Diagrams/TwoD/Size.hs +5/−3
- src/Diagrams/TwoD/Text.hs +16/−14
- src/Diagrams/TwoD/Transform.hs +54/−125
- src/Diagrams/TwoD/Transform/ScaleInv.hs +189/−0
- src/Diagrams/TwoD/Types.hs +162/−50
- src/Diagrams/TwoD/Vector.hs +17/−9
- src/Diagrams/Util.hs +0/−5
CHANGES.markdown view
@@ -1,3 +1,106 @@+1.0 (25 November 2013)+----------------------++* **New features**++ - New modules `Diagrams.TwoD.Arrow` and `Diagrams.TwoD.Arrowheads`+ for creating arrows.+ - New module `Diagrams.Backend.CmdLine`, providing a flexible+ framework for creating command-line-driven diagram rendering executables.+ - New functions in `Diagrams.Offset`: `offsetTrail` and+ `offsetPath` for one-sided offsets of trails and paths;+ `expandTrail` and `expandPath` for "stroking" trails and paths,+ computing a path whose fill corresponds to the stroke of the+ given trail or path.+ - New module `Diagrams.Tangent` for computing tangent and normal+ vectors of segments, trails, and paths.+ - New functions in `Diagrams.Align` to allow diagrams to be aligned by `Trace`+ called `snug`, `snugBy` and `snugCenter`+ and the ability to define other boundary functions for alignment. Functions+ `snugL`, `snugR`, etc. are included in `TwoD.Align`.+ - Lenses from `Control.Lens` are now used consistently for record fields+ throughout the library.+ - New function `angleRatio` for calculating the ratio between two angles.+ - Restricted identity functions `asTurn`, `asRad`, and `asDeg` for+ resolving type ambiguity+ - New miter limit attribute.+ - New function `annularWedge` in `TwoD.Arc`+ - New `avgScale` utility in `TwoD.Transform`, for backends which+ cannot fully implement freezing of line width+ - New function `heptagon`, a vast improvement over the linguistic+ frankenstein `septagon`.+ - New function `lookupName` (re-exported from `diagrams-core`) for+ simple lookups of named subdiagrams+ - New function `angleBetween` to calculate the angle between two+ vectors.+ - New function `arcBetween` to draw an arc between two given+ points.+ - A bunch of new modules containing types, primitives and+ utilities for constructing 3D diagrams: `Diagrams.ThreeD.Align`,+ `.Camera`, `.Light`, `.Shapes`, `.Transform`, `.Types`, and+ `.Vector`. This is still a "feature preview" (in particular,+ appropriate 3D backends are still under construction).++* **New instances**++ - `AdditiveGroup` and `VectorSpace` instances for `Turn`, `Rad`, `Deg`+ - `Alignable` instance for `(->) e`+ - `Default` instances for `FillRule`, `FillRuleA`, `LineJoin`,+ `LineCap`, `FillColor`+ - `Show` instances for `FillRule`, `FillRuleA`++* **API changes**++ - `e` no longer exported from `Diagrams.Prelude`.+ - `Diagrams.BoundingBox` is no longer exported from `Diagrams.Prelude`.+ - Re-export `Diagrams.Core.pointDiagram` from `Diagrams.Prelude`.+ - Added `fromAlphaColour` method to `Color` class.+ - `&` renamed to `^&`+ - Stop re-exporting `tan`, `over`, and `both` from `Data.Colour`.+ - New coordinate lenses `_x`, `_y`, and `_z` for `R2`, `P2`, `R3`, `P3`+ - Export `fullTurn` from `Diagrams.Prelude`.+ - `Codomain (Located a)` is now `Point (Codomain a)` instead of+ `Located (Codomain a)`.+ - Export `domainBounds` from `Diagrams.Parametric`.+ - Adjusting functionality moved from `Diagrams.Parametric` to its+ own module, `Diagrams.Parametric.Adjust`.+ - Rename `strokeT` (and primed variant) to `strokeTrail`; rename+ `strokeLocT` to `strokeLocTrail`.+ - `ScaleInv` is now in its own module, `Diagrams.TwoD.Transform.ScaleInv`.+ - Re-export `Image` type (but not constructor) from `Diagrams.TwoD`+ - Removed `Floating` and `RealFloat` instances for `Turn` and `Deg`+ - `offsetSegment` now returns a `Located` instead of a tuple.+ - Removed `Num` and `Fractional` instances for `R2`.++* **Dependency/version changes**++ - Remove `newtype` dependency+ - New dependencies on `lens`, `tagged`, `optparse-applicative`,+ `filepath`, `safe`, `vector-space-points`, `MemoTrie`+ - Depend on `intervals >= 0.3 && < 0.5`.++* **Bug fixes**++ - Depend on `intervals 0.3`, which allows diagrams to build on+ Windows, by evading a GHCi linker bug which affects the FFI use in+ previous versions of intervals ([diagrams-contrib#14](https://github.com/diagrams/diagrams-contrib/issues/14))++ - Use point envelope at the origin for text objects instead of an+ empty envelope+ ([#115](https://github.com/diagrams/diagrams-lib/issues/115),+ [#116](https://github.com/diagrams/diagrams-lib/issues/116)).+ - Adjusting the end of a trail now works correctly ([#95](https://github.com/diagrams/diagrams-lib/issues/95)).+ - Only look for miter join on corners in `Diagrams.TwoD.Offset` ([#118](https://github.com/diagrams/diagrams-lib/issues/118)).+ - `wedge` from `Diagrams.TwoD.Arc` is now a Loop ([#99](https://github.com/diagrams/diagrams-lib/issues/99))++* **Performance improvements**++ - `R2` is now strict and `UNPACK`ed+ - Add strictness to `Offset`, `Segment`, `OffsetEnvelope`, and `SizeSpec2D`.+ - Make `getEnvelope` calculation for `Segment` more efficient by+ floating divisions out of the inner calculation.+ - Use a specialized `HasTrie` instance for `R2`.+ 0.7.1.1 (27 September 2013) ---------------------------
LICENSE view
@@ -1,12 +1,17 @@ Copyright (c) 2011-2013 diagrams-lib team: + Jan Bracker <jan.bracker@googlemail.com> Daniel Bergey <bergey@alum.mit.edu> Daniil Frumin <difrumin@gmail.com> Niklas Haas <nand@lavabit.com> Peter Hall <peter.hall@memorphic.com> Claude Heiland-Allen <claudiusmaximus@goto10.org> Deepak Jois <deepak.jois@gmail.com>+ John Lato <jwlato@tsurucapital.com>+ Chris Mears <chris@cmears.id.au>+ Jeffrey Rosenbluth <jeffrey.rosenbluth@gmail.com> Ian Ross <ian@skybluetrades.net>+ Carlos Scheidegger <cscheid@research.att.com> Michael Sloan <mgsloan@gmail.com> Jim Snavely <ludflu@gmail.com> Kanchalai Suveepattananont <ksuvee@seas.upenn.edu>
Setup.hs view
@@ -1,29 +1,2 @@-import Data.List (isSuffixOf)-import Distribution.Simple-import Distribution.Simple.Setup (Flag (..), HaddockFlags,- haddockDistPref)-import Distribution.Simple.Utils (copyFiles)-import Distribution.Text (display)-import Distribution.Verbosity (normal)-import System.Directory (getDirectoryContents)-import System.FilePath ((</>))---- Ugly hack, logic copied from Distribution.Simple.Haddock-haddockOutputDir :: Package pkg => HaddockFlags -> pkg -> FilePath-haddockOutputDir flags pkg = destDir- where- baseDir = case haddockDistPref flags of- NoFlag -> "."- Flag x -> x- destDir = baseDir </> "doc" </> "html" </> display (packageName pkg)--diagramsDir = "diagrams"--main :: IO ()-main = defaultMainWithHooks simpleUserHooks- { postHaddock = \args flags pkg lbi -> do- dias <- filter ("svg" `isSuffixOf`) `fmap` getDirectoryContents diagramsDir- copyFiles normal (haddockOutputDir flags pkg)- (map (\d -> ("", diagramsDir </> d)) dias)- postHaddock simpleUserHooks args flags pkg lbi- }+import Distribution.Simple+main = defaultMain
diagrams-lib.cabal view
@@ -1,5 +1,5 @@ Name: diagrams-lib-Version: 0.7.1.1+Version: 1.0 Synopsis: Embedded domain-specific language for declarative graphics Description: Diagrams is a flexible, extensible EDSL for creating graphics of many types. Graphics can be created@@ -15,9 +15,10 @@ Maintainer: diagrams-discuss@googlegroups.com Bug-reports: http://github.com/diagrams/diagrams-lib/issues Category: Graphics-Build-type: Custom+Build-type: Simple Cabal-version: >=1.10 Extra-source-files: CHANGES.markdown, README.markdown, diagrams/*.svg+Extra-doc-files: diagrams/*.svg Tested-with: GHC == 7.4.2, GHC == 7.6.1 Source-repository head type: git@@ -32,6 +33,7 @@ Diagrams.Points, Diagrams.Located, Diagrams.Parametric,+ Diagrams.Parametric.Adjust, Diagrams.Segment, Diagrams.Trail, Diagrams.TrailLike,@@ -39,6 +41,7 @@ Diagrams.CubicSpline, Diagrams.CubicSpline.Internal, Diagrams.Solve,+ Diagrams.Tangent, Diagrams.Transform, Diagrams.BoundingBox, Diagrams.Names,@@ -48,8 +51,11 @@ Diagrams.TwoD, Diagrams.TwoD.Types, Diagrams.TwoD.Align,+ Diagrams.TwoD.Arrow,+ Diagrams.TwoD.Arrowheads, Diagrams.TwoD.Combinators, Diagrams.TwoD.Transform,+ Diagrams.TwoD.Transform.ScaleInv, Diagrams.TwoD.Ellipse, Diagrams.TwoD.Arc, Diagrams.TwoD.Segment,@@ -66,24 +72,36 @@ Diagrams.TwoD.Adjust, Diagrams.ThreeD.Types, Diagrams.ThreeD.Shapes,+ Diagrams.ThreeD.Vector,+ Diagrams.ThreeD.Transform,+ Diagrams.ThreeD.Camera,+ Diagrams.ThreeD.Light,+ Diagrams.ThreeD Diagrams.Animation, Diagrams.Animation.Active, Diagrams.Util,- Diagrams.Backend.Show+ Diagrams.Backend.Show,+ Diagrams.Backend.CmdLine Build-depends: base >= 4.2 && < 4.8, containers >= 0.3 && < 0.6, array >= 0.3 && < 0.5, semigroups >= 0.3.4 && < 0.12, monoid-extras >= 0.3 && < 0.4,- diagrams-core >= 0.7 && < 0.8,+ diagrams-core >= 1.0 && < 1.1, active >= 0.1 && < 0.2, vector-space >= 0.7.7 && < 0.9,+ vector-space-points >= 0.1.2 && < 0.2,+ MemoTrie >= 0.6 && < 0.7, NumInstances >= 1.2 && < 1.4, colour >= 2.3.2 && < 2.4, data-default-class < 0.1, pretty >= 1.0.1.2 && < 1.2,- newtype >= 0.2 && < 0.3, fingertree >= 0.1 && < 0.2,- intervals >= 0.2.2 && < 0.3+ intervals >= 0.3 && < 0.5,+ lens >= 3.9 && < 3.11,+ tagged >= 0.7,+ optparse-applicative >= 0.7 && < 0.8,+ filepath,+ safe >= 0.2 && < 0.4 Hs-source-dirs: src default-language: Haskell2010
− diagrams/besideEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="84.860339985334" height="100.0" font-size="1" viewBox="0 0 85 100"><g><g transform="matrix(21.832407982400788,0.0,0.0,21.832407982400788,21.832407982400788,78.16759201759922)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(128,0,128)" fill-opacity="1.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 2.8868978654915356,-2.0803467982373034 c 0.0,-0.8284271247461902 -0.6715728752538097,-1.5 -1.4999999999999996 -1.5c -0.8284271247461902,-5.072653133236334e-17 -1.5,0.6715728752538096 -1.5 1.4999999999999996c -1.0145306266472669e-16,0.8284271247461902 0.6715728752538095,1.5 1.4999999999999993 1.5c 0.8284271247461902,1.5217959399709003e-16 1.5,-0.6715728752538094 1.5000000000000002 -1.4999999999999996Z" /></g></g><g transform="matrix(21.832407982400788,0.0,0.0,21.832407982400788,21.832407982400788,78.16759201759922)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(255,165,0)" fill-opacity="1.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.0,0.0 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g></g><g transform="matrix(21.832407982400788,0.0,0.0,21.832407982400788,21.832407982400788,78.16759201759922)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 9.160693596474608e-2,0.0 c 0.0,-5.05931137120553e-2 -4.101382225269076e-2,-9.160693596474608e-2 -9.160693596474606e-2 -9.160693596474608e-2c -5.05931137120553e-2,-3.0979347383183296e-18 -9.160693596474608e-2,4.1013822252690756e-2 -9.160693596474608e-2 9.160693596474605e-2c -6.195869476636659e-18,5.05931137120553e-2 4.1013822252690756e-2,9.160693596474608e-2 9.160693596474603e-2 9.160693596474608e-2c 5.05931137120553e-2,9.293804214954989e-18 9.160693596474608e-2,-4.101382225269075e-2 9.160693596474609e-2 -9.160693596474605e-2Z" /></g></g></g></svg>
− diagrams/closeLineEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500.0" height="68.18181818181819" font-size="1" viewBox="0 0 500 68"><g><g transform="matrix(41.32231404958678,0.0,0.0,41.32231404958678,250.0,34.09090909090909)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 3.5,-0.75 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 h 2.0 Z" /></g></g><g transform="matrix(41.32231404958678,0.0,0.0,41.32231404958678,250.0,34.09090909090909)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -2.5,-0.75 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 " /></g></g></g></svg>
− diagrams/cubicOffsetExample.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600.0" height="302.8587568898731" font-size="1" viewBox="0 0 600 303"><g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 33.417476733497544,-1.6473872989404414 c 0.8062160672722946,1.905601613552696 2.6000741970593846,4.243483864433998 6.1181079451566704 6.588839696498854" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 32.86092310128323,-3.9349733247464833 c 2.5438939233202715e-2,0.6274938344190003 0.18344919012734384,1.4057027990550142 0.5565536322143172 2.287586025806042" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 33.000311673428904,-5.029283712603785 c -0.11129079091128233,0.22258158182256466 -0.16025559544153956,0.5795904798926219 -0.13938857214567413 1.0943103878573026" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 32.97862528132407,-5.0044688233462296 c 5.153156049894565e-3,-5.841483753310084e-3 1.692390853525727e-2,-1.5289922118400523e-2 2.1686392104834917e-2 -2.4814889257555817e-2" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 32.70873785722833,-4.826371179429536 c 8.358937623750423e-2,-3.1497446118479856e-2 0.1859951877994061,-8.299958544359087e-2 0.2698874240957419 -0.17809764391669347" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 32.055356993320274,-4.853120624705525 c 0.22391741974384227,0.10443579260779995 0.40910731509659143,0.11879455062523658 0.6533808639080557 2.6749445275989214e-2" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 31.72347357921467,-5.143549245977102 c 9.378804941573246e-2,0.15871823747277802 0.21780468092203953,0.23722193939149805 0.33188341410559885 0.290428621271577" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 31.691808767395802,-5.205805672754545 c 5.879553721364279e-3,2.4935979612594604e-2 2.2991427605793424e-2,4.7578391955314714e-2 3.166481181886982e-2 6.2256426777443974e-2" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 31.711972577462916,-5.042326266928818 c -3.953664939657162e-3,-6.508340746820251e-2 -9.443295519196648e-3,-0.11801225901967066 -2.0163810067113208e-2 -0.163479405825728" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 31.661929314384686,-4.205360512837057 c 4.7781656372351815e-2,-0.35039881339724666 6.298412834573885e-2,-0.6239392027650263 5.004326307822693e-2 -0.8369657540917615" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 28.08645729142907,5.326289096396298 c 2.4270875082384364,-4.854175016476873 3.347932569058263,-7.86302694731943 3.5754720229556165 -9.531649609233355" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 28.980884482428987,5.773502691896256 c 10.0,-20.0 -5.0,-10.0 10.0 0.0" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 22.22681744227194,-4.975977707743982 c 0.0,1.1652184940288222 4.623280507125882e-2,5.8820192426981635 4.707106781186548 10.542893218813452" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 22.22527234029002,-5.190961309967572 c 1.3596945248057525e-3,5.336801009862579e-2 1.5451019819200384e-3,0.12796315263602145 1.5451019819200384e-3 0.21498360222358961" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 22.219061458808028,-5.310773112363486 c 2.667352776137804e-3,3.119320885427821e-2 5.02539135926483e-3,7.328131507884304e-2 6.2108814819927805e-3 0.11981180239591362" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 22.17283082599389,-5.555708087831506 c 1.5097180450167632e-2,4.9065836463044805e-2 3.77384688109178e-2,0.14562383531926093 4.6230632814137085e-2 0.2449349754680199" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 21.98765210484117,-5.902700770832827 c 5.915986229623687e-2,7.248909052964826e-2 0.1384351262519885,0.19507599957394778 0.18517872115271883 0.34699268300132147" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 21.651201254320615,-6.170110768106993 c 0.11662169140991802,5.726092743049299e-2 0.23178207485071373,0.1391584419009324 0.33645085052055707 0.26740999727416637" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 21.098403476790917,-6.266956245808321 c 0.20191976907307557,-2.2211174598038314e-2 0.3705651859412463,7.369780030821671e-3 0.552797777529697 9.684547770132823e-2" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 20.68717773824717,-6.127488517764909 c 0.14370207595416082,-8.692183392465397e-2 0.28088371953770774,-0.12513010595274754 0.41122573854374933 -0.13946772804341212" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 20.48926554076378,-5.971144448967711 c 6.721861761310331e-2,-6.819078770254902e-2 0.13666548184831018,-0.11929744431724854 0.19791219748338984 -0.15634406879719753" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 20.34021917756031,-5.779740302591862 c 4.992158119902007e-2,-8.181592474283846e-2 0.10709836789040328,-0.14884946518015663 0.14904636320346876 -0.19140414637584913" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 20.208899018783505,-5.493502020830685 c 4.542742635734029e-2,-0.12492542248268579 0.10576723145080258,-0.2443598730880031 0.13132015877680647 -0.28623828176117616" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 19.662024018783505,-3.911470770830685 c 0.3068064887395122,-0.8437178440336586 0.4701733778151219,-1.3711017889915853 0.546875 -1.58203125" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 15.332390251272024,5.826808696756062 c 2.472343200154557,-4.944686400309114 3.7115479674728395,-8.03854351748049 4.329633767511479 -9.738279467586747" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 16.22681744227194,6.27402229225602 c 10.0,-20.0 0.0,-10.0 10.0 0.0" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 13.009770219789226,-2.4104743608548755 c -0.2855399505357898,9.691052866669228e-2 -0.6461909532308479,0.16047436085487377 -1.0892105128500125 0.16047436085487377" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 13.893839526646092,-2.982120392131483 c -0.2040335330264581,0.2331811806016664 -0.4832891526977512,0.4356236759256361 -0.8840693068568652 0.5716460312766082" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 14.185013884508258,-4.851123441588392 c 0.26509461237177,0.70691896632472 0.17274121378843077,1.3388138247133698 -0.2911743578621666 1.8690030494569096" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 11.295559706939214,-6.75 c 1.3528278761481514,0.0 2.551247208532007,0.996991307646174 2.8894541775690445 1.8988765584116083" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 9.203810396758112,-5.989978417355905 c 0.7131947941382994,-0.5593684659908231 1.4205071509921139,-0.7600215826440954 2.0917493101811018 -0.7600215826440954" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 7.49586988404493,-3.666654710493214 c 0.5144343791036886,-1.122402281680775 1.1116643005702707,-1.8556560894957015 1.7079405127131826 -2.3233237068626913" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 5.920559706939214,6.75 c 0.0,-5.2028660713222505 0.6810675710972038,-8.46557993374737 1.5753101771057156 -10.416654710493214" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 6.920559706939214,6.75 c 0.0,-20.0 10.0,-10.0 5.0 -10.0" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 2.660826934705069,-8.569475230141833 c 0.48895650949203384,-0.9250528557957396 1.122019777927579,-1.556458070895497 1.9677823889408268 -1.894763115300796" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 1.7534960535105757,-5.761630493146541 c 0.2156599309608425,-1.086926052042646 0.5083600089169349,-2.0530349786323434 0.9073308811944935 -2.807844736995292" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M 0.8835457044574557,1.0837838328712444 c 0.31486663625486255,-2.3929864355369554 0.4763670537345416,-4.86175451761215 0.8699503490531199 -6.845414326017784" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -0.7828015282143159,7.11175903331599 c 0.9591837382060431,-1.6232340185025345 1.3712137747622202,-3.7849609203321535 1.6663472326717716 -6.027975200444747" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -5.0,9.46423834544263 c 2.0016683287913244,0.0 3.404020713214209,-0.9763323360826055 4.217198471785684 -2.3524793121266407" /></g></g><g transform="matrix(13.155574898915933,0.0,0.0,13.155574898915933,72.35566194403765,151.42937844493656)"><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -5.0,10.46423834544263 c 10.0,0.0 5.0,-18.0 10.0 -20.0" /></g></g></g></svg>
− diagrams/cubicSplineEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600.0" height="150.9864382575877" font-size="1" viewBox="0 0 600 151"><g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 5.30560144347186,0.5148061556407302 c -0.2727272727272727,-0.2727272727272727 0.2727272727272728,-3.3636363636363638 2.0 -3.000000000000001c 1.727272727272727,0.36363636363636376 4.636363636363635,4.181818181818182 3.0 5.000000000000002c -1.6363636363636362,0.8181818181818175 -7.8181818181818175,-1.3636363636363633 -8.999999999999998 -2.999999999999999c -1.1818181818181817,-1.6363636363636362 2.6363636363636367,-2.727272727272727 4.000000000000002 -2.0c 1.3636363636363635,0.7272727272727275 0.27272727272727276,3.272727272727273 -3.552713678800501e-15 2.9999999999999982Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 5.5056014434718605,-2.48519384435927 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 1.5056014434718603,-0.4851938443592698 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 10.50560144347186,2.51480615564073 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 7.5056014434718605,-2.48519384435927 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 5.5056014434718605,0.5148061556407302 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M -6.333419254268965,0.5148061556407302 c 0.2142857142857144,-1.9107142857142858 0.4285714285714288,-3.8214285714285716 2.0 -3.0c 1.5714285714285712,0.8214285714285716 4.5,4.375 2.999999999999999 5.0c -1.5,0.625 -7.428571428571428,-1.6785714285714284 -8.999999999999998 -2.999999999999999c -1.5714285714285712,-1.3214285714285712 1.2142857142857149,-1.6607142857142856 4.0 -2.0" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M -6.133419254268965,-2.48519384435927 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M -10.133419254268965,-0.4851938443592698 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M -1.1334192542689652,2.51480615564073 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M -4.133419254268965,-2.48519384435927 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g transform="matrix(25.27996301518507,0.0,0.0,25.27996301518507,300.0,75.49321912879385)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M -6.133419254268965,0.5148061556407302 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g></g></svg>
− diagrams/decagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="95.10565162951534" font-size="1" viewBox="0 0 100 95"><g><g transform="matrix(28.092454034086124,0.0,0.0,28.092454034086124,49.99999999999999,47.55282581475767)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.3090169943749481,0.9510565162951532 l 0.3090169943749472,-0.9510565162951536 l -0.3090169943749477,-0.9510565162951534 l -0.8090169943749475,-0.5877852522924729 l -1.0,4.440892098500626e-16 l -0.8090169943749473,0.5877852522924731 l -0.3090169943749473,0.9510565162951536 l 0.3090169943749475,0.9510565162951535 l 0.8090169943749475,0.587785252292473 l 1.0,-5.551115123125783e-17 l 0.8090169943749477,-0.5877852522924736 Z" /></g></g></g></svg>
− diagrams/diagramA.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></svg>
− diagrams/diagramNeg.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 4.464000000000002,-3.8037685950413227 l 2.077770135746605,7.445342986425346 " /></g></g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 14.271599430272687,3.6415743913840233 c 0.0,-4.269066838162075 -3.4607624563640047,-7.7298292945260805 -7.729829294526079 -7.7298292945260805c -4.269066838162075,-2.614049519350648e-16 -7.7298292945260805,3.4607624563640043 -7.7298292945260805 7.729829294526078c -5.228099038701296e-16,4.269066838162075 3.460762456364004,7.7298292945260805 7.729829294526077 7.7298292945260805c 4.269066838162075,7.842148558051945e-16 7.7298292945260805,-3.4607624563640034 7.729829294526082 -7.729829294526078Z" /></g></g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></svg>
− diagrams/diagramPos.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M -4.463999999999999,3.1082314049586772 l -3.900145794392522,-8.6003214953271 " /></g></g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 1.079194030081819,-5.492090090368422 c 0.0,-5.215412572526979 -4.227927251947359,-9.44333982447434 -9.443339824474338 -9.44333982447434c -5.215412572526979,-3.193519156589014e-16 -9.44333982447434,4.227927251947358 -9.44333982447434 9.443339824474336c -6.387038313178028e-16,5.215412572526979 4.227927251947357,9.44333982447434 9.443339824474336 9.44333982447434c 5.215412572526979,9.580557469767042e-16 9.44333982447434,-4.227927251947357 9.443339824474343 -9.443339824474336Z" /></g></g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></svg>
− diagrams/diagramZero.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 0.0,-0.6177685950413228 l 61.17187500000001,54.37500000000001 " /></g></g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 143.0170881527289,53.75723140495869 c 0.0,-45.20186307090284 -36.64335008182604,-81.84521315272889 -81.84521315272887 -81.84521315272889c -45.20186307090284,-2.7678158462639055e-15 -81.84521315272889,36.643350081826036 -81.84521315272889 81.84521315272886c -5.535631692527811e-15,45.20186307090284 36.64335008182603,81.84521315272889 81.84521315272885 81.84521315272889c 45.20186307090284,8.303447538791717e-15 81.84521315272889,-36.64335008182603 81.84521315272893 -81.84521315272886Z" /></g></g><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="0.1" font-size="1.0em"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></svg>
− diagrams/dodecagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="99.99999999999999" font-size="1" viewBox="0 0 100 100"><g><g transform="matrix(24.35901749373842,0.0,0.0,24.35901749373842,50.0,49.99999999999999)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.8660254037844393,0.4999999999999996 l -2.220446049250313e-16,-1.0 l -0.5000000000000001,-0.8660254037844386 l -0.8660254037844387,-0.49999999999999994 l -1.0,1.6081226496766364e-16 l -0.8660254037844386,0.49999999999999994 l -0.5000000000000001,0.8660254037844386 l -3.4450928483976665e-16,1.0 l 0.49999999999999956,0.8660254037844389 l 0.8660254037844385,0.5000000000000002 l 1.0,-3.834758505292834e-17 l 0.8660254037844385,-0.5000000000000003 l 0.5000000000000021,-0.8660254037844389 Z" /></g></g></g></svg>
− diagrams/glueLineEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500.0" height="68.18181818181819" font-size="1" viewBox="0 0 500 68"><g><g transform="matrix(41.32231404958677,0.0,0.0,41.32231404958677,136.36363636363637,0.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 6.0,0.0 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 3.0,-0.5 Z" /></g></g><g transform="matrix(41.32231404958677,0.0,0.0,41.32231404958677,136.36363636363637,0.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.0,0.0 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 " /></g></g></g></svg>
− diagrams/hendecagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="98.98214418809323" font-size="1" viewBox="0 0 100 99"><g><g transform="matrix(25.875425140597297,0.0,0.0,25.875425140597297,50.00000000000001,50.5141613269018)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.7566685458330673,0.2525708066345108 l -0.1423148382732844,-0.9898214418809328 l -0.6548607339452844,-0.7557495743542588 l -0.9594929736144971,-0.28173255684143045 l -0.9594929736144977,0.28173255684142884 l -0.6548607339452855,0.7557495743542577 l -0.14231483827328584,0.9898214418809326 l 0.4154150130018858,0.9096319953545187 l 0.841253532831181,0.5406408174555977 l 0.9999999999999999,-2.7755575615628914e-17 l 0.8412535328311814,-0.5406408174555973 l 0.41541501300188677,-0.9096319953545157 Z" /></g></g></g></svg>
− diagrams/hexagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="86.6025403784439" font-size="1" viewBox="0 0 100 87"><g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,50.0,43.30127018922196)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.49999999999999967,0.8660254037844387 l 0.5000000000000002,-0.8660254037844385 l -0.4999999999999996,-0.8660254037844388 l -0.9999999999999999,-4.440892098500626e-16 l -0.5000000000000003,0.8660254037844384 l 0.49999999999999933,0.866025403784439 l 1.0000000000000002,2.220446049250313e-16 Z" /></g></g></g></svg>
− diagrams/hruleEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="48.00000000000001" font-size="1" viewBox="0 0 300 48"><g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,24.000000000000004)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -2.5,0.4000000000000001 h 5.0 " /></g></g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,24.000000000000004)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -2.0,0.2 h 4.0 " /></g></g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,24.000000000000004)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -1.5,0.0 h 3.0 " /></g></g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,24.000000000000004)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -1.0,-0.2 h 2.0 " /></g></g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,24.000000000000004)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -0.5,-0.4 h 1.0 " /></g></g></g></svg>
− diagrams/lineFromOffsetsEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="50.0" font-size="1" viewBox="0 0 300 50"><g><g transform="matrix(50.0,0.0,0.0,50.0,0.0,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.0,0.0 l 2.0,-1.0 l 2.0,1.0 l 2.0,-0.5 " /></g></g></g></svg>
− diagrams/lineFromVerticesEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="120.00000000000001" font-size="1" viewBox="0 0 300 120"><g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,60.00000000000001)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -2.5,1.0 v -1.0 l 1.0,-1.0 l 4.0,1.0 " /></g></g></g></svg>
− diagrams/nonagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="98.48077530122075" font-size="1" viewBox="0 0 100 98"><g><g transform="matrix(31.572395939441876,0.0,0.0,31.572395939441876,50.0,50.771330594287235)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.266044443118978,0.7309511000407727 l 0.1736481776669308,-0.984807753012208 l -0.49999999999999956,-0.8660254037844388 l -0.9396926207859082,-0.3420201433256692 l -0.9396926207859086,0.3420201433256681 l -0.5000000000000006,0.8660254037844384 l 0.17364817766692983,0.9848077530122082 l 0.766044443118978,0.6427876096865394 l 1.0,-2.7755575615628914e-17 l 0.7660444431189786,-0.6427876096865375 Z" /></g></g></g></svg>
− diagrams/octagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="99.99999999999999" font-size="1" viewBox="0 0 100 100"><g><g transform="matrix(37.65577839755409,0.0,0.0,37.65577839755409,50.00000000000001,50.00000000000001)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.2071067811865475,0.4999999999999996 l -2.220446049250313e-16,-1.0 l -0.7071067811865476,-0.7071067811865475 l -1.0,1.6081226496766364e-16 l -0.7071067811865475,0.7071067811865476 l 9.957992501029599e-17,1.0 l 0.7071067811865476,0.7071067811865476 l 1.0,-3.834758505292834e-17 l 0.7071067811865477,-0.7071067811865477 Z" /></g></g></g></svg>
− diagrams/pentagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="95.10565162951538" font-size="1" viewBox="0 0 100 95"><g><g transform="matrix(56.18490806817227,0.0,0.0,56.18490806817227,50.00000000000001,52.573111211913364)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.5000000000000001,0.6881909602355868 l 0.3090169943749472,-0.9510565162951536 l -0.8090169943749475,-0.5877852522924729 l -0.8090169943749473,0.5877852522924731 l 0.3090169943749479,0.9510565162951533 l 0.9999999999999996,1.1102230246251565e-16 Z" /></g></g></g></svg>
− diagrams/rectEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="150.0" height="104.99999999999999" font-size="1" viewBox="0 0 150 105"><g><g transform="matrix(136.36363636363635,0.0,0.0,136.36363636363635,74.99999999999999,52.49999999999999)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.5000000000000001,0.35 l -1.1102230246251565e-16,-0.7 h -1.0 l -1.1102230246251565e-16,0.7 h 1.0 Z" /></g></g></g></svg>
− diagrams/roundedRectEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="76.19047619047622" font-size="1" viewBox="0 0 400 76"><g><g transform="matrix(173.1601731601732,0.0,0.0,173.1601731601732,199.99999999999997,38.09523809523811)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.0499999999999998,0.10000000000000003 v -0.1 c -0.11045694996615868,-4.4408920985006264e-17 -0.19999999999999996,-8.954305003384136e-2 -0.19999999999999996 -0.20000000000000007h -0.29999999999999993 c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996v 0.2 h 0.6 c 5.522847498307935e-2,1.014530626647267e-17 0.1,-4.477152501692063e-2 9.999999999999992e-2 -9.999999999999992e-2Z" /></g></g><g transform="matrix(173.1601731601732,0.0,0.0,173.1601731601732,199.99999999999997,38.09523809523811)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.15000000000000013,0.10000000000000003 v -0.20000000000000004 c -5.522847498307934e-2,-2.2204460492503132e-17 -9.999999999999998e-2,-4.477152501692068e-2 -9.999999999999998e-2 -0.10000000000000003h -0.3 c -2.2204460492503132e-17,5.5228474983079326e-2 -4.477152501692068e-2,9.999999999999998e-2 -0.10000000000000003 9.999999999999996e-2v 0.2 c 5.522847498307934e-2,2.2204460492503132e-17 9.999999999999998e-2,4.477152501692068e-2 9.999999999999996e-2 0.10000000000000003h 0.30000000000000004 c 0.0,-5.522847498307934e-2 4.477152501692068e-2,-9.999999999999998e-2 9.999999999999998e-2 -9.999999999999998e-2Z" /></g></g><g transform="matrix(173.1601731601732,0.0,0.0,173.1601731601732,199.99999999999997,38.09523809523811)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -0.5499999999999998,0.10000000000000003 v -0.20000000000000004 c 0.0,-5.522847498307935e-2 -4.4771525016920645e-2,-0.1 -9.999999999999998e-2 -0.1h -0.3 c -5.522847498307935e-2,-3.3817687554908897e-18 -0.1,4.477152501692064e-2 -0.1 9.999999999999998e-2v 0.2 c -6.763537510981779e-18,5.522847498307935e-2 4.477152501692064e-2,0.1 9.999999999999998e-2 0.10000000000000003h 0.30000000000000004 c 5.522847498307935e-2,1.014530626647267e-17 0.1,-4.477152501692063e-2 9.999999999999998e-2 -9.999999999999998e-2Z" /></g></g></g></svg>
− diagrams/septagonEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="97.49279121818235" font-size="1" viewBox="0 0 100 97"><g><g transform="matrix(40.45835162842079,0.0,0.0,40.45835162842079,50.0,51.28584316362768)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 1.1234898018587336,0.2564292158181373 l -0.22252093395631548,-0.9749279121818234 l -0.9009688679024197,-0.4338837391175572 l -0.9009688679024187,0.43388373911755906 l -0.22252093395631345,0.9749279121818237 l 0.6234898018587343,0.7818314824680291 l 1.0,-2.7755575615628914e-17 l 0.6234898018587329,-0.7818314824680312 Z" /></g></g></g></svg>
− diagrams/squareEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200.0" height="85.71428571428572" font-size="1" viewBox="0 0 200 86"><g><g transform="matrix(25.974025974025974,0.0,0.0,25.974025974025974,100.0,42.85714285714286)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="3.0e-2" font-size="1.0em"><path d="M 3.5000000000000004,1.5 l -3.3306690738754696e-16,-3.0 h -3.0 l -3.3306690738754696e-16,3.0 h 3.000000000000001 Z" /></g></g><g transform="matrix(25.974025974025974,0.0,0.0,25.974025974025974,100.0,42.85714285714286)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="3.0e-2" font-size="1.0em"><path d="M 2.220446049250313e-16,1.0 l -2.220446049250313e-16,-2.0 h -2.0 l -2.220446049250313e-16,2.0 h 2.0 Z" /></g></g><g transform="matrix(25.974025974025974,0.0,0.0,25.974025974025974,100.0,42.85714285714286)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="3.0e-2" font-size="1.0em"><path d="M -2.5,0.5 l -1.1102230246251565e-16,-1.0 h -1.0 l -1.1102230246251565e-16,1.0 h 1.0 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_Combinators_appendsEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200.0" height="182.15600114617723" font-size="1" viewBox="0 0 200 182"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(30.3030303030303,0.0,0.0,30.3030303030303,100.0,91.07800057308862)"><g><g><path d="M 2.0001669752541407,1.732340017192659 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g><path d="M -1.669752541431091e-4,1.7323400171926577 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g><path d="M -1.0,-7.771561172376096e-16 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g><path d="M -1.6697525414155479e-4,-1.7323400171926586 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g><path d="M 2.0001669752541424,-1.7323400171926582 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g><path d="M 3.0,0.0 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g><path d="M 1.0,0.0 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_Combinators_besideEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="169.72067997066802" height="200.0" font-size="1" viewBox="0 0 170 200"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(39.69528724072871,0.0,0.0,39.69528724072871,84.86033998533402,99.99999999999999)"><g><g fill="rgb(128,0,128)" fill-opacity="1.0"><path d="M 1.9434489327457674,-0.7901733991186513 c 0.0,-0.8284271247461902 -0.6715728752538097,-1.5 -1.4999999999999996 -1.5c -0.8284271247461902,-5.072653133236334e-17 -1.5,0.6715728752538096 -1.5 1.4999999999999996c -1.0145306266472669e-16,0.8284271247461902 0.6715728752538095,1.5 1.4999999999999993 1.5c 0.8284271247461902,1.5217959399709003e-16 1.5,-0.6715728752538094 1.5000000000000002 -1.4999999999999996Z" /></g><g fill="rgb(255,165,0)" fill-opacity="1.0"><path d="M 5.655106725423198e-2,1.2901733991186521 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M -0.8518419967810219,1.2901733991186521 c 0.0,-5.05931137120553e-2 -4.101382225269076e-2,-9.160693596474608e-2 -9.160693596474606e-2 -9.160693596474608e-2c -5.05931137120553e-2,-3.0979347383183296e-18 -9.160693596474608e-2,4.1013822252690756e-2 -9.160693596474608e-2 9.160693596474605e-2c -6.195869476636659e-18,5.05931137120553e-2 4.1013822252690756e-2,9.160693596474608e-2 9.160693596474603e-2 9.160693596474608e-2c 5.05931137120553e-2,9.293804214954989e-18 9.160693596474608e-2,-4.101382225269075e-2 9.160693596474609e-2 -9.160693596474605e-2Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_Combinators_positionEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="204.25531914893568" height="300.0" font-size="1" viewBox="0 0 204 300"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(31.91489361702117,0.0,0.0,31.91489361702117,102.12765957446776,293.6170212765958)"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 3.2000000000000055,-9.000000000000032 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 3.0000000000000053,-7.840000000000029 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.800000000000005,-6.7600000000000255 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.600000000000005,-5.760000000000023 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.400000000000005,-4.84000000000002 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.2000000000000046,-4.000000000000018 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.0000000000000044,-3.2400000000000153 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.800000000000004,-2.560000000000013 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.6000000000000039,-1.9600000000000108 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.4000000000000037,-1.440000000000009 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.2000000000000035,-1.000000000000007 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.0000000000000033,-0.6400000000000055 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.8000000000000032,-0.3600000000000038 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.600000000000003,-0.16000000000000242 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.40000000000000285,-4.000000000000114e-2 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.20000000000000268,-7.099748146989106e-30 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.4980018054066022e-15,-3.999999999999901e-2 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.19999999999999768,-0.15999999999999814 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.39999999999999786,-0.35999999999999743 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.5999999999999981,-0.6399999999999969 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.7999999999999983,-0.9999999999999964 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.9999999999999984,-1.4399999999999962 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -1.1999999999999986,-1.959999999999996 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -1.3999999999999988,-2.559999999999996 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -1.599999999999999,-3.239999999999996 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -1.7999999999999992,-3.9999999999999964 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -1.9999999999999993,-4.839999999999997 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -2.1999999999999993,-5.759999999999997 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -2.3999999999999995,-6.759999999999998 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -2.5999999999999996,-7.839999999999999 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -2.8,-9.0 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_Combinators_strutEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="119.99999999999999" font-size="1" viewBox="0 0 300 120"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,59.99999999999999)"><g><g><path d="M 2.5,1.1102230246251565e-16 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g><g></g><g><path d="M -0.5000000000000002,1.1102230246251565e-16 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_Combinators_withEnvelopeEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="166.66666666666669" font-size="1" viewBox="0 0 300 167"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(55.555555555555564,0.0,0.0,55.555555555555564,150.0,83.33333333333334)"><g><g><g fill="rgb(0,0,255)" fill-opacity="1.0"><path d="M 2.0,1.0 l -2.220446049250313e-16,-2.0 h -2.0 l -2.220446049250313e-16,2.0 h 2.0 Z" /></g><g stroke="rgb(255,255,255)" stroke-opacity="1.0" stroke-dasharray="0.1,0.1" stroke-dashoffset="0.0"><path d="M 1.7999999999999998,1.1102230246251565e-16 c 0.0,-0.4418277998646348 -0.35817220013536516,-0.8 -0.7999999999999998 -0.8c -0.4418277998646348,-2.7054150043927117e-17 -0.8,0.3581722001353651 -0.8 0.7999999999999998c -5.4108300087854235e-17,0.4418277998646348 0.3581722001353651,0.8 0.7999999999999997 0.8c 0.4418277998646348,8.116245013178136e-17 0.8,-0.35817220013536505 0.8000000000000002 -0.7999999999999998Z" /></g></g><g fill="rgb(0,128,0)" fill-opacity="1.0"><path d="M 0.19999999999999996,1.1102230246251565e-16 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.5522847498307935,-3.3817687554908895e-17 -1.0,0.4477152501692064 -1.0 0.9999999999999997c -6.763537510981779e-17,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.5522847498307935,1.0145306266472669e-16 1.0,-0.44771525016920627 1.0000000000000002 -0.9999999999999997Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_CubicSpline_cubicSplineEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600.0" height="150.9864382575878" font-size="1" viewBox="0 0 600 151"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(25.279963015185068,0.0,0.0,25.279963015185068,300.0,75.4932191287939)"><g><g><g stroke-width="5.0e-2"><path d="M 5.30560144347186,0.514806155640732 c -0.27272727272727276,-0.27272727272727276 0.27272727272727276,-3.3636363636363633 2.0 -2.999999999999999c 1.727272727272727,0.36363636363636376 4.636363636363636,4.181818181818182 3.0 4.999999999999998c -1.6363636363636362,0.8181818181818183 -7.818181818181818,-1.3636363636363633 -8.999999999999998 -3.0c -1.1818181818181825,-1.6363636363636367 2.636363636363636,-2.727272727272727 4.000000000000001 -1.9999999999999996c 1.363636363636364,0.7272727272727271 0.27272727272727276,3.272727272727273 -2.6645352591003757e-15 3.000000000000001Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M 5.5056014434718605,-2.485193844359268 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M 1.5056014434718603,-0.48519384435926804 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M 10.50560144347186,2.514806155640732 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M 7.5056014434718605,-2.485193844359268 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M 5.5056014434718605,0.514806155640732 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g><g></g><g fill-opacity="0.0" stroke-width="5.0e-2"><path d="M -6.333419254268965,0.514806155640732 c 0.2142857142857144,-1.9107142857142858 0.4285714285714288,-3.8214285714285716 2.0 -3.0c 1.5714285714285712,0.8214285714285716 4.5,4.375 2.999999999999999 5.0c -1.5,0.625 -7.428571428571427,-1.6785714285714282 -9.0 -2.999999999999999c -1.571428571428572,-1.3214285714285716 1.214285714285714,-1.660714285714286 4.0 -2.0" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M -6.133419254268965,-2.485193844359268 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M -10.133419254268965,-0.48519384435926804 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M -1.1334192542689652,2.514806155640732 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M -4.133419254268965,-2.485193844359268 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g><g fill="rgb(0,0,255)" fill-opacity="1.0" stroke-width="0.0"><path d="M -6.133419254268965,0.514806155640732 c 0.0,-0.1104569499661587 -8.954305003384129e-2,-0.2 -0.19999999999999996 -0.2c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996c -1.3527075021963559e-17,0.1104569499661587 8.954305003384128e-2,0.2 0.19999999999999993 0.2c 0.1104569499661587,2.029061253294534e-17 0.2,-8.954305003384126e-2 0.20000000000000004 -0.19999999999999996Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TrailLike_explodeTrailEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="285.31695488854604" font-size="1" viewBox="0 0 300 285"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(168.5547242045168,0.0,0.0,168.5547242045168,150.0,142.65847744427302)"><g fill-opacity="0.0"><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -0.49999999999999956,0.7694208842938132 l 0.9999999999999996,1.1102230246251565e-16 " /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -0.8090169943749475,-0.18163563200134014 l 0.3090169943749479,0.9510565162951533 " /></g><g stroke="rgb(255,255,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -1.1102230246251565e-16,-0.7694208842938133 l -0.8090169943749473,0.5877852522924731 " /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 0.8090169943749473,-0.18163563200134036 l -0.8090169943749475,-0.5877852522924729 " /></g><g stroke="rgb(255,165,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 0.5000000000000002,0.7694208842938133 l 0.3090169943749471,-0.9510565162951536 " /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TrailLike_fromOffsetsEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="86.60254037844385" font-size="1" viewBox="0 0 300 87"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(90.9090909090909,0.0,0.0,90.9090909090909,150.0,43.301270189221924)"><g fill-opacity="0.0"><path d="M -1.5,0.4330127018922193 h 1.0 l 0.5000000000000001,-0.8660254037844386 l 0.5000000000000001,0.8660254037844386 h 1.0 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TrailLike_fromSegmentsEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="247.48737341529161" height="200.00000000000003" font-size="1" viewBox="0 0 247 200"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(128.564869306645,0.0,0.0,128.564869306645,123.74368670764581,100.00000000000001)"><g fill-opacity="0.0"><path d="M -0.875,0.7071067811865476 l 1.0,-1.0 c 1.0,-1.0 1.0,0.0 0.0 1.0h -1.0 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TrailLike_fromVerticesEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="305.02203183512904" font-size="1" viewBox="0 0 300 305"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(114.88022467370443,0.0,0.0,114.88022467370443,150.0,152.51101591756452)"><g><path d="M 0.41802076667285704,0.6469755613042312 l 0.457690772717425,-0.1352679348067608 l 0.311295508610812,-0.4195471927671871 l -0.45996928695328987,-0.39624138872120573 l 1.2786776094528052e-2,-0.47708988249036255 l -0.3028174891412384,-0.4257068344650894 l -0.5189862813282371,0.315011464662979 l -0.44978811048447176,-0.15958982826097634 l -0.49844700928799934,0.1564458998246363 l 0.13921812539752376,0.5909291807288132 l -0.29077111610952444,0.3784579443663209 l -5.239704189479388e-3,0.5223957179572758 l 0.6050278146739517,5.020285397155655e-2 l 0.2700816777820438,0.3934897011917795 l 0.49520869400790596,0.16641240945036362 l 0.2347096282100502,-0.5599021106421431 Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TrailLike_twiddleEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="259.80762113533166" font-size="1" viewBox="0 0 300 260"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(136.36363636363635,0.0,0.0,136.36363636363635,150.0,129.90381056766583)"><g fill-opacity="0.0"><path d="M -0.5000000000000007,0.8660254037844385 h 0.0 " /><path d="M -0.5000000000000007,0.8660254037844385 l -0.49999999999999933,-0.866025403784439 " /><path d="M -0.5000000000000007,0.8660254037844385 l 9.992007221626409e-16,-1.7320508075688774 " /><path d="M -0.5000000000000007,0.8660254037844385 l 1.0000000000000009,-1.732050807568877 " /><path d="M -0.5000000000000007,0.8660254037844385 l 1.5000000000000004,-0.8660254037844382 " /><path d="M -0.5000000000000007,0.8660254037844385 l 1.0000000000000004,3.3306690738754696e-16 " /><path d="M -1.0,-5.551115123125783e-16 l 0.49999999999999933,0.866025403784439 " /><path d="M -1.0,-5.551115123125783e-16 h 0.0 " /><path d="M -1.0,-5.551115123125783e-16 l 0.5000000000000003,-0.8660254037844384 " /><path d="M -1.0,-5.551115123125783e-16 l 1.5000000000000002,-0.8660254037844379 " /><path d="M -1.0,-5.551115123125783e-16 l 2.0,8.881784197001252e-16 " /><path d="M -1.0,-5.551115123125783e-16 l 1.4999999999999996,0.8660254037844394 " /><path d="M -0.49999999999999967,-0.8660254037844389 l -9.992007221626409e-16,1.7320508075688774 " /><path d="M -0.49999999999999967,-0.8660254037844389 l -0.5000000000000003,0.8660254037844384 " /><path d="M -0.49999999999999967,-0.8660254037844389 h 0.0 " /><path d="M -0.49999999999999967,-0.8660254037844389 l 0.9999999999999999,4.440892098500626e-16 " /><path d="M -0.49999999999999967,-0.8660254037844389 l 1.4999999999999996,0.8660254037844393 " /><path d="M -0.49999999999999967,-0.8660254037844389 l 0.9999999999999993,1.7320508075688776 " /><path d="M 0.5000000000000002,-0.8660254037844385 l -1.0000000000000009,1.732050807568877 " /><path d="M 0.5000000000000002,-0.8660254037844385 l -1.5000000000000002,0.8660254037844379 " /><path d="M 0.5000000000000002,-0.8660254037844385 l -0.9999999999999999,-4.440892098500626e-16 " /><path d="M 0.5000000000000002,-0.8660254037844385 h 0.0 " /><path d="M 0.5000000000000002,-0.8660254037844385 l 0.49999999999999967,0.8660254037844388 " /><path d="M 0.5000000000000002,-0.8660254037844385 l -5.551115123125783e-16,1.7320508075688772 " /><path d="M 0.9999999999999999,3.3306690738754696e-16 l -1.5000000000000004,0.8660254037844382 " /><path d="M 0.9999999999999999,3.3306690738754696e-16 l -2.0,-8.881784197001252e-16 " /><path d="M 0.9999999999999999,3.3306690738754696e-16 l -1.4999999999999996,-0.8660254037844393 " /><path d="M 0.9999999999999999,3.3306690738754696e-16 l -0.49999999999999967,-0.8660254037844388 " /><path d="M 0.9999999999999999,3.3306690738754696e-16 h 0.0 " /><path d="M 0.9999999999999999,3.3306690738754696e-16 l -0.5000000000000002,0.8660254037844385 " /><path d="M 0.49999999999999967,0.8660254037844388 l -1.0000000000000004,-3.3306690738754696e-16 " /><path d="M 0.49999999999999967,0.8660254037844388 l -1.4999999999999996,-0.8660254037844394 " /><path d="M 0.49999999999999967,0.8660254037844388 l -0.9999999999999993,-1.7320508075688776 " /><path d="M 0.49999999999999967,0.8660254037844388 l 5.551115123125783e-16,-1.7320508075688772 " /><path d="M 0.49999999999999967,0.8660254037844388 l 0.5000000000000002,-0.8660254037844385 " /><path d="M 0.49999999999999967,0.8660254037844388 h 0.0 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_Trail_closeLineEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500.0" height="68.18181818181819" font-size="1" viewBox="0 0 500 68"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(41.32231404958678,0.0,0.0,41.32231404958678,250.0,34.09090909090909)"><g fill-opacity="0.0"><g><path d="M 3.5,-0.75 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 h 2.0 Z" /></g><path d="M -2.5,-0.75 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_Trail_glueLineEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500.0" height="68.18181818181819" font-size="1" viewBox="0 0 500 68"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(41.32231404958677,0.0,0.0,41.32231404958677,136.36363636363637,0.0)"><g><path d="M 6.0,0.0 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 3.0,-0.5 Z" /></g><path d="M 0.0,0.0 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 " /></g></g></g></svg>
+ diagrams/src_Diagrams_Trail_lineFromOffsetsEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="50.0" font-size="1" viewBox="0 0 300 50"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(50.0,0.0,0.0,50.0,0.0,50.0)"><path d="M 0.0,0.0 l 2.0,-1.0 l 2.0,1.0 l 2.0,-0.5 " /></g></g></g></svg>
+ diagrams/src_Diagrams_Trail_lineFromVerticesEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="120.00000000000001" font-size="1" viewBox="0 0 300 120"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,60.00000000000001)"><g fill-opacity="0.0"><path d="M -2.5,1.0 v -1.0 l 1.0,-1.0 l 4.0,1.0 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_Trail_trailOffsetEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="90.00000000000001" font-size="1" viewBox="0 0 300 90"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,45.00000000000001)"><g fill-opacity="0.0"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="5.0e-2"><path d="M 0.5,-0.75 h -2.0 " /></g><path d="M 0.5,-0.75 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arc_annularWedgeEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="178.54130895779457" font-size="1" viewBox="0 0 400 179"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(81.15495782275252,0.0,0.0,81.15495782275252,200.0,89.27065447889727)"><g fill="rgb(0,0,255)" fill-opacity="1.0"><g><path d="M 2.0282508910505657,-0.49497249665864596 l 0.2121320343559643,-0.21213203435596428 c -0.39052429175126996,-0.39052429175127 -1.023689270621825,-0.3905242917512702 -1.414213562373095 -2.220446049250313e-16c -0.39052429175127,0.39052429175126996 -0.3905242917512702,1.023689270621825 -3.3306690738754696e-16 1.414213562373095c 0.3905242917512699,0.39052429175127007 1.0236892706218248,0.39052429175127024 1.4142135623730947 4.440892098500626e-16l -0.21213203435596423,-0.21213203435596434 c -0.2733670042258889,0.27336700422588883 -0.7165824894352774,0.2733670042258887 -0.9899494936611662 -3.108624468950438e-16c -0.2733670042258889,-0.2733670042258889 -0.2733670042258888,-0.7165824894352775 2.3314683517128283e-16 -0.9899494936611664c 0.2733670042258889,-0.27336700422588894 0.7165824894352775,-0.27336700422588883 0.9899494936611667 1.1102230246251565e-16Z" /></g><g><path d="M -3.989378006737523e-2,-0.29835431843854476 l 7.316992428735741e-2,-0.6961653267577913 c -0.28185620611337825,-2.9624280998431504e-2 -0.5630453243913867,6.173960189645773e-2 -0.7736590696265117 0.25137706989087893l 0.4683914244512005,0.5202013778341761 c 6.31841235705375e-2,-5.689124039832636e-2 0.14754085905394002,-8.430040526679312e-2 0.23209772088795366 -7.541312096726371e-2Z" /></g><path d="M -1.7403829254065295,2.250171937223655e-6 h 0.5 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0l -3.061616997868383e-17,0.5 c 0.27614237491539667,0.0 0.4999999999999999,0.22385762508460327 0.49999999999999983 0.5Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arc_arc'Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="299.99999999999994" font-size="1" viewBox="0 0 300 300"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(109.09090909090911,0.0,0.0,109.09090909090911,150.0,149.99999999999997)"><g fill-opacity="0.0"><path d="M 1.2499999999999998,0.25000000000000033 c 0.0,-0.8284271247461902 -0.6715728752538097,-1.5 -1.4999999999999996 -1.5" /><path d="M 0.7499999999999998,0.25000000000000033 c 0.0,0.5522847498307932 -0.44771525016920655,0.9999999999999996 -1.0 0.9999999999999994c -0.5522847498307932,0.0 -0.9999999999999997,-0.44771525016920655 -0.9999999999999996 -1.0c 0.0,-0.5522847498307932 0.44771525016920655,-0.9999999999999997 1.0 -0.9999999999999997" /><path d="M 0.24999999999999978,0.25000000000000033 c 0.0,-0.2761423749153967 -0.22385762508460322,-0.5 -0.4999999999999999 -0.5" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arc_arcBetweenEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="149.99999999999991" font-size="1" viewBox="0 0 300 150"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(136.363636363636,0.0,0.0,136.363636363636,150.0,74.99999999999997)"><g fill-opacity="0.0"><path d="M -0.9999999999999991,0.4999999999999992 c 0.5260763745333457,-0.5611805842666443 1.2354097078666786,-0.9158472509333104 2.0000000000000013 -0.9999999999999992" /><path d="M -0.9999999999999979,0.5000000000000004 c 0.6017048539333386,-0.44992362546665604 1.2790381872666725,-0.7885902921333223 2.0000000000000004 -0.9999999999999998" /><path d="M -0.9999999999999987,0.5 l 2.0000000000000004,-0.9999999999999999 " /><path d="M -1.0000000000000027,0.500000000000001 c 0.720961812733329,-0.21140970786667745 1.3982951460666655,-0.5500763745333455 2.000000000000005 -1.000000000000002" /><path d="M -0.9999999999999994,0.5000000000000004 c 0.7645902921333227,-8.415274906668882e-2 1.4739236254666557,-0.4388194157333549 2.0000000000000013 -0.999999999999999" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arc_wedgeEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="178.54130895779457" font-size="1" viewBox="0 0 400 179"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(81.15495782275252,0.0,0.0,81.15495782275252,200.0,89.27065447889727)"><g fill="rgb(0,0,255)" fill-opacity="1.0"><g><path d="M 1.5332761442199825,2.250171937223655e-6 l 0.7071067811865476,-0.7071067811865475 c -0.39052429175126996,-0.39052429175127 -1.023689270621825,-0.3905242917512702 -1.414213562373095 -2.220446049250313e-16c -0.39052429175127,0.39052429175126996 -0.3905242917512702,1.023689270621825 -3.3306690738754696e-16 1.414213562373095c 0.3905242917512699,0.39052429175127007 1.0236892706218248,0.39052429175127024 1.4142135623730947 4.440892098500626e-16l -0.707106781186547,-0.7071067811865477 Z" /></g><g><path d="M -7.125231904767126e-2,2.250171937223655e-6 l 0.10452846326765346,-0.9945218953682733 c -0.28185620611337825,-2.9624280998431504e-2 -0.5630453243913867,6.173960189645773e-2 -0.7736590696265117 0.25137706989087893l 0.6691306063588582,0.7431448254773944 Z" /></g><path d="M -2.2403829254065295,2.250171937223655e-6 h 1.0 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0l -2.220446049250313e-16,1.0 Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrow_example1.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="499.99999999999994" height="142.85714285714286" font-size="1" viewBox="0 0 500 143"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(64.93506493506493,0.0,0.0,64.93506493506493,71.42857142857139,71.42857142857143)"><g><g stroke="rgb(169,169,169)" stroke-opacity="1.0" stroke-width="7.0e-2"><path d="M 6.0,1.0 l -2.220446049250313e-16,-2.0 h -2.0 l -2.220446049250313e-16,2.0 h 2.0 Z" /><g fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M 5.04,0.0 c 0.0,-2.209138999323174e-2 -1.7908610006768258e-2,-4.0e-2 -3.9999999999999994e-2 -4.0e-2c -2.209138999323174e-2,-1.3527075021963559e-18 -4.0e-2,1.7908610006768255e-2 -4.0e-2 3.999999999999999e-2c -2.7054150043927117e-18,2.209138999323174e-2 1.7908610006768255e-2,4.0e-2 3.999999999999998e-2 4.0e-2c 2.209138999323174e-2,4.0581225065890676e-18 4.0e-2,-1.790861000676825e-2 4.000000000000001e-2 -3.999999999999999e-2Z" /></g></g></g><g></g><g stroke="rgb(169,169,169)" stroke-opacity="1.0" stroke-width="7.0e-2"><path d="M 1.0000000000000002,1.0 l -2.220446049250313e-16,-2.0 h -2.0 l -2.220446049250313e-16,2.0 h 2.0 Z" /><g fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M 4.0e-2,0.0 c 0.0,-2.209138999323174e-2 -1.7908610006768258e-2,-4.0e-2 -3.9999999999999994e-2 -4.0e-2c -2.209138999323174e-2,-1.3527075021963559e-18 -4.0e-2,1.7908610006768255e-2 -4.0e-2 3.999999999999999e-2c -2.7054150043927117e-18,2.209138999323174e-2 1.7908610006768255e-2,4.0e-2 3.999999999999998e-2 4.0e-2c 2.209138999323174e-2,4.0581225065890676e-18 4.0e-2,-1.790861000676825e-2 4.000000000000001e-2 -3.999999999999999e-2Z" /></g></g><g><g><g fill-opacity="0.0" stroke-width="2.0e-2"><path d="M 0.29748256273725837,3.878304871039902e-2 c 0.9519443557972225,0.12410577608570911 1.903888711594445,0.24821155217141821 2.15046054898094 0.17171496874379844c 0.24657183738649566,-7.649658342761977e-2 -0.21222884363773598,-0.35359552636856845 3.4342993748759695e-2 -0.43009210979618817c 0.24657183738649566,-7.649658342761977e-2 1.198516193183718,4.760919265808934e-2 2.1504605489809396 0.1717149687437984" /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.29748256273725837,3.878304871039902e-2 l -1.2927682903466336e-3,9.916085424575276e-3 l -9.430757659181744e-3,-1.2294957065939064e-3 l 1.0723525949528377e-2,-8.68658971798137e-3 l -8.137989368835107e-3,-1.1145581131169199e-2 l 9.43075765918174e-3,1.2294957065939237e-3 l -1.2927682903466336e-3,9.916085424575276e-3 h -0.0 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.29748256273725837,3.878304871039902e-2 l -0.15757826014270998,0.12764623322362204 l -0.30987766951797735,-4.03990090733323e-2 l 0.16997336692342907,-0.12603027286068874 l -0.13197986013857382,-0.16539616579119604 l 0.30987766951797735,4.03990090733323e-2 l 0.11958475335785472,0.16378020542826274 l 1.3877787807814457e-17,2.7755575615628914e-17 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 5.0,-2.7755575615628914e-17 l -0.5609471155928247,0.10469666898034764 l 0.2039680403081149,-0.15123632743282647 l -0.15837583216628864,-0.19847539894943522 l 0.5153549074509984,0.24501505740191404 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 4.64302092471529,-4.653965845247886e-2 l -1.1567038557738623e-2,8.57662027886182e-3 l 2.5855365806932637e-3,-1.9832170849150513e-2 l 8.981501977045359e-3,1.1255550570288693e-2 h -0.0 Z" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrow_example2.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500.0" height="191.60937134592436" font-size="1" viewBox="0 0 500 192"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(58.063445862401316,0.0,0.0,58.063445862401316,250.0,95.80468567296218)"><g><g><g><g fill-opacity="0.0"><path d="M -2.707106781186548,0.0 l 4.98932980156782e-17,0.8148193920143483 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -2.707106781186548,1.0 l -8.8167787843871e-2,-0.2713525491562421 l 8.816778784387098e-2,9.13525491562421e-2 l 8.816778784387096e-2,-9.135254915624214e-2 l -8.816778784387094e-2,0.27135254915624213 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -2.707106781186548,0.8200000000000001 l -4.9999999999999906e-3,-5.180607985651786e-3 l 9.999999999999981e-3,-6.123233995736754e-19 l -4.9999999999999906e-3,5.180607985651786e-3 v 8.673617379884035e-19 Z" /></g></g></g></g><g><g stroke="rgb(169,169,169)" stroke-opacity="1.0" stroke-width="0.1"><path d="M 3.9142135623730954,0.4999999999999996 l -2.220446049250313e-16,-1.0 l -0.7071067811865476,-0.7071067811865475 l -1.0,1.6081226496766364e-16 l -0.7071067811865475,0.7071067811865476 l 9.957992501029599e-17,1.0 l 0.7071067811865476,0.7071067811865476 l 1.0,-3.834758505292834e-17 l 0.7071067811865477,-0.7071067811865477 Z" /></g><g fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M 2.75539105243401,0.0 c 0.0,-2.6666666666666675e-2 -2.161760458079523e-2,-4.828427124746191e-2 -4.8284271247461895e-2 -4.828427124746191e-2c -2.6666666666666675e-2,-1.632862398863138e-18 -4.828427124746191e-2,2.1617604580795226e-2 -4.828427124746191e-2 4.8284271247461895e-2c -3.265724797726276e-18,2.6666666666666675e-2 2.1617604580795223e-2,4.828427124746191e-2 4.828427124746189e-2 4.828427124746191e-2c 2.6666666666666675e-2,4.898587196589414e-18 4.828427124746191e-2,-2.1617604580795223e-2 4.8284271247461916e-2 -4.8284271247461895e-2Z" /></g></g><g></g><g stroke="rgb(169,169,169)" stroke-opacity="1.0" stroke-width="0.1"><path d="M -1.5000000000000004,0.4999999999999996 l -2.220446049250313e-16,-1.0 l -0.7071067811865476,-0.7071067811865475 l -1.0,1.6081226496766364e-16 l -0.7071067811865475,0.7071067811865476 l 9.957992501029599e-17,1.0 l 0.7071067811865476,0.7071067811865476 l 1.0,-3.834758505292834e-17 l 0.7071067811865477,-0.7071067811865477 Z" /></g><g fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M -2.658822509939086,0.0 c 0.0,-2.6666666666666675e-2 -2.161760458079523e-2,-4.828427124746191e-2 -4.8284271247461895e-2 -4.828427124746191e-2c -2.6666666666666675e-2,-1.632862398863138e-18 -4.828427124746191e-2,2.1617604580795226e-2 -4.828427124746191e-2 4.8284271247461895e-2c -3.265724797726276e-18,2.6666666666666675e-2 2.1617604580795223e-2,4.828427124746191e-2 4.828427124746189e-2 4.828427124746191e-2c 2.6666666666666675e-2,4.898587196589414e-18 4.828427124746191e-2,-2.1617604580795223e-2 4.8284271247461916e-2 -4.8284271247461895e-2Z" /></g><g><g><g fill-opacity="0.0"><path d="M -2.707106781186548,0.0 h 5.229032954387444 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.7071067811865483,0.0 l -0.2713525491562421,8.816778784387098e-2 l 9.13525491562421e-2,-8.816778784387098e-2 l -9.135254915624214e-2,-8.816778784387096e-2 l 0.27135254915624213,8.816778784387096e-2 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 2.527106781186548,0.0 l -5.180607985651786e-3,4.9999999999999906e-3 v -9.999999999999981e-3 l 5.180607985651786e-3,4.9999999999999906e-3 h -0.0 Z" /></g></g></g></g><g><g><g fill-opacity="0.0"><path d="M -1.5000000000000016,0.5000000000000004 l 2.81481939201435,-4.687615948763571e-16 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.5,0.49999999999999994 l -0.2713525491562421,8.816778784387103e-2 l 9.135254915624208e-2,-8.8167787843871e-2 l -9.135254915624215e-2,-8.816778784387094e-2 l 0.27135254915624213,8.816778784387092e-2 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.32,0.5 l -5.180607985651785e-3,4.999999999999991e-3 l -1.6653345369377307e-18,-9.999999999999981e-3 l 5.180607985651787e-3,4.99999999999999e-3 h -0.0 Z" /></g></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_blockEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.2427050983124842,0.0 h -0.2417050983124837 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.2427050983124842,-8.816778784387098e-2 l -2.6945678834043217e-17,0.17633557568774197 h -0.24270509831248419 l -2.6945678834043217e-17,-0.17633557568774197 h 0.24270509831248424 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_dart'Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.18,0.0 h -0.1789999999999995 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.18,0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.0,0.0 l 0.2713525491562421,8.816778784387098e-2 l -9.13525491562421e-2,-8.816778784387098e-2 l 9.135254915624214e-2,-8.816778784387096e-2 l -0.27135254915624213,8.816778784387096e-2 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_dartEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="73.63770250368194" font-size="1" viewBox="0 0 100 74"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(147.27540500736387,0.0,0.0,147.27540500736387,26.36229749631806,36.81885125184097)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.0,0.0 h -0.1789999999999995 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.0000000000005005e-3,0.0 l -0.2713525491562421,8.816778784387098e-2 l 9.13525491562421e-2,-8.816778784387098e-2 l -9.135254915624214e-2,-8.816778784387096e-2 l 0.27135254915624213,8.816778784387096e-2 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.1789999999999995,0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_missile'Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.18000000000000005,0.0 h -0.17899999999999955 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.18000000000000005,0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 5.551115123125783e-17,0.0 c -2.7755575615628914e-17,4.408389392193548e-2 0.22635254915624206,8.816778784387098e-2 0.27135254915624213 8.8167787843871e-2c 4.500000000000001e-2,0.0 -9.135254915624212e-2,-4.40838939219355e-2 -9.135254915624208e-2 -8.816778784387098e-2c 1.2721305490496585e-17,-4.4083893921935485e-2 0.13635254915624218,-8.816778784387096e-2 9.13525491562421e-2 -8.816778784387094e-2c -4.5000000000000005e-2,0.0 -0.27135254915624213,4.408389392193548e-2 -0.27135254915624213 8.816778784387093e-2Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_missileEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="99.99999999999999" height="73.63770250368192" font-size="1" viewBox="0 0 100 74"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(147.27540500736384,0.0,0.0,147.27540500736384,26.362297496318064,36.81885125184096)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.0,0.0 h -0.17899999999999955 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.000000000000445e-3,0.0 c 2.7755575615628914e-17,4.408389392193548e-2 -0.22635254915624206,8.816778784387098e-2 -0.27135254915624213 8.8167787843871e-2c -4.500000000000001e-2,0.0 9.135254915624212e-2,-4.40838939219355e-2 9.135254915624208e-2 -8.816778784387098e-2c -1.2721305490496585e-17,-4.4083893921935485e-2 -0.13635254915624218,-8.816778784387096e-2 -9.13525491562421e-2 -8.816778784387094e-2c 4.5000000000000005e-2,0.0 0.27135254915624213,4.408389392193548e-2 0.27135254915624213 8.816778784387093e-2Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.17899999999999955,0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_quillEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.18000000000000002,0.0 h -0.17899999999999952 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.18000000000000002,0.0 h 0.0 h 0.0 h 0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.18000000000000002,0.0 l -8.38525491562421e-2,8.816778784387098e-2 h -0.1875 l 9.13525491562421e-2,-8.816778784387098e-2 l -9.13525491562421e-2,-8.816778784387098e-2 h 0.1875 l 8.38525491562421e-2,8.816778784387098e-2 h -2.7755575615628914e-17 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_spike'Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.21213203435596423,0.0 h -0.21113203435596373 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.21213203435596423,0.0 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.0,0.0 l 0.2560660171779821,0.10606601717798213 c -5.85786437626905e-2,-5.8578643762690494e-2 -5.857864376269052e-2,-0.15355339059327375 -3.3306690738754695e-17 -0.21213203435596423l -0.2560660171779821,0.10606601717798213 l 5.551115123125783e-17,-2.7755575615628914e-17 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_spikeEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="70.31043123416943" font-size="1" viewBox="0 0 100 70"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(140.62086246833886,0.0,0.0,140.62086246833886,29.689568765830572,35.155215617084714)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.0,0.0 h -0.21113203435596373 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.0000000000005005e-3,0.0 l -0.2560660171779821,0.10606601717798213 c 5.85786437626905e-2,-5.8578643762690494e-2 5.857864376269052e-2,-0.15355339059327375 3.3306690738754695e-17 -0.21213203435596423l 0.2560660171779821,0.10606601717798213 l -5.551115123125783e-17,-2.7755575615628914e-17 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.21113203435596373,0.0 Z" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_thorn'Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.21213203435596423,0.0 h -0.21113203435596373 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.21213203435596423,0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.0,0.0 c 7.5e-2,0.0 0.20303300858899107,5.3033008588991064e-2 0.2560660171779821 0.10606601717798213l -4.393398282201788e-2,-0.10606601717798213 l 4.393398282201788e-2,-0.10606601717798213 c -5.303300858899106e-2,5.3033008588991064e-2 -0.18106601717798212,0.10606601717798213 -0.2560660171779821 0.10606601717798211v 1.3877787807814457e-17 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_thornEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="70.31043123416943" font-size="1" viewBox="0 0 100 70"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(140.62086246833886,0.0,0.0,140.62086246833886,29.689568765830572,35.155215617084714)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.0,0.0 h -0.21113203435596373 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.0000000000005005e-3,0.0 c -7.5e-2,0.0 -0.20303300858899107,5.3033008588991064e-2 -0.2560660171779821 0.10606601717798213l 4.393398282201788e-2,-0.10606601717798213 l -4.393398282201788e-2,-0.10606601717798213 c 5.303300858899106e-2,5.3033008588991064e-2 0.18106601717798212,0.10606601717798213 0.2560660171779821 0.10606601717798211v 1.3877787807814457e-17 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M -0.21113203435596373,0.0 h 0.0 h 0.0 h 0.0 h -0.0 Z" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_tri'Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(200.0,0.0,0.0,200.0,0.0,50.0)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.22499999999999998,0.0 h -0.22399999999999948 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 0.0,0.0 l 0.22499999999999998,0.1299038105676658 v -0.2598076211353316 l -0.22499999999999998,0.1299038105676658 Z" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_tri25Ex.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="119.99999999999999" height="82.72509808789549" font-size="1" viewBox="0 0 120 83"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(137.87516347982583,0.0,0.0,137.87516347982583,37.274901912104454,41.362549043947745)"><g stroke-width="0.0"><path d="M 0.6000000000000002,0.3 l -6.661338147750939e-17,-0.6 h -0.6 l -6.661338147750939e-17,0.6 h 0.6000000000000002 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.0,0.0 h -0.2703525491562416 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.0000000000005005e-3,0.0 l -0.2713525491562421,8.816778784387098e-2 v -0.17633557568774197 l 0.2713525491562421,8.816778784387098e-2 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Arrowheads_triEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="69.06077348066303" font-size="1" viewBox="0 0 100 69"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(138.12154696132606,0.0,0.0,138.12154696132606,30.939226519336966,34.530386740331515)"><g stroke-width="0.0"><path d="M 0.5,0.25 l -5.551115123125783e-17,-0.5 h -0.5 l -5.551115123125783e-17,0.5 h 0.5 Z" /></g><g><g><g fill-opacity="0.0" stroke-width="0.0"><path d="M 0.0,0.0 h -0.22399999999999948 " /></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g><g stroke-width="0.0"><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="M 1.0000000000005005e-3,0.0 l -0.22499999999999998,0.1299038105676658 v -0.2598076211353316 l 0.22499999999999998,0.1299038105676658 Z" /></g><g fill="rgb(0,0,0)" fill-opacity="1.0"><path d="" /></g></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Curvature_diagramA.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g fill-opacity="0.0" stroke-width="0.1"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Curvature_diagramNeg.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g fill-opacity="0.0"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" stroke-width="5.0e-2"><g><path d="M 4.464000000000002,-3.8037685950413227 l 2.077770135746605,7.445342986425346 " /><g><path d="M 14.271599430272687,3.6415743913840233 c 0.0,-4.269066838162075 -3.4607624563640047,-7.7298292945260805 -7.729829294526079 -7.7298292945260805c -4.269066838162075,-2.614049519350648e-16 -7.7298292945260805,3.4607624563640043 -7.7298292945260805 7.729829294526078c -5.228099038701296e-16,4.269066838162075 3.460762456364004,7.7298292945260805 7.729829294526077 7.7298292945260805c 4.269066838162075,7.842148558051945e-16 7.7298292945260805,-3.4607624563640034 7.729829294526082 -7.729829294526078Z" /></g></g></g><g fill-opacity="0.0" stroke-width="0.1"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Curvature_diagramPos.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g fill-opacity="0.0"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" stroke-width="5.0e-2"><g><path d="M -4.463999999999999,3.1082314049586772 l -3.900145794392522,-8.6003214953271 " /><g><path d="M 1.079194030081819,-5.492090090368422 c 0.0,-5.215412572526979 -4.227927251947359,-9.44333982447434 -9.443339824474338 -9.44333982447434c -5.215412572526979,-3.193519156589014e-16 -9.44333982447434,4.227927251947358 -9.44333982447434 9.443339824474336c -6.387038313178028e-16,5.215412572526979 4.227927251947357,9.44333982447434 9.443339824474336 9.44333982447434c 5.215412572526979,9.580557469767042e-16 9.44333982447434,-4.227927251947357 9.443339824474343 -9.443339824474336Z" /></g></g></g><g fill-opacity="0.0" stroke-width="0.1"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Curvature_diagramZero.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="200.0" font-size="1" viewBox="0 0 400 200"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(18.181818181818183,0.0,0.0,18.181818181818183,200.0,100.0)"><g fill-opacity="0.0"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" stroke-width="5.0e-2"><g><path d="M -0.6039999999999992,6.1981404958677544e-2 l -33.11407551269532,-29.72616679687502 " /><g><path d="M 10.781216498483047,-29.66418539191634 c 0.0,-24.57628035604107 -19.923011655137294,-44.49929201117837 -44.49929201117836 -44.49929201117837c -24.57628035604107,-1.5048631536486836e-15 -44.49929201117837,19.92301165513729 -44.49929201117837 44.499292011178355c -3.0097263072973672e-15,24.57628035604107 19.923011655137287,44.49929201117837 44.49929201117835 44.49929201117837c 24.57628035604107,4.514589460946051e-15 44.49929201117837,-19.923011655137284 44.49929201117839 -44.499292011178355Z" /></g></g></g><g fill-opacity="0.0" stroke-width="0.1"><path d="M -10.0,4.132231404958677 c 12.0,0.0 8.0,-10.0 20.0 -8.0" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Offset_cubicOffsetExample.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600.0" height="302.85875688987323" font-size="1" viewBox="0 0 600 303"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(13.155574898915939,0.0,0.0,13.155574898915939,72.35566194403765,151.42937844493662)"><g fill-opacity="0.0"><g fill-opacity="0.0"><g fill-opacity="0.0"><g fill-opacity="0.0" stroke-width="0.1"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 33.417476733497544,-1.6473872989404432 c 0.8062160672722944,1.9056016135526965 2.600074197059385,4.243483864433998 6.1181079451566704 6.588839696498854" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 32.86092310128323,-3.934973324746485 c 2.5438939233202618e-2,0.6274938344190009 0.18344919012734362,1.405702799055014 0.5565536322143174 2.287586025806042" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 33.000311673428904,-5.029283712603787 c -0.11129079091128213,0.22258158182256516 -0.16025559544153944,0.5795904798926212 -0.13938857214567424 1.094310387857302" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 32.97862528132407,-5.004468823346231 c 5.153156049894747e-3,-5.8414837533096176e-3 1.692390853525705e-2,-1.5289922118400412e-2 2.1686392104834695e-2 -2.4814889257555706e-2" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 32.70873785722833,-4.826371179429538 c 8.358937623750418e-2,-3.149744611848071e-2 0.18599518779940638,-8.299958544359143e-2 0.26988742409574185 -0.17809764391669347" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 32.05535699332027,-4.853120624705527 c 0.22391741974384205,0.10443579260780034 0.4091073150965916,0.11879455062523725 0.6533808639080556 2.6749445275989103e-2" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 31.72347357921467,-5.143549245977104 c 9.378804941573238e-2,0.1587182374727778 0.21780468092203975,0.23722193939149783 0.33188341410559863 0.29042862127157676" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 31.691808767395802,-5.205805672754547 c 5.879553721364061e-3,2.493597961259475e-2 2.2991427605793202e-2,4.75783919553141e-2 3.16648118188696e-2 6.225642677744325e-2" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 31.711972577462916,-5.04232626692882 c -3.953664939657209e-3,-6.508340746820274e-2 -9.44329551919676e-3,-0.11801225901966994 -2.0163810067113097e-2 -0.1634794058257274" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 31.661929314384686,-4.205360512837057 c 4.7781656372351655e-2,-0.35039881339724666 6.298412834573863e-2,-0.6239392027650261 5.004326307822682e-2 -0.8369657540917625" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 28.08645729142907,5.326289096396298 c 2.4270875082384364,-4.854175016476873 3.347932569058263,-7.86302694731943 3.5754720229556165 -9.531649609233355" /></g></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.1"><path d="M 28.980884482428987,5.773502691896256 c 10.0,-20.0 -5.0,-10.0 10.0 0.0" /></g></g></g><g fill-opacity="0.0"><g fill-opacity="0.0" stroke-width="0.1"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 22.22681744227194,-4.975977707743981 c 0.0,1.1652184940288226 4.6232805071259264e-2,5.8820192426981635 4.707106781186548 10.542893218813452" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 22.22527234029002,-5.190961309967571 c 1.3596945248055547e-3,5.336801009862491e-2 1.5451019819199274e-3,0.12796315263602231 1.5451019819199274e-3 0.21498360222359025" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 22.219061458808028,-5.310773112363485 c 2.6673527761378324e-3,3.11932088542779e-2 5.02539135926483e-3,7.328131507884272e-2 6.210881481992558e-3 0.1198118023959136" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 22.17283082599389,-5.555708087831505 c 1.5097180450167613e-2,4.906583646304519e-2 3.7738468810918135e-2,0.14562383531926137 4.623063281413753e-2 0.2449349754680199" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 21.98765210484117,-5.902700770832826 c 5.9159862296237264e-2,7.248909052964869e-2 0.13843512625198873,0.19507599957394817 0.1851787211527185 0.34699268300132147" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 21.651201254320615,-6.170110768106992 c 0.11662169140991807,5.7260927430492714e-2 0.231782074850714,0.13915844190093196 0.33645085052055723 0.26740999727416614" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 21.098403476790917,-6.26695624580832 c 0.20191976907307563,-2.2211174598037786e-2 0.37056518594124643,7.369780030821005e-3 0.5527977775296966 9.684547770132745e-2" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 20.68717773824717,-6.127488517764908 c 0.1437020759541605,-8.692183392465402e-2 0.28088371953770785,-0.12513010595274743 0.41122573854374966 -0.139467728043412" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 20.48926554076378,-5.97114444896771 c 6.721861761310333e-2,-6.819078770254983e-2 0.1366654818483104,-0.1192974443172492 0.19791219748339017 -0.15634406879719798" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 20.34021917756031,-5.779740302591861 c 4.9921581199019904e-2,-8.181592474283761e-2 0.10709836789040317,-0.14884946518015596 0.14904636320346842 -0.19140414637584868" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 20.208899018783505,-5.493502020830686 c 4.542742635734065e-2,-0.12492542248268634 0.10576723145080269,-0.244359873088003 0.13132015877680647 -0.2862382817611753" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 19.662024018783505,-3.911470770830686 c 0.30680648873951233,-0.8437178440336588 0.4701733778151218,-1.3711017889915862 0.546875 -1.58203125" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 15.332390251272024,5.826808696756061 c 2.472343200154557,-4.944686400309114 3.7115479674728395,-8.03854351748049 4.329633767511479 -9.738279467586747" /></g></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.1"><path d="M 16.22681744227194,6.274022292256019 c 10.0,-20.0 0.0,-10.0 10.0 0.0" /></g></g></g><g fill-opacity="0.0"><g fill-opacity="0.0"><g fill-opacity="0.0" stroke-width="0.1"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 13.009770219789226,-2.4104743608548738 c -0.2855399505357896,9.691052866669203e-2 -0.6461909532308479,0.16047436085487377 -1.0892105128500127 0.16047436085487377" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 13.893839526646092,-2.982120392131481 c -0.20403353302645844,0.23318118060166704 -0.4832891526977514,0.4356236759256369 -0.8840693068568655 0.5716460312766074" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 14.185013884508258,-4.851123441588392 c 0.2650946123717697,0.7069189663247197 0.17274121378843077,1.3388138247133696 -0.2911743578621664 1.8690030494569108" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 11.295559706939214,-6.75 c 1.352827876148151,0.0 2.551247208532007,0.9969913076461747 2.8894541775690445 1.898876558411608" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 9.203810396758112,-5.989978417355905 c 0.7131947941382997,-0.5593684659908238 1.4205071509921137,-0.7600215826440948 2.0917493101811013 -0.7600215826440948" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 7.49586988404493,-3.666654710493214 c 0.5144343791036887,-1.1224022816807757 1.1116643005702709,-1.8556560894957013 1.707940512713183 -2.3233237068626913" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 5.920559706939214,6.75 c 0.0,-5.2028660713222505 0.6810675710972038,-8.46557993374737 1.5753101771057156 -10.416654710493214" /></g></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.1"><path d="M 6.920559706939214,6.75 c 0.0,-20.0 10.0,-10.0 5.0 -10.0" /></g></g></g><g fill-opacity="0.0"><g fill-opacity="0.0" stroke-width="0.1"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 2.660826934705069,-8.569475230141833 c 0.4889565094920343,-0.9250528557957409 1.1220197779275782,-1.556458070895495 1.9677823889408277 -1.8947631153007976" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 1.7534960535105757,-5.761630493146541 c 0.21565993096084224,-1.0869260520426458 0.5083600089169344,-2.0530349786323434 0.9073308811944933 -2.8078447369952926" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 0.8835457044574557,1.0837838328712444 c 0.31486663625486244,-2.3929864355369546 0.4763670537345419,-4.86175451761215 0.86995034905312 -6.845414326017785" /></g><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -0.7828015282143159,7.11175903331599 c 0.9591837382060433,-1.6232340185025347 1.3712137747622197,-3.7849609203321535 1.6663472326717716 -6.027975200444746" /></g><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -5.0,9.46423834544263 c 2.0016683287913244,0.0 3.404020713214209,-0.9763323360826055 4.217198471785684 -2.3524793121266407" /></g></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.1"><path d="M -5.0,10.46423834544263 c 10.0,0.0 5.0,-18.0 10.0 -20.0" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Offset_expandLoopExample.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="300.0" font-size="1" viewBox="0 0 300 300"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(22.727272727272723,0.0,0.0,22.727272727272723,150.0,150.00000000000003)"><g><g fill="rgb(0,128,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M -5.000000000000001,5.999999999999998 h 5.0 c 0.2652164898395441,-1.2726212873067038e-16 0.5195704027385128,-0.10535684036541806 0.7071067811865477 -0.2928932188134526l 5.0,-5.0 c 0.1875363784480345,-0.1875363784480347 0.29289321881345226,-0.44189029134700364 0.2928932188134524 -0.7071067811865477v -5.0 c 0.0,-0.5522847498307935 -0.44771525016920644,-1.0 -0.9999999999999998 -1.0c -0.26521648983954393,9.478247619436096e-17 -0.5195704027385128,0.10535684036541801 -0.7071067811865476 0.2928932188134525l -10.0,10.0 c -0.39052429175127,0.39052429175126996 -0.3905242917512702,1.023689270621825 -2.220446049250313e-16 1.414213562373095c 0.18753637844803464,0.18753637844803456 0.4418902913470036,0.2928932188134523 0.7071067811865476 0.2928932188134526l 3.3306690738754696e-16,1.7763568394002505e-15 ZM -5.000000000000001,3.9999999999999982 l 2.6645352591003757e-15,7.771561172376096e-16 c -0.5522847498307935,0.0 -1.0,0.44771525016920644 -1.0 0.9999999999999997c -1.1102230246251565e-16,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999996 1.0c 0.26521648983954393,-5.551115123125783e-17 0.5195704027385128,-0.10535684036541795 0.7071067811865476 -0.29289321881345237l 10.0,-10.0 c 0.39052429175126996,-0.3905242917512699 0.39052429175127,-1.023689270621825 0.0 -1.414213562373095c -0.3905242917512699,-0.39052429175126996 -1.023689270621825,-0.39052429175127 -1.414213562373095 -1.1102230246251565e-16c -0.18753637844803453,0.18753637844803472 -0.2928932188134523,0.4418902913470036 -0.2928932188134525 0.7071067811865476v 5.0 c -1.1102230246251565e-16,0.5522847498307935 0.4477152501692063,1.0 0.9999999999999997 1.0000000000000002c 0.5522847498307935,1.1102230246251565e-16 1.0,-0.4477152501692063 1.0000000000000002 -0.9999999999999996c 1.1102230246251565e-16,-0.5522847498307935 -0.4477152501692062,-1.0 -0.9999999999999994 -1.0000000000000002c -0.26521648983954393,5.551115123125783e-17 -0.5195704027385128,0.10535684036541787 -0.7071067811865476 0.29289321881345226l -5.0,5.0 c -0.39052429175126985,0.3905242917512701 -0.3905242917512697,1.023689270621825 4.440892098500626e-16 1.414213562373095c 0.3905242917512701,0.39052429175126985 1.023689270621825,0.39052429175126974 1.414213562373095 -3.3306690738754696e-16c 0.3905242917512699,-0.3905242917512701 0.39052429175126974,-1.023689270621825 -2.220446049250313e-16 -1.4142135623730947c -0.18753637844803472,-0.18753637844803447 -0.44189029134700375,-0.2928932188134522 -0.7071067811865476 -0.2928932188134523l -5.000000000000001,-2.886579864025407e-15 Z" /></g><g stroke="rgb(255,255,255)" stroke-opacity="1.0" stroke-width="0.2"><path d="M -5.000000000000001,4.999999999999998 h 5.0 l 5.0,-5.0 v -5.0 l -10.0,10.0 Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Offset_expandTrailExample.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600.0" height="197.3830287816636" font-size="1" viewBox="0 0 600 197"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(12.98696646675048,0.0,0.0,12.98696646675048,300.0,98.6915143908318)"><g fill-opacity="0.0"><g fill-opacity="0.0"><g><g fill="rgb(0,0,0)" fill-opacity="1.0" font-weight="bold" font-family="Helvetica"><text transform="matrix(1.0,0.0,0.0,1.0,14.00005014902262,5.408430753773163)" dominant-baseline="middle" text-anchor="middle" stroke="none">LineCapSquare</text></g></g><g fill-opacity="0.0"><g fill="rgb(0,128,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M 9.000025074511312,-9.161939524945151e-2 h -2.0 v 4.0 h 2.0 h 10.0 c 1.104569499661587,-6.763537510981779e-17 2.0,-0.895430500338413 1.9999999999999998 -1.9999999999999998c 0.0,-0.4678730100377969 -0.16403243875498852,-0.9209387968686479 -0.4635574408052485 -1.28036879932896l -5.0,-6.0 l -1.2803687993289596,-1.536442559194752 l -3.072885118389502,2.5607375986579175 l 1.2803687993289596,1.536442559194752 l 5.0,6.0 c 0.7071281620285479,0.8485537944342576 1.9682575640894535,0.9632019218943404 2.8168113585237107 0.2560737598657927c 0.8485537944342576,-0.7071281620285479 0.9632019218943405,-1.9682575640894533 0.25607375986579295 -2.8168113585237107c -0.37998765062862305,-0.4559851807543475 -0.9428828741606051,-0.7196312006710406 -1.5364425591947515 -0.7196312006710406l -10.000000000000002,8.881784197001252e-16 Z" /></g><g stroke="rgb(255,255,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.2"><path d="M 9.000025074511312,1.9083806047505485 h 10.0 l -5.0,-6.0 " /></g></g></g><g fill-opacity="0.0"><g><g fill="rgb(0,0,0)" fill-opacity="1.0" font-weight="bold" font-family="Helvetica"><text transform="matrix(1.0,0.0,0.0,1.0,-0.9999999999999947,5.000050149022616)" dominant-baseline="middle" text-anchor="middle" stroke="none">LineCapRound</text></g></g><g fill-opacity="0.0"><g fill="rgb(0,128,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M -6.000025074511304,-0.4999999999999991 c -1.104569499661587,-6.763537510981779e-17 -2.0,0.8954305003384128 -2.0 1.9999999999999993c -1.3527075021963558e-16,1.104569499661587 0.8954305003384126,2.0 1.9999999999999991 2.0h 10.0 c 1.104569499661587,-6.763537510981779e-17 2.0,-0.895430500338413 1.9999999999999998 -1.9999999999999998c 0.0,-0.4678730100377969 -0.16403243875498852,-0.9209387968686479 -0.4635574408052485 -1.28036879932896l -5.0,-6.0 c -0.7071281620285479,-0.8485537944342575 -1.9682575640894537,-0.9632019218943401 -2.8168113585237107 -0.2560737598657923c -0.848553794434257,0.7071281620285474 -0.9632019218943398,1.9682575640894528 -0.2560737598657927 2.8168113585237107l 5.0,6.0 c 0.7071281620285479,0.8485537944342576 1.9682575640894535,0.9632019218943404 2.8168113585237107 0.2560737598657927c 0.8485537944342576,-0.7071281620285479 0.9632019218943405,-1.9682575640894533 0.25607375986579295 -2.8168113585237107c -0.37998765062862305,-0.4559851807543475 -0.9428828741606051,-0.7196312006710406 -1.5364425591947515 -0.7196312006710406h -10.000000000000004 Z" /></g><g stroke="rgb(255,255,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.2"><path d="M -6.000025074511304,1.5000000000000009 h 10.0 l -5.0,-6.0 " /></g></g></g><g><g fill="rgb(0,0,0)" fill-opacity="1.0" font-weight="bold" font-family="Helvetica"><text transform="matrix(1.0,0.0,0.0,1.0,-15.000050149022613,4.640209474175787)" dominant-baseline="middle" text-anchor="middle" stroke="none">LineCapButt</text></g></g><g fill-opacity="0.0"><g fill="rgb(0,128,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M -21.000075223533923,-0.8598406748468275 v 4.0 h 10.0 c 1.104569499661587,-6.763537510981779e-17 2.0,-0.895430500338413 1.9999999999999998 -1.9999999999999998c 0.0,-0.4678730100377969 -0.16403243875498852,-0.9209387968686479 -0.4635574408052485 -1.28036879932896l -5.0,-6.0 l -3.072885118389502,2.5607375986579175 l 5.0,6.0 c 0.7071281620285479,0.8485537944342576 1.9682575640894535,0.9632019218943404 2.8168113585237107 0.2560737598657927c 0.8485537944342576,-0.7071281620285479 0.9632019218943405,-1.9682575640894533 0.25607375986579295 -2.8168113585237107c -0.37998765062862305,-0.4559851807543475 -0.9428828741606051,-0.7196312006710406 -1.5364425591947515 -0.7196312006710406l -10.000000000000002,8.881784197001252e-16 Z" /></g><g stroke="rgb(255,255,255)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="0.2"><path d="M -21.000075223533923,1.1401593251531725 h 10.0 l -5.0,-6.0 " /></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Offset_offsetTrailExample.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600.0" height="185.1008379753402" font-size="1" viewBox="0 0 600 185"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(13.702641330909062,0.0,0.0,13.702641330909062,300.0,92.5504189876701)"><g fill-opacity="0.0" stroke-width="0.2"><g fill-opacity="0.0"><g><g fill="rgb(0,0,0)" fill-opacity="1.0" font-weight="bold" font-family="Helvetica"><text transform="matrix(1.0,0.0,0.0,1.0,14.135041612651108,4.64018439966448)" dominant-baseline="middle" text-anchor="middle" stroke="none">LineJoinBevel</text></g></g><g fill-opacity="0.0"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 8.366820333053731,3.14018439966448 h 10.0 l 1.536442559194752,-3.2803687993289596 l -5.0,-6.0 " /></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M 8.366820333053731,1.1401843996644798 h 10.0 l -5.0,-6.0 " /></g></g></g><g fill-opacity="0.0"><g><g fill="rgb(0,0,0)" fill-opacity="1.0" font-weight="bold" font-family="Helvetica"><text transform="matrix(1.0,0.0,0.0,1.0,1.366820333053731,4.64018439966448)" dominant-baseline="middle" text-anchor="middle" stroke="none">LineJoinRound</text></g></g><g fill-opacity="0.0"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -4.633179666946269,3.14018439966448 h 10.0 c 1.104569499661587,-6.763537510981779e-17 2.0,-0.895430500338413 1.9999999999999998 -1.9999999999999998c 0.0,-0.4678730100377969 -0.16403243875498852,-0.9209387968686479 -0.4635574408052485 -1.28036879932896l -5.0,-6.0 " /></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -4.633179666946269,1.1401843996644798 h 10.0 l -5.0,-6.0 " /></g></g></g><g><g fill="rgb(0,0,0)" fill-opacity="1.0" font-weight="bold" font-family="Helvetica"><text transform="matrix(1.0,0.0,0.0,1.0,-12.768221279597377,4.64018439966448)" dominant-baseline="middle" text-anchor="middle" stroke="none">LineJoinMiter</text></g></g><g fill-opacity="0.0"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -19.903262892248485,3.14018439966448 h 10.0 h 4.270083225302217 l -2.7336406661074655,-3.2803687993289596 l -5.0,-6.0 " /></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -19.903262892248485,1.1401843996644798 h 10.0 l -5.0,-6.0 " /></g></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Offset_offsetTrailLeftExample.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200.0" height="154.67216693398285" font-size="1" viewBox="0 0 200 155"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(15.151451832306767,0.0,0.0,15.151451832306767,100.0,77.33608346699143)"><g fill-opacity="0.0" stroke-width="0.2"><g stroke="rgb(0,128,0)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -6.000025074511308,-4.64018439966448 h 10.0 c 0.4678730100377967,1.6653345369377348e-16 0.9209387968686479,0.16403243875498819 1.28036879932896 0.46355744080524836c 0.8485537944342573,0.7071281620285479 0.9632019218943395,1.9682575640894537 0.2560737598657916 2.816811358523711l -5.0,6.0 " /></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0" fill-opacity="0.0"><path d="M -6.000025074511308,-2.64018439966448 h 10.0 l -5.0,6.0 " /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Offset_offsetTrailOuterExample.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="271.2911579538083" font-size="1" viewBox="0 0 300 271"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(19.48051948051948,0.0,0.0,19.48051948051948,150.0,135.64557897690415)"><g stroke-width="0.2"><g stroke="rgb(0,128,0)" stroke-opacity="1.0"><path d="M 4.232050807568877,5.330127018922195 l 2.500000000000001,-4.330127018922193 c 0.35726558990816415,-0.6188021535170062 0.35726558990816465,-1.3811978464829942 1.1102230246251565e-15 -2.0000000000000004l -2.4999999999999982,-4.330127018922194 c -0.35726558990816315,-0.6188021535170058 -1.0175196277525493,-0.9999999999999999 -1.7320508075688763 -1.0000000000000004l -5.0,-2.220446049250313e-15 c -0.714531179816327,-3.61068003170518e-16 -1.3747852176607136,0.381197846482993 -1.7320508075688776 0.9999999999999987l -2.5000000000000013,4.330127018922193 c -0.35726558990816415,0.6188021535170058 -0.357265589908165,1.381197846482994 -1.4432899320127035e-15 2.0l 2.4999999999999964,4.3301270189221945 c 0.35726558990816343,0.6188021535170066 1.0175196277525498,1.0000000000000009 1.7320508075688772 1.000000000000001h 5.000000000000002 c 0.714531179816327,2.735631709452133e-16 1.3747852176607136,-0.3811978464829932 1.7320508075688776 -0.9999999999999989l 8.881784197001252e-16,6.661338147750939e-16 Z" /></g><g stroke="rgb(0,0,255)" stroke-opacity="1.0"><path d="M 2.4999999999999996,4.3301270189221945 l 2.500000000000001,-4.330127018922193 l -2.4999999999999982,-4.330127018922194 l -5.0,-2.220446049250313e-15 l -2.5000000000000013,4.330127018922193 l 2.4999999999999964,4.3301270189221945 h 5.000000000000002 Z" /></g></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_decagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="95.10565162951534" font-size="1" viewBox="0 0 100 95"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(28.092454034086124,0.0,0.0,28.092454034086124,49.99999999999999,47.55282581475767)"><path d="M 1.3090169943749481,0.9510565162951532 l 0.3090169943749472,-0.9510565162951536 l -0.3090169943749477,-0.9510565162951534 l -0.8090169943749475,-0.5877852522924729 l -1.0,4.440892098500626e-16 l -0.8090169943749473,0.5877852522924731 l -0.3090169943749473,0.9510565162951536 l 0.3090169943749475,0.9510565162951535 l 0.8090169943749475,0.587785252292473 l 1.0,-5.551115123125783e-17 l 0.8090169943749477,-0.5877852522924736 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_dodecagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="99.99999999999999" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(24.35901749373842,0.0,0.0,24.35901749373842,50.0,49.99999999999999)"><path d="M 1.8660254037844393,0.4999999999999996 l -2.220446049250313e-16,-1.0 l -0.5000000000000001,-0.8660254037844386 l -0.8660254037844387,-0.49999999999999994 l -1.0,1.6081226496766364e-16 l -0.8660254037844386,0.49999999999999994 l -0.5000000000000001,0.8660254037844386 l -3.4450928483976665e-16,1.0 l 0.49999999999999956,0.8660254037844389 l 0.8660254037844385,0.5000000000000002 l 1.0,-3.834758505292834e-17 l 0.8660254037844385,-0.5000000000000003 l 0.5000000000000021,-0.8660254037844389 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_hendecagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="98.98214418809323" font-size="1" viewBox="0 0 100 99"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(25.875425140597297,0.0,0.0,25.875425140597297,50.00000000000001,50.5141613269018)"><path d="M 1.7566685458330673,0.2525708066345108 l -0.1423148382732844,-0.9898214418809328 l -0.6548607339452844,-0.7557495743542588 l -0.9594929736144971,-0.28173255684143045 l -0.9594929736144977,0.28173255684142884 l -0.6548607339452855,0.7557495743542577 l -0.14231483827328584,0.9898214418809326 l 0.4154150130018858,0.9096319953545187 l 0.841253532831181,0.5406408174555977 l 0.9999999999999999,-2.7755575615628914e-17 l 0.8412535328311814,-0.5406408174555973 l 0.41541501300188677,-0.9096319953545157 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_heptagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="97.49279121818235" font-size="1" viewBox="0 0 100 97"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(40.45835162842079,0.0,0.0,40.45835162842079,50.0,51.28584316362768)"><path d="M 1.1234898018587336,0.2564292158181373 l -0.22252093395631548,-0.9749279121818234 l -0.9009688679024197,-0.4338837391175572 l -0.9009688679024187,0.43388373911755906 l -0.22252093395631345,0.9749279121818237 l 0.6234898018587343,0.7818314824680291 l 1.0,-2.7755575615628914e-17 l 0.6234898018587329,-0.7818314824680312 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_hexagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="86.6025403784439" font-size="1" viewBox="0 0 100 87"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,50.0,43.30127018922196)"><path d="M 0.49999999999999967,0.8660254037844387 l 0.5000000000000002,-0.8660254037844385 l -0.4999999999999996,-0.8660254037844388 l -0.9999999999999999,-4.440892098500626e-16 l -0.5000000000000003,0.8660254037844384 l 0.49999999999999933,0.866025403784439 l 1.0000000000000002,2.220446049250313e-16 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_hruleEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="48.00000000000001" font-size="1" viewBox="0 0 300 48"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,24.000000000000004)"><g fill-opacity="0.0"><g fill-opacity="0.0"><path d="M -2.5,0.4 h 5.0 " /></g><g fill-opacity="0.0"><g fill-opacity="0.0"><path d="M -2.0,0.2 h 4.0 " /></g><path d="M -1.5,0.0 h 3.0 " /></g><g fill-opacity="0.0"><path d="M -1.0,-0.2 h 2.0 " /></g><path d="M -0.5,-0.4 h 1.0 " /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_nonagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="98.48077530122075" font-size="1" viewBox="0 0 100 98"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(31.572395939441876,0.0,0.0,31.572395939441876,50.0,50.771330594287235)"><path d="M 1.266044443118978,0.7309511000407727 l 0.1736481776669308,-0.984807753012208 l -0.49999999999999956,-0.8660254037844388 l -0.9396926207859082,-0.3420201433256692 l -0.9396926207859086,0.3420201433256681 l -0.5000000000000006,0.8660254037844384 l 0.17364817766692983,0.9848077530122082 l 0.766044443118978,0.6427876096865394 l 1.0,-2.7755575615628914e-17 l 0.7660444431189786,-0.6427876096865375 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_octagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="99.99999999999999" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(37.65577839755409,0.0,0.0,37.65577839755409,50.00000000000001,50.00000000000001)"><path d="M 1.2071067811865475,0.4999999999999996 l -2.220446049250313e-16,-1.0 l -0.7071067811865476,-0.7071067811865475 l -1.0,1.6081226496766364e-16 l -0.7071067811865475,0.7071067811865476 l 9.957992501029599e-17,1.0 l 0.7071067811865476,0.7071067811865476 l 1.0,-3.834758505292834e-17 l 0.7071067811865477,-0.7071067811865477 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_pentagonEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="95.10565162951538" font-size="1" viewBox="0 0 100 95"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(56.18490806817227,0.0,0.0,56.18490806817227,50.00000000000001,52.573111211913364)"><path d="M 0.5000000000000001,0.6881909602355868 l 0.3090169943749472,-0.9510565162951536 l -0.8090169943749475,-0.5877852522924729 l -0.8090169943749473,0.5877852522924731 l 0.3090169943749479,0.9510565162951533 l 0.9999999999999996,1.1102230246251565e-16 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_rectEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="150.0" height="104.99999999999999" font-size="1" viewBox="0 0 150 105"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(136.36363636363635,0.0,0.0,136.36363636363635,74.99999999999999,52.49999999999999)"><path d="M 0.5000000000000001,0.35 l -1.1102230246251565e-16,-0.7 h -1.0 l -1.1102230246251565e-16,0.7 h 1.0 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_roundedRectEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400.0" height="76.19047619047622" font-size="1" viewBox="0 0 400 76"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(173.1601731601732,0.0,0.0,173.1601731601732,199.99999999999997,38.09523809523811)"><g><g><path d="M 1.0499999999999998,0.10000000000000003 v -0.1 c -0.11045694996615868,-4.4408920985006264e-17 -0.19999999999999996,-8.954305003384136e-2 -0.19999999999999996 -0.20000000000000007h -0.29999999999999993 c -0.1104569499661587,-6.763537510981779e-18 -0.2,8.954305003384128e-2 -0.2 0.19999999999999996v 0.2 h 0.6 c 5.522847498307935e-2,1.014530626647267e-17 0.1,-4.477152501692063e-2 9.999999999999992e-2 -9.999999999999992e-2Z" /></g><g><path d="M 0.15000000000000013,0.10000000000000003 v -0.20000000000000004 c -5.522847498307934e-2,-2.2204460492503132e-17 -9.999999999999998e-2,-4.477152501692068e-2 -9.999999999999998e-2 -0.10000000000000003h -0.3 c -2.2204460492503132e-17,5.5228474983079326e-2 -4.477152501692068e-2,9.999999999999998e-2 -0.10000000000000003 9.999999999999996e-2v 0.2 c 5.522847498307934e-2,2.2204460492503132e-17 9.999999999999998e-2,4.477152501692068e-2 9.999999999999996e-2 0.10000000000000003h 0.30000000000000004 c 0.0,-5.522847498307934e-2 4.477152501692068e-2,-9.999999999999998e-2 9.999999999999998e-2 -9.999999999999998e-2Z" /></g><path d="M -0.5499999999999998,0.10000000000000003 v -0.20000000000000004 c 0.0,-5.522847498307935e-2 -4.4771525016920645e-2,-0.1 -9.999999999999998e-2 -0.1h -0.3 c -5.522847498307935e-2,-3.3817687554908897e-18 -0.1,4.477152501692064e-2 -0.1 9.999999999999998e-2v 0.2 c -6.763537510981779e-18,5.522847498307935e-2 4.477152501692064e-2,0.1 9.999999999999998e-2 0.10000000000000003h 0.30000000000000004 c 5.522847498307935e-2,1.014530626647267e-17 0.1,-4.477152501692063e-2 9.999999999999998e-2 -9.999999999999998e-2Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_squareEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200.0" height="85.71428571428572" font-size="1" viewBox="0 0 200 86"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="3.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(25.974025974025974,0.0,0.0,25.974025974025974,100.0,42.85714285714286)"><g><g><path d="M 3.5000000000000004,1.5 l -3.3306690738754696e-16,-3.0 h -3.0 l -3.3306690738754696e-16,3.0 h 3.000000000000001 Z" /></g><g><path d="M 2.220446049250313e-16,1.0 l -2.220446049250313e-16,-2.0 h -2.0 l -2.220446049250313e-16,2.0 h 2.0 Z" /></g><path d="M -2.5,0.5 l -1.1102230246251565e-16,-1.0 h -1.0 l -1.1102230246251565e-16,1.0 h 1.0 Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_triangleEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="86.60254037844385" font-size="1" viewBox="0 0 100 87"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(90.9090909090909,0.0,0.0,90.9090909090909,50.0,57.73502691896257)"><path d="M 0.5,0.28867513459481275 l -0.5000000000000002,-0.8660254037844385 l -0.4999999999999999,0.8660254037844386 l 1.0,-1.1102230246251565e-16 Z" /></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_unitSquareEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(90.9090909090909,0.0,0.0,90.9090909090909,49.99999999999999,50.0)"><path d="M 0.5000000000000001,0.5 l -1.1102230246251565e-16,-1.0 h -1.0 l -1.1102230246251565e-16,1.0 h 1.0 Z" /><g fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0"><path d="M 2.2000000000000002e-2,0.0 c 0.0,-1.2150264496277458e-2 -9.849735503722543e-3,-2.2000000000000002e-2 -2.2e-2 -2.2000000000000002e-2c -1.2150264496277458e-2,-7.439891262079958e-19 -2.2000000000000002e-2,9.849735503722541e-3 -2.2000000000000002e-2 2.1999999999999995e-2c -1.4879782524159916e-18,1.2150264496277458e-2 9.84973550372254e-3,2.2000000000000002e-2 2.1999999999999992e-2 2.2000000000000002e-2c 1.2150264496277458e-2,2.2319673786239874e-18 2.2000000000000002e-2,-9.84973550372254e-3 2.2000000000000006e-2 -2.1999999999999995e-2Z" /></g></g></g></g></svg>
+ diagrams/src_Diagrams_TwoD_Shapes_vruleEx.svg view
@@ -0,0 +1,4 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="50.00000000000001" height="100.0" font-size="1" viewBox="0 0 50 100"><g><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill-opacity="0.0" stroke-width="1.0e-2" stroke-linecap="butt" stroke-linejoin="miter" font-size="1.0em" stroke-miterlimit="10.0"><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g fill-opacity="0.0"><g fill-opacity="0.0"><g fill-opacity="0.0"><path d="M 0.5,-0.9999999999999999 v 1.9999999999999998 " /></g><path d="M 0.30000000000000004,-0.8999999999999999 v 1.7999999999999998 " /></g><g fill-opacity="0.0"><g fill-opacity="0.0"><path d="M 0.10000000000000003,-0.7999999999999999 v 1.5999999999999999 " /></g><path d="M -9.999999999999998e-2,-0.7 v 1.4 " /></g><g fill-opacity="0.0"><path d="M -0.3,-0.6 v 1.2 " /></g><path d="M -0.5,-0.5 v 1.0 " /></g></g></g></g></svg>
− diagrams/trailOffsetEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300.0" height="90.00000000000001" font-size="1" viewBox="0 0 300 90"><g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,45.00000000000001)"><g stroke="rgb(255,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="5.0e-2" font-size="1.0em"><path d="M 0.5,-0.75 h -2.0 " /></g></g><g transform="matrix(54.54545454545455,0.0,0.0,54.54545454545455,150.0,45.00000000000001)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.5,-0.75 l 2.0,1.0 l -3.0,0.5 l -2.0,-1.0 l 1.0,-0.5 " /></g></g></g></svg>
− diagrams/triangleEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="86.60254037844385" font-size="1" viewBox="0 0 100 87"><g><g transform="matrix(90.9090909090909,0.0,0.0,90.9090909090909,50.0,57.73502691896257)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.5,0.28867513459481275 l -0.5000000000000002,-0.8660254037844385 l -0.4999999999999999,0.8660254037844386 l 1.0,-1.1102230246251565e-16 Z" /></g></g></g></svg>
− diagrams/unitSquareEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100.0" height="100.0" font-size="1" viewBox="0 0 100 100"><g><g transform="matrix(90.9090909090909,0.0,0.0,90.9090909090909,49.99999999999999,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.5000000000000001,0.5 l -1.1102230246251565e-16,-1.0 h -1.0 l -1.1102230246251565e-16,1.0 h 1.0 Z" /></g></g><g transform="matrix(90.9090909090909,0.0,0.0,90.9090909090909,49.99999999999999,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(255,0,0)" fill-opacity="1.0" stroke-width="0.0" font-size="1.0em"><path d="M 2.2000000000000002e-2,0.0 c 0.0,-1.2150264496277458e-2 -9.849735503722543e-3,-2.2000000000000002e-2 -2.2e-2 -2.2000000000000002e-2c -1.2150264496277458e-2,-7.439891262079958e-19 -2.2000000000000002e-2,9.849735503722541e-3 -2.2000000000000002e-2 2.1999999999999995e-2c -1.4879782524159916e-18,1.2150264496277458e-2 9.84973550372254e-3,2.2000000000000002e-2 2.1999999999999992e-2 2.2000000000000002e-2c 1.2150264496277458e-2,2.2319673786239874e-18 2.2000000000000002e-2,-9.84973550372254e-3 2.2000000000000006e-2 -2.1999999999999995e-2Z" /></g></g></g></svg>
− diagrams/vruleEx.svg
@@ -1,4 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="50.00000000000001" height="100.0" font-size="1" viewBox="0 0 50 100"><g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.5000000000000001,-0.9999999999999999 v 1.9999999999999998 " /></g></g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.3000000000000001,-0.8999999999999999 v 1.7999999999999998 " /></g></g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M 0.10000000000000003,-0.7999999999999999 v 1.5999999999999999 " /></g></g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -9.999999999999998e-2,-0.7 v 1.4 " /></g></g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -0.3,-0.6 v 1.2 " /></g></g><g transform="matrix(45.45454545454546,0.0,0.0,45.45454545454546,25.000000000000004,50.0)"><g stroke="rgb(0,0,0)" stroke-opacity="1.0" fill="rgb(0,0,0)" fill-opacity="0.0" stroke-width="1.0e-2" font-size="1.0em"><path d="M -0.5,-0.5 v 1.0 " /></g></g></g></svg>
src/Diagrams/Align.hs view
@@ -21,69 +21,134 @@ ( -- * Alignable class Alignable(..)- , alignByDefault+ , alignBy'Default+ , envelopeBoundary+ , traceBoundary -- * General alignment functions , align+ , snug , center+ , snugBy+ , snugCenter ) where import Diagrams.Core -import Data.AffineSpace (alerp)+import Data.AffineSpace (alerp, (.-.)) import Data.VectorSpace+import Data.Maybe (fromMaybe)+import Data.Ord (comparing) import qualified Data.Map as M import qualified Data.Set as S+import qualified Data.Foldable as F -- | Class of things which can be aligned. class Alignable a where -- | @alignBy v d a@ moves the origin of @a@ along the vector -- @v@. If @d = 1@, the origin is moved to the edge of the- -- envelope in the direction of @v@; if @d = -1@, it moves to the- -- edge of the envelope in the direction of the negation of @v@.+ -- boundary in the direction of @v@; if @d = -1@, it moves to the+ -- edge of the boundary in the direction of the negation of @v@. -- Other values of @d@ interpolate linearly (so for example, @d = -- 0@ centers the origin along the direction of @v@).- alignBy :: V a -> Scalar (V a) -> a -> a+ alignBy' :: ( HasOrigin a, AdditiveGroup (V a), Num (Scalar (V a))+ , Fractional (Scalar (V a)))+ => (V a -> a -> Point (V a)) -> V a -> Scalar (V a) -> a -> a+ alignBy' = alignBy'Default + defaultBoundary :: V a -> a -> Point (V a)++ alignBy :: (HasOrigin a, Num (Scalar (V a)), Fractional (Scalar (V a)))+ => V a -> Scalar (V a) -> a -> a+ alignBy = alignBy' defaultBoundary+ -- | Default implementation of 'alignBy' for types with 'HasOrigin'--- and 'Enveloped' instances.-alignByDefault :: (HasOrigin a, Enveloped a, Num (Scalar (V a)))- => V a -> Scalar (V a) -> a -> a-alignByDefault v d a = moveOriginTo (alerp (envelopeP (negateV v) a)- (envelopeP v a)- ((d + 1) / 2))- a+-- and 'AdditiveGroup' instances.+alignBy'Default :: ( HasOrigin a, AdditiveGroup (V a), Num (Scalar (V a))+ , Fractional (Scalar (V a)))+ => (V a -> a -> Point (V a)) -> V a -> Scalar (V a) -> a -> a+alignBy'Default boundary v d a = moveOriginTo (alerp (boundary (negateV v) a)+ (boundary v a)+ ((d + 1) / 2)) a +-- | Some standard functions which can be used as the `boundary` argument to+-- `alignBy'`.+envelopeBoundary :: Enveloped a => V a -> a -> Point (V a)+envelopeBoundary = envelopeP++traceBoundary :: Traced a => V a -> a -> Point (V a)+traceBoundary v a = fromMaybe origin (maxTraceP origin v a)++combineBoundaries+ :: (F.Foldable f, InnerSpace (V a), Ord (Scalar (V a)))+ => (V a -> a -> Point (V a)) -> (V a -> f a -> Point (V a))+combineBoundaries b v fa+ = b v $ F.maximumBy (comparing (magnitudeSq . (.-. origin) . b v)) fa+ instance (InnerSpace v, OrderedField (Scalar v)) => Alignable (Envelope v) where- alignBy = alignByDefault+ defaultBoundary = envelopeBoundary -instance (Enveloped b, HasOrigin b) => Alignable [b] where- alignBy = alignByDefault+instance (InnerSpace v, OrderedField (Scalar v)) => Alignable (Trace v) where+ defaultBoundary = traceBoundary -instance (Enveloped b, HasOrigin b, Ord b) => Alignable (S.Set b) where- alignBy = alignByDefault+instance (InnerSpace (V b), Ord (Scalar (V b)), Alignable b)+ => Alignable [b] where+ defaultBoundary = combineBoundaries defaultBoundary -instance (Enveloped b, HasOrigin b) => Alignable (M.Map k b) where- alignBy = alignByDefault+instance (InnerSpace (V b), Ord (Scalar (V b)), Alignable b)+ => Alignable (S.Set b) where+ defaultBoundary = combineBoundaries defaultBoundary +instance (InnerSpace (V b), Ord (Scalar (V b)), Alignable b)+ => Alignable (M.Map k b) where+ defaultBoundary = combineBoundaries defaultBoundary+ instance ( HasLinearMap v, InnerSpace v, OrderedField (Scalar v) , Monoid' m ) => Alignable (QDiagram b v m) where- alignBy = alignByDefault+ defaultBoundary = envelopeBoundary +-- | Although the 'alignBy' method for the @(b -> a)@ instance is+-- sensible, there is no good implementation for+-- 'defaultBoundary'. Instead, we provide a total method, but one that+-- is not sensible. This should not present a serious problem as long+-- as your use of 'Alignable' happens through 'alignBy'.+instance (HasOrigin a, Alignable a) => Alignable (b -> a) where+ alignBy v d f b = alignBy v d (f b)+ defaultBoundary _ _ = origin+ -- | @align v@ aligns an enveloped object along the edge in the -- direction of @v@. That is, it moves the local origin in the -- direction of @v@ until it is on the edge of the envelope. (Note -- that if the local origin is outside the envelope to begin with, -- it may have to move \"backwards\".)-align :: (Alignable a, Num (Scalar (V a))) => V a -> a -> a+align :: ( Alignable a, HasOrigin a, Num (Scalar (V a))+ , Fractional (Scalar (V a))) => V a -> a -> a align v = alignBy v 1 +-- | Version of @alignBy@ specialized to use @traceBoundary@+snugBy :: (Alignable a, Traced a, HasOrigin a, Num (Scalar (V a)), Fractional (Scalar (V a)))+ => V a -> Scalar (V a) -> a -> a+snugBy = alignBy' traceBoundary++-- | Like align but uses trace.+snug :: (Fractional (Scalar (V a)), Alignable a, Traced a, HasOrigin a)+ => V a -> a -> a+snug v = snugBy v 1+ -- | @center v@ centers an enveloped object along the direction of -- @v@.-center :: (Alignable a, Num (Scalar (V a))) => V a -> a -> a+center :: ( Alignable a, HasOrigin a, Num (Scalar (V a))+ , Fractional (Scalar (V a))) => V a -> a -> a center v = alignBy v 0++-- | Like @center@ using trace.+snugCenter+ :: (Fractional (Scalar (V a)), Alignable a, Traced a, HasOrigin a)+ => V a -> a -> a+snugCenter v = (alignBy' traceBoundary) v 0+
src/Diagrams/Animation.hs view
@@ -109,7 +109,8 @@ -- -- Uses 30 samples per time unit by default; to adjust this number -- see 'animRect''.-animRect :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ R2)+animRect :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ R2+ , Monoid' m) => QAnimation b R2 m -> t animRect = animRect' 30 @@ -117,7 +118,8 @@ -- parameter is the number of samples per time unit to use. Lower -- rates will be faster but less accurate; higher rates are more -- accurate but slower.-animRect' :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ R2)+animRect' :: (TrailLike t, Enveloped t, Transformable t, Monoid t, V t ~ R2+ , Monoid' m) => Rational -> QAnimation b R2 m -> t animRect' r anim | null results = rect 1 1
src/Diagrams/Animation/Active.hs view
@@ -39,9 +39,7 @@ import Control.Applicative (pure, (<$>)) -import Diagrams.Align import Diagrams.Core-import Diagrams.Path import Diagrams.TrailLike import Data.Active@@ -97,5 +95,5 @@ ) a1 -instance Alignable a => Alignable (Active a) where- alignBy v d a = alignBy v d <$> a+--instance Alignable a => Alignable (Active a) where+-- alignBy v d a = alignBy v d <$> a
src/Diagrams/Attributes.hs view
@@ -1,7 +1,6 @@-{-# LANGUAGE DeriveDataTypeable- , ExistentialQuantification- , GeneralizedNewtypeDeriving- #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.Attributes@@ -26,13 +25,13 @@ -- * Color -- $color - Color(..), SomeColor(..)+ Color(..), SomeColor(..), someToAlpha -- ** Line color- , LineColor, getLineColor, lineColor, lineColorA, lc, lcA+ , LineColor, getLineColor, mkLineColor, styleLineColor, lineColor, lineColorA, lc, lcA -- ** Fill color- , FillColor, getFillColor, recommendFillColor, fillColor, fc, fcA+ , FillColor, getFillColor, mkFillColor, styleFillColor, recommendFillColor, fillColor, fc, fcA -- ** Opacity , Opacity, getOpacity, opacity@@ -58,19 +57,19 @@ ) where -import Diagrams.Core--import Data.Default.Class-+import Control.Lens (Setter, sets) import Data.Colour import Data.Colour.RGBSpace-import Data.Colour.SRGB (sRGBSpace)--import Data.Typeable-+import Data.Colour.SRGB (sRGBSpace)+import Data.Default.Class+import Data.Maybe (fromMaybe) import Data.Monoid.Recommend import Data.Semigroup+import Data.Typeable +import Diagrams.Core+import Diagrams.Core.Style (setAttr)+ ------------------------------------------------------------ -- Color ------------------------------------------------- ------------------------------------------------------------@@ -88,13 +87,21 @@ -- both the 'Data.Colour.Colour' and 'Data.Colour.AlphaColour' types -- from the "Data.Colour" library. class Color c where- -- | Convert a color to its standard representation, AlphaColour+ -- | Convert a color to its standard representation, AlphaColour. toAlphaColour :: c -> AlphaColour Double + -- | Convert from an AlphaColour Double. Note that this direction+ -- may lose some information. For example, the instance for+ -- 'Colour' drops the alpha channel.+ fromAlphaColour :: AlphaColour Double -> c+ -- | An existential wrapper for instances of the 'Color' class. data SomeColor = forall c. Color c => SomeColor c deriving Typeable +someToAlpha :: SomeColor -> AlphaColour Double+someToAlpha (SomeColor c) = toAlphaColour c+ -- | The color with which lines (strokes) are drawn. Note that child -- colors always override parent colors; that is, @'lineColor' c1 -- . 'lineColor' c2 $ d@ is equivalent to @'lineColor' c2 $ d@.@@ -105,18 +112,33 @@ instance AttributeClass LineColor instance Default LineColor where- def = LineColor (Last (SomeColor black))+ def = LineColor (Last (SomeColor (black :: Colour Double))) getLineColor :: LineColor -> SomeColor getLineColor (LineColor (Last c)) = c +mkLineColor :: Color c => c -> LineColor+mkLineColor = LineColor . Last . SomeColor++styleLineColor :: (Color c, Color c') => Setter (Style v) (Style v) c c'+styleLineColor = sets modifyLineColor+ where+ modifyLineColor f s+ = flip setAttr s+ . mkLineColor+ . f+ . fromAlphaColour . someToAlpha+ . getLineColor+ . fromMaybe def . getAttr+ $ s+ -- | Set the line (stroke) color. This function is polymorphic in the -- color type (so it can be used with either 'Colour' or -- 'AlphaColour'), but this can sometimes create problems for type -- inference, so the 'lc' and 'lcA' variants are provided with more -- concrete types. lineColor :: (Color c, HasStyle a) => c -> a -> a-lineColor = applyAttr . LineColor . Last . SomeColor+lineColor = applyAttr . mkLineColor -- | Apply a 'lineColor' attribute. lineColorA :: HasStyle a => LineColor -> a -> a@@ -141,12 +163,30 @@ deriving (Typeable, Semigroup) instance AttributeClass FillColor +instance Default FillColor where+ def = FillColor (Recommend (Last (SomeColor (transparent :: AlphaColour Double))))++mkFillColor :: Color c => c -> FillColor+mkFillColor = FillColor . Commit . Last . SomeColor++styleFillColor :: (Color c, Color c') => Setter (Style v) (Style v) c c'+styleFillColor = sets modifyFillColor+ where+ modifyFillColor f s+ = flip setAttr s+ . mkFillColor+ . f+ . fromAlphaColour . someToAlpha+ . getFillColor+ . fromMaybe def . getAttr+ $ s+ -- | Set the fill color. This function is polymorphic in the color -- type (so it can be used with either 'Colour' or 'AlphaColour'), -- but this can sometimes create problems for type inference, so the -- 'fc' and 'fcA' variants are provided with more concrete types. fillColor :: (Color c, HasStyle a) => c -> a -> a-fillColor = applyAttr . FillColor . Commit . Last . SomeColor+fillColor = applyAttr . mkFillColor -- | Set a \"recommended\" fill color, to be used only if no explicit -- calls to 'fillColor' (or 'fc', or 'fcA') are used.@@ -167,19 +207,24 @@ fcA = fillColor instance (Floating a, Real a) => Color (Colour a) where- toAlphaColour = opaque . colourConvert+ toAlphaColour = opaque . colourConvert+ fromAlphaColour = colourConvert . (`over` black) instance (Floating a, Real a) => Color (AlphaColour a) where- toAlphaColour = alphaColourConvert+ toAlphaColour = alphaColourConvert+ fromAlphaColour = alphaColourConvert instance Color SomeColor where toAlphaColour (SomeColor c) = toAlphaColour c+ fromAlphaColour c = SomeColor c instance Color LineColor where- toAlphaColour (LineColor (Last c)) = toAlphaColour c+ toAlphaColour (LineColor c) = toAlphaColour . getLast $ c+ fromAlphaColour = LineColor . Last . fromAlphaColour instance Color FillColor where toAlphaColour (FillColor c) = toAlphaColour . getLast . getRecommend $ c+ fromAlphaColour = FillColor . Commit . Last . fromAlphaColour -- | Convert to an RGB space while preserving the alpha channel. toRGBAUsingSpace :: Color c => RGBSpace Double -> c
+ src/Diagrams/Backend/CmdLine.hs view
@@ -0,0 +1,534 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Backend.CmdLine+-- Copyright : (c) 2013 Diagrams team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Convenient creation of command-line-driven executables for+-- rendering diagrams. This module provides a general framework+-- and default behaviors for parsing command-line arguments,+-- records for diagram creation options in various forms, and+-- classes and instances for a unified entry point to command-line-driven+-- diagram creation executables.+--+-- For a tutorial on command-line diagram creation see+-- <http://projects.haskell.org/diagrams/doc/cmdline.html>.+--+-----------------------------------------------------------------------------++module Diagrams.Backend.CmdLine+ (++ -- * Options++ -- ** Standard options+ DiagramOpts(..)+ , diagramOpts+ , width+ , height+ , output++ -- ** Multi-diagram options+ , DiagramMultiOpts(..)+ , diagramMultiOpts+ , selection+ , list++ -- ** Animation options+ , DiagramAnimOpts(..)+ , diagramAnimOpts+ , fpu++ -- ** Loop options+ , DiagramLoopOpts(..)+ , diagramLoopOpts+ , loop+ , src+ , interval++ -- * Parsing+ , Parseable(..)+ , readHexColor++ -- * Command-line programs (@Mainable@)+ -- ** Arguments, rendering, and entry point+ , Mainable(..)++ -- ** General currying+ , ToResult(..)++ -- ** Default @mainRender@ implementations+ , defaultAnimMainRender+ , defaultMultiMainRender+ ) where++import Control.Lens hiding (argument)+import Diagrams.Animation+import Diagrams.Attributes+import Diagrams.Core hiding (value)++import Options.Applicative hiding ((&))++import Prelude++import Control.Monad (forM_)++import Data.Active hiding (interval)+import Data.Char (isDigit)+import Data.Colour+import Data.Colour.Names+import Data.Colour.SRGB+import Data.Data+import Data.List (intercalate)+import Data.Monoid++import Numeric++import Safe (readMay)++import System.Environment (getProgName)+import System.FilePath (addExtension, splitExtension)++import Text.Printf++-- | Standard options most diagrams are likely to have.+data DiagramOpts = DiagramOpts+ { _width :: Maybe Int -- ^ Final output width of diagram.+ , _height :: Maybe Int -- ^ Final output height of diagram.+ , _output :: FilePath -- ^ Output file path, format is typically chosen by extension.+ }+ deriving (Show, Data, Typeable)++makeLenses ''DiagramOpts++-- | Extra options for a program that can offer a choice+-- between multiple diagrams.+data DiagramMultiOpts = DiagramMultiOpts+ { _selection :: Maybe String -- ^ Selected diagram to render.+ , _list :: Bool -- ^ Flag to indicate that a list of available diagrams should+ -- be printed to standard out.+ }+ deriving (Show, Data, Typeable)++makeLenses ''DiagramMultiOpts++-- | Extra options for animations.+data DiagramAnimOpts = DiagramAnimOpts+ { _fpu :: Double -- ^ Number of frames per unit time to generate for the animation.+ }+ deriving (Show, Data, Typeable)++makeLenses ''DiagramAnimOpts++-- | Extra options for command-line looping.+data DiagramLoopOpts = DiagramLoopOpts+ { _loop :: Bool -- ^ Flag to indicate that the program should loop creation.+ , _src :: Maybe FilePath -- ^ File path for the source file to recompile.+ , _interval :: Int -- ^ Interval in seconds at which to check for recompilation.+ }++makeLenses ''DiagramLoopOpts++-- | Command line parser for 'DiagramOpts'.+-- Width is option @--width@ or @-w@.+-- Height is option @--height@ or @-h@ (note we change help to be @-?@ due to this).+-- Output is option @--output@ or @-o@.+diagramOpts :: Parser DiagramOpts+diagramOpts = DiagramOpts+ <$> (optional . option)+ ( long "width" <> short 'w'+ <> metavar "WIDTH"+ <> help "Desired WIDTH of the output image")+ <*> (optional . option)+ ( long "height" <> short 'h'+ <> metavar "HEIGHT"+ <> help "Desired HEIGHT of the output image")+ <*> strOption+ ( long "output" <> short 'o'+ <> value ""+ <> metavar "OUTPUT"+ <> help "OUTPUT file")++-- | Command line parser for 'DiagramMultiOpts'.+-- Selection is option @--selection@ or @-s@.+-- List is @--list@ or @-l@.+diagramMultiOpts :: Parser DiagramMultiOpts+diagramMultiOpts = DiagramMultiOpts+ <$> (optional . strOption)+ ( long "selection" <> short 's'+ <> metavar "NAME"+ <> help "NAME of the diagram to render")+ <*> switch+ ( long "list" <> short 'l'+ <> help "List all available diagrams")++-- | Command line parser for 'DiagramAnimOpts'+-- Frames per unit is @--fpu@ or @-f@.+diagramAnimOpts :: Parser DiagramAnimOpts+diagramAnimOpts = DiagramAnimOpts+ <$> option+ ( long "fpu" <> short 'f'+ <> value 30.0+ <> help "Frames per unit time (for animations)")++-- | CommandLine parser for 'DiagramLoopOpts'+-- Loop is @--loop@ or @-l@.+-- Source is @--src@ or @-s@.+-- Interval is @-i@ defaulting to one second.+diagramLoopOpts :: Parser DiagramLoopOpts+diagramLoopOpts = DiagramLoopOpts+ <$> switch (long "loop" <> short 'l' <> help "Run in a self-recompiling loop")+ <*> (optional . strOption)+ ( long "src" <> short 's'+ <> help "Source file to watch")+ <*> option+ ( long "interval" <> short 'i'+ <> value 1+ <> metavar "INTERVAL"+ <> help "When running in a loop, check for changes every INTERVAL seconds.")++-- | A hidden \"helper\" option which always fails.+-- Taken from Options.Applicative.Extra but without the+-- short option 'h'. We want the 'h' for Height.+helper' :: Parser (a -> a)+helper' = abortOption ShowHelpText $ mconcat+ [ long "help"+ , short '?'+ , help "Show this help text"+ ]++-- | Apply a parser to the command line that includes the standard+-- program description and help behavior. Results in parsed commands+-- or fails with a help message.+defaultOpts :: Parser a -> IO a+defaultOpts optsParser = do+ prog <- getProgName+ let p = info (helper' <*> optsParser)+ ( fullDesc+ <> progDesc "Command-line diagram generation."+ <> header prog)+ execParser p++-- | Parseable instances give a command line parser for a type. If a custom+-- parser for a common type is wanted a newtype wrapper could be used to make+-- a new 'Parseable' instance. Notice that we do /not/ want as many+-- instances as 'Read' because we want to limit ourselves to things that make+-- sense to parse from the command line.+class Parseable a where+ parser :: Parser a++-- The following instance would overlap with the product instance for+-- Parseable. We can't tell if one wants to parse (a,b) as one argument or a+-- as one argument and b as another. Since this is the command line we almost+-- certainly want the latter. So we need to have less Read instances.+--+-- instance Read a => Parseable a where+-- parser = argument readMay mempty++-- | Parse 'Int' according to its 'Read' instance.+instance Parseable Int where+ parser = argument readMay mempty++-- | Parse 'Double' according to its 'Read' instance.+instance Parseable Double where+ parser = argument readMay mempty++-- | Parse a string by just accepting the given string.+instance Parseable String where+ parser = argument Just mempty++-- | Parse 'DiagramOpts' using the 'diagramOpts' parser.+instance Parseable DiagramOpts where+ parser = diagramOpts++-- | Parse 'DiagramMultiOpts' using the 'diagramMultiOpts' parser.+instance Parseable DiagramMultiOpts where+ parser = diagramMultiOpts++-- | Parse 'DiagramAnimOpts' using the 'diagramAnimOpts' parser.+instance Parseable DiagramAnimOpts where+ parser = diagramAnimOpts++-- | Parse 'DiagramLoopOpts' using the 'diagramLoopOpts' parser.+instance Parseable DiagramLoopOpts where+ parser = diagramLoopOpts+++-- | Parse @'Colour' Double@ as either a named color from "Data.Colour.Names"+-- or a hexadecimal color.+instance Parseable (Colour Double) where+ parser = argument (liftA2 (<|>) rc rh) mempty+ where+ rh s = (f . colorToSRGBA) <$> readHexColor s+ rc s = readColourName s+ f (r,g,b,_) = sRGB r g b -- TODO: this seems unfortunate. Should the alpha+ -- value be applied to the r g b values?++-- | Parse @'AlphaColour' Double@ as either a named color from "Data.Colour.Names"+-- or a hexadecimal color.+instance Parseable (AlphaColour Double) where+ parser = argument (liftA2 (<|>) rc rh) mempty+ where+ rh s = readHexColor s+ rc s = opaque <$> readColourName s++-- Addapted from the Clay.Color module of the clay package++-- | Parses a hexadecimal color. The string can start with @\"0x\"@ or @\"#\"@+-- or just be a string of hexadecimal values. If four or three digits are+-- given each digit is repeated to form a full 24 or 32 bit color. For+-- example, @\"0xfc4\"@ is the same as @\"0xffcc44\"@. When eight or six+-- digits are given each pair of digits is a color or alpha channel with the+-- order being red, green, blue, alpha.+readHexColor :: String -> Maybe (AlphaColour Double)+readHexColor cs = case cs of+ ('0':'x':hs) -> handle hs+ ('#':hs) -> handle hs+ hs -> handle hs+ where+ handle hs | length hs <= 8 && all isHexDigit hs+ = case hs of+ [a,b,c,d,e,f,g,h] -> withOpacity <$> (sRGB <$> hex a b <*> hex c d <*> hex e f) <*> hex g h+ [a,b,c,d,e,f ] -> opaque <$> (sRGB <$> hex a b <*> hex c d <*> hex e f)+ [a,b,c,d ] -> withOpacity <$> (sRGB <$> hex a a <*> hex b b <*> hex c c) <*> hex d d+ [a,b,c ] -> opaque <$> (sRGB <$> hex a a <*> hex b b <*> hex c c)+ _ -> Nothing+ handle _ = Nothing++ isHexDigit c = isDigit c|| c `elem` "abcdef"++ hex a b = (/ 255) <$> case readHex [a,b] of+ [(h,"")] -> Just h+ _ -> Nothing+++-- | This instance is needed to signal the end of a chain of+-- nested tuples, it always just results in the unit value+-- without consuming anything.+instance Parseable () where+ parser = pure ()++-- | Allow 'Parseable' things to be combined.+instance (Parseable a, Parseable b) => Parseable (a,b) where+ parser = (,) <$> parser <*> parser+++-- | This class allows us to abstract over functions that take some arguments+-- and produce a final value. When some @d@ is an instance of+-- 'ToResult' we get a type @'Args' d@ that is a type of /all/ the arguments+-- at once, and a type @'ResultOf' d@ that is the type of the final result from+-- some base case instance.+class ToResult d where+ type Args d :: *+ type ResultOf d :: *++ toResult :: d -> Args d -> ResultOf d++-- | A diagram can always produce a diagram when given @()@ as an argument.+-- This is our base case.+instance ToResult (Diagram b v) where+ type Args (Diagram b v) = ()+ type ResultOf (Diagram b v) = Diagram b v++ toResult d _ = d++-- | A list of diagrams can produce pages.+instance ToResult [Diagram b v] where+ type Args [Diagram b v] = ()+ type ResultOf [Diagram b v] = [Diagram b v]++ toResult ds _ = ds++-- | A list of named diagrams can give the multi-diagram interface.+instance ToResult [(String,Diagram b v)] where+ type Args [(String,Diagram b v)] = ()+ type ResultOf [(String,Diagram b v)] = [(String,Diagram b v)]++ toResult ds _ = ds++-- | An animation is another suitable base case.+instance ToResult (Animation b v) where+ type Args (Animation b v) = ()+ type ResultOf (Animation b v) = Animation b v++ toResult a _ = a++-- | Diagrams that require IO to build are a base case.+instance ToResult d => ToResult (IO d) where+ type Args (IO d) = Args d+ type ResultOf (IO d) = IO (ResultOf d)++ toResult d args = flip toResult args <$> d++-- | An instance for a function that, given some 'a', can produce a 'd' that is+-- also an instance of 'ToResult'. For this to work we need both the+-- argument 'a' and all the arguments that 'd' will need. Producing the+-- result is simply applying the argument to the producer and passing the+-- remaining arguments to the produced producer.++-- The previous paragraph stands as a witness to the fact that Haskell code+-- is clearer and easier to understand then paragraphs in English written by+-- me.+instance ToResult d => ToResult (a -> d) where+ type Args (a -> d) = (a, Args d)+ type ResultOf (a -> d) = ResultOf d++ toResult f (a,args) = toResult (f a) args+++-- | This class represents the various ways we want to support diagram creation+-- from the command line. It has the right instances to select between creating+-- single static diagrams, multiple static diagrams, static animations, and+-- functions that produce diagrams as long as the arguments are 'Parseable'.+--+-- Backends are expected to create @Mainable@ instances for the types that are+-- suitable for generating output in the backend's format. For instance,+-- Postscript can handle single diagrams, pages of diagrams, animations as+-- separate files, and association lists. This implies instances for+-- @Diagram Postscript R2@, @[Diagram Postscript R2]@, @Animation Postscript R2@,+-- and @[(String,Diagram Postscript R2)]@. We can consider these as the base+-- cases for the function instance.+--+-- The associated type 'MainOpts' describes the options which need to be parsed+-- from the command-line and passed to @mainRender@.+class Mainable d where+ -- | Associated type that describes the options which need to be parsed+ -- from the command-line and passed to @mainRender@.+ type MainOpts d :: *++ -- | This method invokes the command-line parser resulting in an options+ -- value or ending the program with an error or help message.+ -- Typically the default instance will work. If a different help message+ -- or parsing behavior is desired a new implementation is appropriate.+ --+ -- Note the @d@ argument should only be needed to fix the type @d@. Its+ -- value should not be relied on as a parameter.+ mainArgs :: Parseable (MainOpts d) => d -> IO (MainOpts d)+ mainArgs _ = defaultOpts parser++ -- | Backend specific work of rendering with the given options and mainable+ -- value is done here. All backend instances should implement this method.+ mainRender :: MainOpts d -> d -> IO ()++ -- | Main entry point for command-line diagram creation. This is the method+ -- that users will call from their program @main@. For instance an expected+ -- user program would take the following form.+ --+ -- > import Diagrams.Prelude+ -- > import Diagrams.Backend.TheBestBackend.CmdLine+ -- >+ -- > d :: Diagram B R2+ -- > d = ...+ -- >+ -- > main = mainWith d+ --+ -- Most backends should be able to use the default implementation. A different+ -- implementation should be used to handle more complex interactions with the user.+ mainWith :: Parseable (MainOpts d) => d -> IO ()+ mainWith d = do+ opts <- mainArgs d+ mainRender opts d++-- | This instance allows functions resulting in something that is 'Mainable' to+-- be 'Mainable'. It takes a parse of collected arguments and applies them to+-- the given function producing the 'Mainable' result.+instance (Parseable (Args (a -> d)), ToResult d, Mainable (ResultOf d))+ => Mainable (a -> d) where+ type MainOpts (a -> d) = (MainOpts (ResultOf (a -> d)), Args (a -> d))++ mainRender (opts, a) f = mainRender opts (toResult f a)+-- TODO: why can't we get away with: instance (Parseable (Args (a -> d)), Mainable (ResultOf d)) => ...+-- Doesn't `Args (a -> d)` imply `ToResult (a -> d)` which implies `ToResult d` ?++-- | With this instance we can perform IO to produce something +-- 'Mainable' before rendering.+instance Mainable d => Mainable (IO d) where+ type MainOpts (IO d) = MainOpts d++ mainRender opts dio = dio >>= mainRender opts++-- | @defaultMultiMainRender@ is an implementation of 'mainRender' where+-- instead of a single diagram it takes a list of diagrams paired with names+-- as input. The generated executable then takes a @--selection@ option+-- specifying the name of the diagram that should be rendered. The list of+-- available diagrams may also be printed by passing the option @--list@.+--+-- Typically a backend can write its @[(String,Diagram B V)]@ instance as+--+-- > instance Mainable [(String,Diagram B V)] where+-- > type MainOpts [(String,Diagram B V)] = (DiagramOpts, DiagramMultiOpts)+-- > mainRender = defaultMultiMainRender+--+-- We do not provide this instance in general so that backends can choose to+-- opt-in to this form or provide a different instance that makes more sense.+defaultMultiMainRender :: Mainable d => (MainOpts d, DiagramMultiOpts) -> [(String, d)] -> IO ()+defaultMultiMainRender (opts,multi) ds =+ if multi^.list+ then showDiaList (map fst ds)+ else case multi^.selection of+ Nothing -> putStrLn "No diagram selected." >> showDiaList (map fst ds)+ Just sel -> case lookup sel ds of+ Nothing -> putStrLn $ "Unknown diagram: " ++ sel+ Just d -> mainRender opts d++-- | Display the list of diagrams available for rendering.+showDiaList :: [String] -> IO ()+showDiaList ds = do+ putStrLn "Available diagrams:"+ putStrLn $ " " ++ intercalate " " ds++-- | @defaultAnimMainRender@ is an implementation of 'mainRender' which renders+-- an animation as numbered frames, named by extending the given output file+-- name by consecutive integers. For example if the given output file name is+-- @foo\/blah.ext@, the frames will be saved in @foo\/blah001.ext@,+-- @foo\/blah002.ext@, and so on (the number of padding digits used depends on+-- the total number of frames). It is up to the user to take these images and+-- stitch them together into an actual animation format (using, /e.g./+-- @ffmpeg@).+--+-- Of course, this is a rather crude method of rendering animations;+-- more sophisticated methods will likely be added in the future.+--+-- The @fpu@ option from 'DiagramAnimOpts' can be used to control how many frames will+-- be output for each second (unit time) of animation.+--+-- This function requires a lens into the structure that the particular backend+-- uses for it's diagram base case. If @MainOpts (Diagram b v) ~ DiagramOpts@+-- then this lens will simply be 'output'. For a backend supporting looping+-- it will most likely be @_1 . output@. This lens is required because the+-- implementation works by modifying the output field and running the base @mainRender@.+-- Typically a backend can write its @Animation B V@ instance as+--+-- > instance Mainable (Animation B V) where+-- > type MainOpts (Animation B V) = (DiagramOpts, DiagramAnimOpts)+-- > mainRender = defaultAnimMainRender output+--+-- We do not provide this instance in general so that backends can choose to+-- opt-in to this form or provide a different instance that makes more sense.+defaultAnimMainRender :: (Mainable (Diagram b v))+ => (Lens' (MainOpts (Diagram b v)) FilePath) -- ^ A lens into the output path.+ -> (MainOpts (Diagram b v),DiagramAnimOpts)+ -> Animation b v+ -> IO ()+defaultAnimMainRender out (opts,animOpts) anim = do+ let frames = simulate (toRational $ animOpts^.fpu) anim+ nDigits = length . show . length $ frames+ forM_ (zip [1..] frames) $ \(i,d) -> mainRender (indexize out nDigits i opts) d++-- | @indexize d n@ adds the integer index @n@ to the end of the+-- output file name, padding with zeros if necessary so that it uses+-- at least @d@ digits.+indexize :: Lens' s FilePath -> Int -> Integer -> s -> s+indexize out nDigits i opts = opts & out .~ output'+ where fmt = "%0" ++ show nDigits ++ "d"+ output' = addExtension (base ++ printf fmt (i::Integer)) ext+ (base, ext) = splitExtension (opts^.out)
src/Diagrams/Backend/Show.hs view
@@ -19,7 +19,6 @@ import Diagrams.Core.Transform (onBasis) import Diagrams.Prelude-import Diagrams.Trail import Data.Basis
src/Diagrams/BoundingBox.hs view
@@ -1,13 +1,12 @@-{-# LANGUAGE DeriveDataTypeable- , DeriveFunctor- , FlexibleContexts- , GeneralizedNewtypeDeriving- , NoMonomorphismRestriction- , ScopedTypeVariables- , StandaloneDeriving- , TypeFamilies- , UndecidableInstances- #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.BoundingBox@@ -42,28 +41,29 @@ , union, intersection ) where -import Control.Applicative ((<$>))-import Control.Monad (join, liftM2)-import Data.Map (Map, fromList, toList, fromDistinctAscList, toAscList)-import qualified Data.Foldable as F+import Control.Applicative ((<$>))+import qualified Data.Foldable as F+import Data.Map (Map, fromDistinctAscList, fromList,+ toAscList, toList) -import Data.Maybe (fromMaybe)+import Data.Maybe (fromMaybe) -import Data.VectorSpace+import Data.VectorSpace -- (VectorSpace, Scalar, AdditiveGroup, zeroV, negateV, (^+^), (^-^))-import Data.Basis (HasBasis, Basis, decompose, recompose, basisValue)-import Data.Monoid (Monoid(..))-import Data.Semigroup (Semigroup(..), Option(..))+import Data.Basis (Basis, HasBasis, basisValue,+ decompose, recompose)+import Data.Monoid (Monoid (..))+import Data.Semigroup (Option (..), Semigroup (..)) -import Data.Data (Data)-import Data.Typeable (Typeable)+import Data.Data (Data)+import Data.Typeable (Typeable) -import Diagrams.Core.Points (Point(..))-import Diagrams.Core.HasOrigin (HasOrigin(..))-import Diagrams.Core.Envelope (Enveloped(..), appEnvelope)-import Diagrams.Core.V (V)-import Diagrams.Core.Transform- (Transformation(..), Transformable(..), HasLinearMap, (<->))+import Diagrams.Core.Envelope (Enveloped (..), appEnvelope)+import Diagrams.Core.HasOrigin (HasOrigin (..))+import Diagrams.Core.Points (Point (..))+import Diagrams.Core.Transform (HasLinearMap, Transformable (..),+ Transformation (..), (<->))+import Diagrams.Core.V (V) -- Unexported utility newtype @@ -128,7 +128,7 @@ -} -- | An empty bounding box. This is the same thing as @mempty@, but it doesn't--- require the same type constraints that the @Monoid@ +-- require the same type constraints that the @Monoid@ emptyBox :: BoundingBox v emptyBox = BoundingBox $ Option Nothing @@ -182,7 +182,7 @@ getAllCorners (BoundingBox (Option Nothing)) = [] getAllCorners (BoundingBox (Option (Just (NonEmptyBoundingBox (l, u))))) = map (P . recompose)- -- Enumerate all combinations of selections of lower / higher values. + -- Enumerate all combinations of selections of lower / higher values. . mapM (\(b, (l', u')) -> [(b, l'), (b, u')]) -- List of [(basis, (lower, upper))] . toList@@ -194,7 +194,7 @@ boxExtents = maybe zeroV (\(P l, P h) -> h ^-^ l) . getCorners -- | Create a transformation mapping points from one bounding box to the other.-boxTransform :: (AdditiveGroup v, HasLinearMap v, +boxTransform :: (AdditiveGroup v, HasLinearMap v, Fractional (Scalar v), AdditiveGroup (Scalar v), Ord (Basis v)) => BoundingBox v -> BoundingBox v -> Maybe (Transformation v) boxTransform u v = do
src/Diagrams/Combinators.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -----------------------------------------------------------------------------@@ -29,22 +31,26 @@ -- * n-ary operations , appends , position, decorateTrail, decorateLocatedTrail, decoratePath- , cat, cat', CatOpts(..), CatMethod(..)+ , cat, cat'+ , CatOpts(_catMethod, _sep), catMethod, sep+ , CatMethod(..) ) where +import Control.Lens ( (&), (%~), (.~), Lens', makeLensesWith+ , lensRules, lensField, generateSignatures, unwrapping) import Data.AdditiveGroup import Data.AffineSpace ((.+^)) import Data.Default.Class+import Data.Proxy import Data.Semigroup import Data.VectorSpace import Diagrams.Core import Diagrams.Located import Diagrams.Path-import Diagrams.Segment (Segment (..), straight)+import Diagrams.Segment (straight) import Diagrams.Trail (Trail, trailVertices)-import Diagrams.TrailLike (fromOffsets) import Diagrams.Util ------------------------------------------------------------@@ -53,6 +59,17 @@ -- | Use the envelope from some object as the envelope for a -- diagram, in place of the diagram's default envelope.+--+-- <<diagrams/src_Diagrams_Combinators_withEnvelopeEx.svg#diagram=withEnvelopeEx&width=300>>+--+-- > sqNewEnv =+-- > circle 1 # fc green+-- > |||+-- > ( c # dashing [0.1,0.1] 0 # lc white+-- > <> square 2 # withEnvelope (c :: D R2) # fc blue+-- > )+-- > c = circle 0.8+-- > withEnvelopeEx = sqNewEnv # centerXY # pad 1.5 withEnvelope :: (HasLinearMap (V a), Enveloped a, Monoid' m) => a -> QDiagram b (V a) m -> QDiagram b (V a) m withEnvelope = setEnvelope . getEnvelope@@ -87,6 +104,10 @@ -- with a nonempty trace see 'strutR2', 'strutX', and 'strutY' from -- "Diagrams.TwoD.Combinators".) Useful for manually creating -- separation between two diagrams.+--+-- <<diagrams/src_Diagrams_Combinators_strutEx.svg#diagram=strutEx&width=300>>+--+-- > strutEx = (circle 1 ||| strut unitX ||| circle 1) # centerXY # pad 1.1 strut :: ( Backend b v, InnerSpace v , OrderedField (Scalar v) , Monoid' m@@ -135,7 +156,7 @@ :: ( Ord (Scalar v), Num (Scalar v), AdditiveGroup (Scalar v) , Floating (Scalar v), HasLinearMap v, InnerSpace v, Monoid' m ) => (Scalar v) -> v -> QDiagram b v m -> QDiagram b v m-deformEnvelope s v d = setEnvelope (inEnvelope deform $ getEnvelope d) d+deformEnvelope s v d = setEnvelope (getEnvelope d & unwrapping Envelope %~ deform) d where deform = Option . fmap deform' . getOption deform' env v'@@ -167,7 +188,7 @@ -- identity element, in which case the second object is returned -- unchanged). ----- <<diagrams/besideEx.svg#diagram=besideEx&height=200>>+-- <<diagrams/src_Diagrams_Combinators_besideEx.svg#diagram=besideEx&height=200>> -- -- > besideEx = beside (r2 (20,30)) -- > (circle 1 # fc orange)@@ -203,12 +224,24 @@ -- @x@ in the corresponding direction. Note that each object in -- @ys@ is positioned beside @x@ /without/ reference to the other -- objects in @ys@, so this is not the same as iterating 'beside'.+--+-- <<diagrams/src_Diagrams_Combinators_appendsEx.svg#diagram=appendsEx&width=200>>+--+-- > appendsEx = appends c (zip (iterateN 6 (rotateBy (1/6)) unitX) (repeat c))+-- > # centerXY # pad 1.1+-- > where c = circle 1 appends :: (Juxtaposable a, Monoid' a) => a -> [(V a,a)] -> a appends d1 apps = d1 <> mconcat (map (\(v,d) -> juxtapose v d1 d) apps) -- | Position things absolutely: combine a list of objects -- (e.g. diagrams or paths) by assigning them absolute positions in -- the vector space of the combined object.+--+-- <<diagrams/src_Diagrams_Combinators_positionEx.svg#diagram=positionEx&height=300>>+--+-- > positionEx = position (zip (map mkPoint [-3, -2.8 .. 3]) (repeat dot))+-- > where dot = circle 0.2 # fc black+-- > mkPoint x = p2 (x,x^2) position :: (HasOrigin a, Monoid' a) => [(Point (V a), a)] -> a position = mconcat . map (uncurry moveTo) @@ -257,36 +290,48 @@ -- of separation, diagrams may overlap. -- | Options for 'cat''.-data CatOpts v = CatOpts { catMethod :: CatMethod- -- ^ Which 'CatMethod' should be used:- -- normal catenation (default), or- -- distribution?- , sep :: Scalar v- -- ^ How much separation should be used- -- between successive diagrams- -- (default: 0)? When @catMethod =- -- Cat@, this is the distance between- -- /envelopes/; when @catMethod =- -- Distrib@, this is the distance- -- between /origins/.- , catOptsvProxy__ :: Proxy v- -- ^ This field exists solely to aid type inference;- -- please ignore it.+data CatOpts v = CatOpts { _catMethod :: CatMethod+ , _sep :: Scalar v+ , _catOptsvProxy__ :: Proxy v } -- The reason the proxy field is necessary is that without it, -- altering the sep field could theoretically change the type of a--- CatOpts record. This causes problems when writing an expression--- like @with { sep = 10 }@, because knowing the type of the whole+-- CatOpts record. This causes problems when using record update, as+-- in @with { _sep = 10 }@, because knowing the type of the whole -- expression does not tell us anything about the type of @with@, and -- therefore the @Num (Scalar v)@ constraint cannot be satisfied.--- Adding the Proxy field constrains the type of @with@ in @with {sep--- = 10}@ to be the same as the type of the whole expression.+-- Adding the Proxy field constrains the type of @with@ in @with {_sep+-- = 10}@ to be the same as the type of the whole expression. Note+-- this is not a problem when using the 'sep' lens, as its type is+-- more restricted. +makeLensesWith+ ( lensRules+ -- don't make a lens for the proxy field+ & lensField .~ (\label ->+ case label of+ "_catOptsvProxy__" -> Nothing+ _ -> Just (drop 1 label)+ )+ & generateSignatures .~ False+ )+ ''CatOpts++-- | Which 'CatMethod' should be used:+-- normal catenation (default), or distribution?+catMethod :: forall v. Lens' (CatOpts v) CatMethod++-- | How much separation should be used between successive diagrams+-- (default: 0)? When @catMethod = Cat@, this is the distance between+-- /envelopes/; when @catMethod = Distrib@, this is the distance+-- between /origins/.+sep :: forall v. Lens' (CatOpts v) (Scalar v)+ instance Num (Scalar v) => Default (CatOpts v) where- def = CatOpts { catMethod = Cat- , sep = 0- , catOptsvProxy__ = Proxy+ def = CatOpts { _catMethod = Cat+ , _sep = 0+ , _catOptsvProxy__ = Proxy } -- | @cat v@ positions a list of objects so that their local origins@@ -324,9 +369,9 @@ , InnerSpace (V a), OrderedField (Scalar (V a)) ) => V a -> CatOpts (V a) -> [a] -> a-cat' v (CatOpts { catMethod = Cat, sep = s }) = foldB comb mempty+cat' v (CatOpts { _catMethod = Cat, _sep = s }) = foldB comb mempty where comb d1 d2 = d1 <> (juxtapose v d1 d2 # moveOriginBy vs) vs = s *^ normalized (negateV v) -cat' v (CatOpts { catMethod = Distrib, sep = s }) =+cat' v (CatOpts { _catMethod = Distrib, _sep = s }) = position . zip (iterate (.+^ (s *^ normalized v)) origin)
src/Diagrams/Coordinates.hs view
@@ -10,17 +10,20 @@ -- Nice syntax for constructing and pattern-matching on literal -- points and vectors. ----- NOTE: to avoid clashing with the '(&)' operator from the @lens@--- package, this module is not re-exported by "Diagrams.Prelude". To--- make use of the contents of this module, you must explicitly import--- it.--- ----------------------------------------------------------------------------- module Diagrams.Coordinates- ( (:&)(..), Coordinates(..) )+ ( (:&)(..), Coordinates(..)++ -- * Lenses for particular axes+ , HasX(..), HasY(..), HasZ(..)+ ) where +import Control.Lens (Lens')++import Diagrams.Core.Points+ -- | A pair of values, with a convenient infix (left-associative) -- data constructor. data a :& b = a :& b@@ -30,8 +33,8 @@ -- | Types which are instances of the @Coordinates@ class can be--- constructed using '&' (for example, a three-dimensional vector--- could be constructed by @1 & 6 & 3@), and deconstructed using+-- constructed using '^&' (for example, a three-dimensional vector+-- could be constructed by @1 ^& 6 ^& 3@), and deconstructed using -- 'coords'. A common pattern is to use 'coords' in conjunction -- with the @ViewPatterns@ extension, like so: --@@ -53,21 +56,25 @@ -- | Construct a value of type @c@ by providing something of one -- less dimension (which is perhaps itself recursively constructed- -- using @(&)@) and a final coordinate. For example,+ -- using @(^&)@) and a final coordinate. For example, -- -- @- -- 2 & 3 :: P2- -- 3 & 5 & 6 :: R3+ -- 2 ^& 3 :: P2+ -- 3 ^& 5 ^& 6 :: R3 -- @ --- -- Note that @&@ is left-associative.- (&) :: PrevDim c -> FinalCoord c -> c+ -- Note that @^&@ is left-associative.+ (^&) :: PrevDim c -> FinalCoord c -> c + -- | Prefix synonym for @^&@. pr stands for pair of @PrevDim@, @FinalCoord@+ pr :: PrevDim c -> FinalCoord c -> c+ pr = (^&)+ -- | Decompose a value of type @c@ into its constituent coordinates, -- stored in a nested @(:&)@ structure. coords :: c -> Decomposition c -infixl 7 &+infixl 7 ^& -- Some standard instances for plain old tuples @@ -76,7 +83,7 @@ type PrevDim (a,b) = a type Decomposition (a,b) = a :& b - x & y = (x,y)+ x ^& y = (x,y) coords (x,y) = x :& y instance Coordinates (a,b,c) where@@ -84,7 +91,7 @@ type PrevDim (a,b,c) = (a,b) type Decomposition (a,b,c) = Decomposition (a,b) :& c - (x,y) & z = (x,y,z)+ (x,y) ^& z = (x,y,z) coords (x,y,z) = coords (x,y) :& z instance Coordinates (a,b,c,d) where@@ -92,5 +99,25 @@ type PrevDim (a,b,c,d) = (a,b,c) type Decomposition (a,b,c,d) = Decomposition (a,b,c) :& d - (w,x,y) & z = (w,x,y,z)+ (w,x,y) ^& z = (w,x,y,z) coords (w,x,y,z) = coords (w,x,y) :& z++instance Coordinates v => Coordinates (Point v) where+ type FinalCoord (Point v) = FinalCoord v+ type PrevDim (Point v) = PrevDim v+ type Decomposition (Point v) = Decomposition v++ x ^& y = P (x ^& y)+ coords (P v) = coords v++-- | The class of types with at least one coordinate, called _x.+class HasX t where+ _x :: Lens' t Double++-- | The class of types with at least two coordinates, the second called _y.+class HasY t where+ _y :: Lens' t Double++-- | The class of types with at least three coordinates, the third called _z.+class HasZ t where+ _z :: Lens' t Double
src/Diagrams/CubicSpline.hs view
@@ -26,9 +26,7 @@ import Diagrams.Core import Diagrams.Core.Points import Diagrams.CubicSpline.Internal-import Diagrams.Located (at)-import Diagrams.Located-import Diagrams.Path+import Diagrams.Located (Located, at, mapLoc) import Diagrams.Segment import Diagrams.Trail import Diagrams.TrailLike (TrailLike (..))@@ -36,15 +34,14 @@ -- for e.g. the Fractional (Double, Double) instance import Data.NumInstances.Tuple () -import Control.Newtype-import Data.Semigroup+import Data.AffineSpace.Point import Data.VectorSpace -- | Construct a spline path-like thing of cubic segments from a list of -- vertices, with the first vertex as the starting point. The first -- argument specifies whether the path should be closed. ----- <<diagrams/cubicSplineEx.svg#diagram=cubicSplineEx&width=600>>+-- <<diagrams/src_Diagrams_CubicSpline_cubicSplineEx.svg#diagram=cubicSplineEx&width=600>> -- -- > pts = map p2 [(0,0), (2,3), (5,-2), (-4,1), (0,3)] -- > dot = circle 0.2 # fc blue # lw 0@@ -55,12 +52,12 @@ -- -- For more information, see <http://mathworld.wolfram.com/CubicSpline.html>. cubicSpline :: (TrailLike t, Fractional (V t)) => Bool -> [Point (V t)] -> t-cubicSpline c [] = trailLike . closeIf c $ emptyLine `at` origin-cubicSpline c ps = flattenBeziers . map f . solveCubicSplineCoefficients c . map unpack $ ps+cubicSpline closed [] = trailLike . closeIf closed $ emptyLine `at` origin+cubicSpline closed ps = flattenBeziers . map f . solveCubicSplineCoefficients closed . map unPoint $ ps where f [a,b,c,d] = [a, (3*a+b)/3, (3*a+2*b+c)/3, a+b+c+d] flattenBeziers bs@((b:_):_)- = trailLike . closeIf c $ lineFromSegments (map bez bs) `at` P b+ = trailLike . closeIf closed $ lineFromSegments (map bez bs) `at` P b bez [a,b,c,d] = bezier3 (b - a) (c - a) (d - a) closeIf :: (InnerSpace v, OrderedField (Scalar v))
src/Diagrams/Located.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}- ----------------------------------------------------------------------------- -- | -- Module : Diagrams.Located@@ -20,15 +19,17 @@ module Diagrams.Located ( Located- , at, viewLoc, unLoc, loc, mapLoc+ , at, viewLoc, unLoc, loc, mapLoc, located ) where +import Control.Lens (Lens) import Data.AffineSpace+import Data.Functor ((<$>)) import Data.VectorSpace import Diagrams.Core-import Diagrams.Core.Points+import Diagrams.Core.Points () import Diagrams.Core.Transform import Diagrams.Parametric -- for GHC 7.4 type family bug@@ -84,6 +85,10 @@ mapLoc :: (V a ~ V b) => (a -> b) -> Located a -> Located b mapLoc f (Loc p a) = Loc p (f a) +-- | A lens giving access to the object within a 'Located' wrapper.+located :: (V a ~ V a') => Lens (Located a) (Located a') a a'+located f (Loc p a) = Loc p <$> f a+ deriving instance (Eq (V a), Eq a ) => Eq (Located a) deriving instance (Ord (V a), Ord a ) => Ord (Located a) deriving instance (Show (V a), Show a) => Show (Located a)@@ -120,16 +125,18 @@ instance Qualifiable a => Qualifiable (Located a) where n |> (Loc p a) = Loc p (n |> a) -type instance Codomain (Located a) = Located (Codomain a)+type instance Codomain (Located a) = Point (Codomain a) -instance (V a ~ V (Codomain a), Parametric a) => Parametric (Located a) where- (Loc x a) `atParam` p = Loc x (a `atParam` p)+instance (Codomain a ~ V a, AdditiveGroup (V a), Parametric a)+ => Parametric (Located a) where+ (Loc x a) `atParam` p = x .+^ (a `atParam` p) instance DomainBounds a => DomainBounds (Located a) where domainLower (Loc _ a) = domainLower a domainUpper (Loc _ a) = domainUpper a -instance (V a ~ V (Codomain a), EndValues a) => EndValues (Located a)+instance (Codomain a ~ V a, AdditiveGroup (V a), EndValues a)+ => EndValues (Located a) instance ( Codomain a ~ V a, Fractional (Scalar (V a)), AdditiveGroup (V a) , Sectionable a, Parametric a@@ -138,7 +145,12 @@ splitAtParam (Loc x a) p = (Loc x a1, Loc (x .+^ (a `atParam` p)) a2) where (a1,a2) = splitAtParam a p -instance (HasArcLength a, Fractional (Scalar (V a)), V a ~ V (Codomain a))+ reverseDomain (Loc x a) = Loc (x .+^ y) (reverseDomain a)+ where y = a `atParam` (domainUpper a)++instance ( Codomain a ~ V a, AdditiveGroup (V a), Fractional (Scalar (V a))+ , HasArcLength a+ ) => HasArcLength (Located a) where arcLengthBounded eps (Loc _ a) = arcLengthBounded eps a arcLengthToParam eps (Loc _ a) l = arcLengthToParam eps a l
src/Diagrams/Names.hs view
@@ -33,6 +33,7 @@ -- * Querying by name , names+ , lookupName , withName, withNameAll, withNames ) where
src/Diagrams/Parametric.hs view
@@ -15,22 +15,15 @@ ----------------------------------------------------------------------------- module Diagrams.Parametric (- -- * Parametric functions stdTolerance , Codomain, Parametric(..) - , DomainBounds(..), EndValues(..), Sectionable(..), HasArcLength(..)-- -- * Adjusting- , adjust- , AdjustOpts(..), AdjustMethod(..), AdjustSide(..)+ , DomainBounds(..), domainBounds, EndValues(..), Sectionable(..), HasArcLength(..) ) where import Diagrams.Core-import Diagrams.Util -import Data.Default.Class import Data.VectorSpace import qualified Numeric.Interval as I @@ -96,7 +89,8 @@ -- | Type class for parametric objects which can be split into -- subobjects. ----- Minimal definition: Either 'splitAtParam' or 'section'.+-- Minimal definition: Either 'splitAtParam' or 'section',+-- plus 'reverseDomain'. class DomainBounds p => Sectionable p where -- | 'splitAtParam' splits an object @p@ into two new objects -- @(l,r)@ at the parameter @t@, where @l@ corresponds to the@@ -139,12 +133,8 @@ default section :: Fractional (Scalar (V p)) => p -> Scalar (V p) -> Scalar (V p) -> p section x t1 t2 = snd (splitAtParam (fst (splitAtParam x t2)) (t1/t2)) - -- | Flip the parameterization on the domain. This has the- -- following default definition:- --- -- > reverse x = section x (domainUpper x) (domainLower x)+ -- | Flip the parameterization on the domain. reverseDomain :: p -> p- reverseDomain x = section x (domainUpper x) (domainLower x) -- | The standard tolerance used by @std...@ functions (like -- 'stdArcLength' and 'stdArcLengthToParam', currently set at@@ -187,57 +177,3 @@ default stdArcLengthToParam :: Fractional (Scalar (V p)) => p -> Scalar (V p) -> Scalar (V p) stdArcLengthToParam = arcLengthToParam stdTolerance------------------------------------------------------- Adjusting length------------------------------------------------------- | What method should be used for adjusting a segment, trail, or--- path?-data AdjustMethod v = ByParam (Scalar v) -- ^ Extend by the given parameter value- -- (use a negative parameter to shrink)- | ByAbsolute (Scalar v) -- ^ Extend by the given arc length- -- (use a negative length to shrink)- | ToAbsolute (Scalar v) -- ^ Extend or shrink to the given- -- arc length---- | Which side of a segment, trail, or path should be adjusted?-data AdjustSide = Start -- ^ Adjust only the beginning- | End -- ^ Adjust only the end- | Both -- ^ Adjust both sides equally- deriving (Show, Read, Eq, Ord, Bounded, Enum)---- | How should a segment, trail, or path be adjusted?-data AdjustOpts v = AO { adjMethod :: AdjustMethod v- , adjSide :: AdjustSide- , adjEps :: Scalar v- , adjOptsvProxy__ :: Proxy v- }--instance Fractional (Scalar v) => Default (AdjustMethod v) where- def = ByParam 0.2--instance Default AdjustSide where- def = Both--instance Fractional (Scalar v) => Default (AdjustOpts v) where- def = AO def def stdTolerance Proxy---- | Adjust the length of a parametric object such as a segment or--- trail. The second parameter is an option record which controls how--- the adjustment should be performed; see 'AdjustOpts'.-adjust :: (DomainBounds a, Sectionable a, HasArcLength a, Fractional (Scalar (V a)))- => a -> AdjustOpts (V a) -> a-adjust s opts = section s- (if adjSide opts == End then domainLower s else getParam s)- (if adjSide opts == Start then domainUpper s else domainUpper s - getParam (reverseDomain s))- where- getParam seg = case adjMethod opts of- ByParam p -> -p * bothCoef- ByAbsolute len -> param (-len * bothCoef)- ToAbsolute len -> param (absDelta len * bothCoef)- where- param = arcLengthToParam eps seg- absDelta len = arcLength eps s - len- bothCoef = if adjSide opts == Both then 0.5 else 1- eps = adjEps opts
+ src/Diagrams/Parametric/Adjust.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Parametric.Adjust+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Tools for adjusting the length of parametric objects such as+-- segments and trails.+--+-----------------------------------------------------------------------------+module Diagrams.Parametric.Adjust+ ( adjust+ , AdjustOpts(_adjMethod, _adjSide, _adjEps)+ , adjMethod, adjSide, adjEps+ , AdjustMethod(..), AdjustSide(..)++ ) where++import Control.Lens (makeLensesWith, lensRules, lensField, generateSignatures, (^.), (&), (.~), Lens')+import Data.Proxy++import Data.Default.Class+import Data.VectorSpace++import Diagrams.Core.V+import Diagrams.Parametric++-- | What method should be used for adjusting a segment, trail, or+-- path?+data AdjustMethod v = ByParam (Scalar v) -- ^ Extend by the given parameter value+ -- (use a negative parameter to shrink)+ | ByAbsolute (Scalar v) -- ^ Extend by the given arc length+ -- (use a negative length to shrink)+ | ToAbsolute (Scalar v) -- ^ Extend or shrink to the given+ -- arc length++-- | Which side of a segment, trail, or path should be adjusted?+data AdjustSide = Start -- ^ Adjust only the beginning+ | End -- ^ Adjust only the end+ | Both -- ^ Adjust both sides equally+ deriving (Show, Read, Eq, Ord, Bounded, Enum)++-- | How should a segment, trail, or path be adjusted?+data AdjustOpts v = AO { _adjMethod :: AdjustMethod v+ , _adjSide :: AdjustSide+ , _adjEps :: Scalar v+ , _adjOptsvProxy__ :: Proxy v+ }++makeLensesWith+ ( lensRules+ -- don't make a lens for the proxy field+ & lensField .~ (\label ->+ case label of+ "_adjOptsvProxy__" -> Nothing+ _ -> Just (drop 1 label)+ )+ & generateSignatures .~ False+ )+ ''AdjustOpts++-- | Which method should be used for adjusting?+adjMethod :: Lens' (AdjustOpts v) (AdjustMethod v)++-- | Which end(s) of the object should be adjusted?+adjSide :: Lens' (AdjustOpts v) AdjustSide++-- | Tolerance to use when doing adjustment.+adjEps :: Lens' (AdjustOpts v) (Scalar v)++instance Fractional (Scalar v) => Default (AdjustMethod v) where+ def = ByParam 0.2++instance Default AdjustSide where+ def = Both++instance Fractional (Scalar v) => Default (AdjustOpts v) where+ def = AO def def stdTolerance Proxy++-- | Adjust the length of a parametric object such as a segment or+-- trail. The second parameter is an option record which controls how+-- the adjustment should be performed; see 'AdjustOpts'.+adjust :: (DomainBounds a, Sectionable a, HasArcLength a, Fractional (Scalar (V a)))+ => a -> AdjustOpts (V a) -> a+adjust s opts = section s+ (if opts^.adjSide == End then domainLower s else getParam s)+ (if opts^.adjSide == Start then domainUpper s else domainUpper s - getParam (reverseDomain s))+ where+ getParam seg = case opts^.adjMethod of+ ByParam p -> -p * bothCoef+ ByAbsolute len -> param (-len * bothCoef)+ ToAbsolute len -> param (absDelta len * bothCoef)+ where+ param = arcLengthToParam eps seg+ absDelta len = arcLength eps s - len+ bothCoef = if opts^.adjSide == Both then 0.5 else 1+ eps = opts^.adjEps
src/Diagrams/Path.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-}@@ -28,7 +29,7 @@ -- * Paths - Path(..)+ Path(..), pathTrails -- * Constructing paths -- $construct@@ -58,7 +59,7 @@ import Diagrams.Align import Diagrams.Core-import Diagrams.Core.Points+import Diagrams.Core.Points () import Diagrams.Located import Diagrams.Points import Diagrams.Segment@@ -66,11 +67,12 @@ import Diagrams.TrailLike import Diagrams.Transform -import Control.Arrow (first, second, (***))-import Control.Newtype hiding (under)+import Control.Arrow ((***))+import Control.Lens ( Wrapped(..), mapped, over, view, iso+ , unwrapped, wrapped, (%~), op) import Data.AffineSpace import qualified Data.Foldable as F-import Data.List (mapAccumL, partition)+import Data.List (partition) import Data.Semigroup import Data.VectorSpace @@ -82,21 +84,25 @@ -- Hence, unlike trails, paths are not translationally invariant, -- and they form a monoid under /superposition/ (placing one path on -- top of another) rather than concatenation.-newtype Path v = Path { pathTrails :: [Located (Trail v)] }+newtype Path v = Path [Located (Trail v)] deriving (Semigroup, Monoid) +instance Wrapped [Located (Trail v)] [Located (Trail v')] (Path v) (Path v')+ where wrapped = iso Path $ \(Path x) -> x++-- | Extract the located trails making up a 'Path'.+pathTrails :: Path v -> [Located (Trail v)]+pathTrails = op Path+ deriving instance Show v => Show (Path v) deriving instance Eq v => Eq (Path v) deriving instance Ord v => Ord (Path v) type instance V (Path v) = v -instance Newtype (Path v) [Located (Trail v)] where- pack = Path- unpack = pathTrails- instance VectorSpace v => HasOrigin (Path v) where- moveOriginTo = over Path . map . moveOriginTo+ moveOriginTo = over unwrapped . map . moveOriginTo+ --moveOriginTo = over pathTrails . map . moveOriginTo -- | Paths are trail-like; a trail can be used to construct a -- singleton path.@@ -106,7 +112,7 @@ -- See Note [Transforming paths] instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v)) => Transformable (Path v) where- transform = over Path . map . transform+ transform = over unwrapped . map . transform {- ~~~~ Note [Transforming paths] @@ -121,7 +127,7 @@ instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v)) => IsPrim (Path v) instance (InnerSpace v, OrderedField (Scalar v)) => Enveloped (Path v) where- getEnvelope = F.foldMap trailEnvelope . pathTrails+ getEnvelope = F.foldMap trailEnvelope . op Path --view pathTrails -- this type signature is necessary to work around an apparent bug in ghc 6.12.1 where trailEnvelope :: Located (Trail v) -> Envelope v trailEnvelope (viewLoc -> (p, t)) = moveOriginTo ((-1) *. p) (getEnvelope t)@@ -130,7 +136,7 @@ juxtapose = juxtaposeDefault instance (InnerSpace v, OrderedField (Scalar v)) => Alignable (Path v) where- alignBy = alignByDefault+ defaultBoundary = envelopeBoundary instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v)) => Renderable (Path v) NullBackend where@@ -166,11 +172,11 @@ -- | Extract the vertices of a path, resulting in a separate list of -- vertices for each component trail (see 'trailVertices'). pathVertices :: (InnerSpace v, OrderedField (Scalar v)) => Path v -> [[Point v]]-pathVertices = map trailVertices . pathTrails+pathVertices = map trailVertices . op Path -- | Compute the total offset of each trail comprising a path (see 'trailOffset'). pathOffsets :: (InnerSpace v, OrderedField (Scalar v)) => Path v -> [v]-pathOffsets = map (trailOffset . unLoc) . pathTrails+pathOffsets = map (trailOffset . unLoc) . op Path -- | Compute the /centroid/ of a path (/i.e./ the average location of -- its vertices).@@ -179,18 +185,18 @@ -- | Convert a path into a list of lists of 'FixedSegment's. fixPath :: (InnerSpace v, OrderedField (Scalar v)) => Path v -> [[FixedSegment v]]-fixPath = map fixTrail . unpack+fixPath = map fixTrail . op Path -- | \"Explode\" a path by exploding every component trail (see -- 'explodeTrail'). explodePath :: (VectorSpace (V t), TrailLike t) => Path (V t) -> [[t]]-explodePath = map explodeTrail . pathTrails+explodePath = map explodeTrail . op Path -- | Partition a path into two paths based on a predicate on trails: -- the first containing all the trails for which the predicate returns -- @True@, and the second containing the remaining trails. partitionPath :: (Located (Trail v) -> Bool) -> Path v -> (Path v, Path v)-partitionPath p = (pack *** pack) . partition p . unpack+partitionPath p = (view wrapped *** view wrapped) . partition p . op Path ------------------------------------------------------------ -- Modifying paths ---------------------------------------@@ -204,4 +210,4 @@ -- | Reverse all the component trails of a path. reversePath :: (InnerSpace v, OrderedField (Scalar v)) => Path v -> Path v-reversePath = (over Path . map) reverseLocTrail+reversePath = unwrapped . mapped %~ reverseLocTrail
src/Diagrams/Points.hs view
@@ -19,26 +19,18 @@ -- * Point-related utilities , centroid+ , pointDiagram ) where -import Diagrams.Coordinates+import Diagrams.Core (pointDiagram) import Diagrams.Core.Points -import Control.Newtype--import Control.Arrow ((&&&))+import Control.Arrow ((&&&)) +import Data.AffineSpace.Point import Data.VectorSpace -- | The centroid of a set of /n/ points is their sum divided by /n/. centroid :: (VectorSpace v, Fractional (Scalar v)) => [Point v] -> Point v-centroid = pack . uncurry (^/) . (sumV &&& (fromIntegral . length)) . map unpack--instance Coordinates v => Coordinates (Point v) where- type FinalCoord (Point v) = FinalCoord v- type PrevDim (Point v) = PrevDim v- type Decomposition (Point v) = Decomposition v-- x & y = P (x & y)- coords (P v) = coords v+centroid = P . uncurry (^/) . (sumV &&& (fromIntegral . length)) . map unPoint
src/Diagrams/Prelude.hs view
@@ -41,6 +41,13 @@ -- | Parametrization of segments and trails. , module Diagrams.Parametric + -- | Adjusting the length of parameterized objects.+ , module Diagrams.Parametric.Adjust++ -- | Computing tangent and normal vectors of segments and+ -- trails.+ , module Diagrams.Tangent+ -- | Trail-like things. , module Diagrams.TrailLike @@ -54,10 +61,6 @@ -- conjugation of transformations. , module Diagrams.Transform - -- | Convenient definitions and utilities for working with- -- good old-fashioned, axis-aligned bounding boxes.- , module Diagrams.BoundingBox- -- | Giving names to subdiagrams and later retrieving -- subdiagrams by name. , module Diagrams.Names@@ -77,6 +80,9 @@ -- | Utilities for working with points. , module Diagrams.Points + -- | Convenience infix operators for working with coordinates.+ , module Diagrams.Coordinates+ -- | A wide range of things (shapes, transformations, -- combinators) specific to creating two-dimensional -- diagrams.@@ -104,6 +110,9 @@ -- | For working with 'Active' (i.e. animated) things. , module Data.Active + -- | Essential Lens Combinators+ , (&), (.~), (%~)+ , Applicative(..), (*>), (<*), (<$>), (<$), liftA, liftA2, liftA3 ) where @@ -112,7 +121,6 @@ import Diagrams.Align import Diagrams.Animation import Diagrams.Attributes-import Diagrams.BoundingBox import Diagrams.Combinators import Diagrams.Coordinates import Diagrams.CubicSpline@@ -120,10 +128,12 @@ import Diagrams.Located import Diagrams.Names import Diagrams.Parametric+import Diagrams.Parametric.Adjust import Diagrams.Path import Diagrams.Points import Diagrams.Query import Diagrams.Segment+import Diagrams.Tangent import Diagrams.Trace import Diagrams.Trail import Diagrams.TrailLike@@ -134,7 +144,8 @@ import Control.Applicative import Data.Active import Data.AffineSpace-import Data.Colour hiding (AffineSpace (..), atop)-import Data.Colour.Names+import Data.Colour hiding (AffineSpace (..), atop, over)+import Data.Colour.Names hiding (tan) import Data.Semigroup-import Data.VectorSpace hiding (Sum (..))+import Data.VectorSpace hiding (Sum (..))+import Control.Lens ((&), (.~), (%~))
src/Diagrams/Segment.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-}@@ -6,6 +7,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}@@ -54,16 +56,17 @@ -- $segmeas , SegCount(..)- , ArcLength(..), getArcLengthCached, getArcLengthFun, getArcLengthBounded+ , ArcLength(..)+ , getArcLengthCached, getArcLengthFun, getArcLengthBounded , TotalOffset(..)- , OffsetEnvelope(..)+ , OffsetEnvelope(..), oeOffset, oeEnvelope , SegMeasure ) where +import Control.Lens (makeLenses, Wrapped(..), iso, op) import Control.Applicative (liftA2) import Data.AffineSpace-import Data.Default.Class import Data.FingerTree import Data.Monoid.MList import Data.Semigroup@@ -75,7 +78,6 @@ import Diagrams.Located import Diagrams.Parametric import Diagrams.Solve-import Diagrams.Util ------------------------------------------------------------@@ -102,7 +104,7 @@ -- a fixed offset from its start. data Offset c v where OffsetOpen :: Offset Open v- OffsetClosed :: v -> Offset Closed v+ OffsetClosed :: !v -> Offset Closed v deriving instance Show v => Show (Offset c v) deriving instance Eq v => Eq (Offset c v)@@ -129,10 +131,10 @@ -- however, affected by other transformations such as rotations and -- scales. data Segment c v- = Linear (Offset c v)+ = Linear !(Offset c v) -- ^ A linear segment with given offset. - | Cubic v v (Offset c v)+ | Cubic !v !v !(Offset c v) -- ^ A cubic Bézier segment specified by -- three offsets from the starting -- point to the first control point,@@ -231,7 +233,7 @@ instance (InnerSpace v, OrderedField (Scalar v)) => Enveloped (Segment Closed v) where getEnvelope (s@(Linear {})) = mkEnvelope $ \v ->- maximum . map (\t -> ((s `atParam` t) <.> v) / magnitudeSq v) $ [0,1]+ maximum (map (\t -> ((s `atParam` t) <.> v)) [0,1]) / magnitudeSq v getEnvelope (s@(Cubic c1 c2 (OffsetClosed x2))) = mkEnvelope $ \v -> maximum .@@ -349,10 +351,10 @@ -- | Create a 'FixedSegment' from a located 'Segment'. mkFixedSeg :: AdditiveGroup v => Located (Segment Closed v) -> FixedSegment v-mkFixedSeg (viewLoc -> (p, Linear (OffsetClosed v)))- = FLinear p (p .+^ v)-mkFixedSeg (viewLoc -> (p, Cubic c1 c2 (OffsetClosed x2)))- = FCubic p (p .+^ c1) (p .+^ c2) (p .+^ x2)+mkFixedSeg ls =+ case viewLoc ls of+ (p, Linear (OffsetClosed v)) -> FLinear p (p .+^ v)+ (p, Cubic c1 c2 (OffsetClosed x2)) -> FCubic p (p .+^ c1) (p .+^ c2) (p .+^ x2) -- | Convert a 'FixedSegment' back into a located 'Segment'. fromFixedSeg :: AdditiveGroup v => FixedSegment v -> Located (Segment Closed v)@@ -382,26 +384,37 @@ -- automatically track various monoidal \"measures\" on segments. -- | A type to track the count of segments in a 'Trail'.-newtype SegCount = SegCount { getSegCount :: Sum Int }+newtype SegCount = SegCount (Sum Int) deriving (Semigroup, Monoid) +instance Wrapped (Sum Int) (Sum Int) SegCount SegCount+ where wrapped = iso SegCount $ \(SegCount x) -> x+ -- | A type to represent the total arc length of a chain of -- segments. The first component is a \"standard\" arc length, -- computed to within a tolerance of @10e-6@. The second component is -- a generic arc length function taking the tolerance as an -- argument.-newtype ArcLength v = ArcLength- { getArcLength :: (Sum (Interval (Scalar v)), Scalar v -> Sum (Interval (Scalar v))) } +newtype ArcLength v+ = ArcLength (Sum (Interval (Scalar v)), Scalar v -> Sum (Interval (Scalar v)))++instance (Scalar v ~ u, Scalar v' ~ u', u ~ u') => Wrapped+ (Sum (Interval u), u -> Sum (Interval u ))+ (Sum (Interval u'), u' -> Sum (Interval u'))+ (ArcLength v)+ (ArcLength v')+ where wrapped = iso ArcLength $ \(ArcLength x) -> x+ -- | Project out the cached arc length, stored together with error -- bounds. getArcLengthCached :: ArcLength v -> Interval (Scalar v)-getArcLengthCached = getSum . fst . getArcLength+getArcLengthCached = getSum . fst . op ArcLength -- | Project out the generic arc length function taking the tolerance as -- an argument. getArcLengthFun :: ArcLength v -> Scalar v -> Interval (Scalar v)-getArcLengthFun = fmap getSum . snd . getArcLength+getArcLengthFun = fmap getSum . snd . op ArcLength -- | Given a specified tolerance, project out the cached arc length if -- it is accurate enough; otherwise call the generic arc length@@ -418,8 +431,11 @@ -- | A type to represent the total cumulative offset of a chain of -- segments.-newtype TotalOffset v = TotalOffset { getTotalOffset :: v }+newtype TotalOffset v = TotalOffset v +instance Wrapped v v (TotalOffset v) (TotalOffset v)+ where wrapped = iso TotalOffset $ \(TotalOffset x) -> x+ instance AdditiveGroup v => Semigroup (TotalOffset v) where TotalOffset v1 <> TotalOffset v2 = TotalOffset (v1 ^+^ v2) @@ -432,15 +448,20 @@ -- combining the envelopes of two consecutive chains needs to take -- the offset of the the offset of the first into account. data OffsetEnvelope v = OffsetEnvelope- { oeOffset :: TotalOffset v- , oeEnvelope :: Envelope v+ { _oeOffset :: !(TotalOffset v)+ , _oeEnvelope :: Envelope v } +makeLenses ''OffsetEnvelope+ instance (InnerSpace v, OrderedField (Scalar v)) => Semigroup (OffsetEnvelope v) where (OffsetEnvelope o1 e1) <> (OffsetEnvelope o2 e2)- = OffsetEnvelope- (o1 <> o2)- (e1 <> moveOriginBy (negateV . getTotalOffset $ o1) e2)+ = let !negOff = negateV . op TotalOffset $ o1+ e2Off = moveOriginBy negOff e2+ !() = maybe () (\f -> f `seq` ()) $ appEnvelope e2Off+ in OffsetEnvelope+ (o1 <> o2)+ (e1 <> e2Off) -- | @SegMeasure@ collects up all the measurements over a chain of -- segments.
+ src/Diagrams/Tangent.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Tangent+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Computing tangent and normal vectors for segments and trails.+--+-----------------------------------------------------------------------------+module Diagrams.Tangent+ ( tangentAtParam+ , tangentAtStart+ , tangentAtEnd+ , normalAtParam+ , normalAtStart+ , normalAtEnd+ , Tangent(..)+ )+ where++import Control.Lens (cloneIso, (^.))++import Data.VectorSpace+import Diagrams.Core+import Diagrams.Located+import Diagrams.Parametric+import Diagrams.Segment+import Diagrams.Trail+import Diagrams.TwoD.Types (R2)+import Diagrams.TwoD.Vector (perp)++------------------------------------------------------------+-- Tangent+------------------------------------------------------------++-- | A newtype wrapper used to give different instances of+-- 'Parametric' and 'EndValues' that compute tangent vectors.+newtype Tangent t = Tangent t++type instance V (Tangent t) = V t++instance DomainBounds t => DomainBounds (Tangent t) where+ domainLower (Tangent t) = domainLower t+ domainUpper (Tangent t) = domainUpper t++type instance Codomain (Tangent (Located t)) = Codomain (Tangent t)++instance Parametric (Tangent t) => Parametric (Tangent (Located t)) where+ Tangent l `atParam` p = Tangent (unLoc l) `atParam` p++instance (DomainBounds t, EndValues (Tangent t))+ => EndValues (Tangent (Located t)) where+ atStart (Tangent l) = atStart (Tangent (unLoc l))+ atEnd (Tangent l) = atEnd (Tangent (unLoc l))++-- | Compute the tangent vector to a segment or trail at a particular+-- parameter.+--+-- Examples of more specific types this function can have include+--+-- * @Segment Closed R2 -> Double -> R2@+--+-- * @Trail' Line R2 -> Double -> R2@+--+-- * @Located (Trail R2) -> Double -> R2@+--+-- See the instances listed for the 'Tangent' newtype for more.+tangentAtParam :: Parametric (Tangent t) => t -> Scalar (V t) -> Codomain (Tangent t)+tangentAtParam t p = Tangent t `atParam` p++-- | Compute the tangent vector at the start of a segment or trail.+tangentAtStart :: EndValues (Tangent t) => t -> Codomain (Tangent t)+tangentAtStart = atStart . Tangent++-- | Compute the tangent vector at the end of a segment or trail.+tangentAtEnd :: EndValues (Tangent t) => t -> Codomain (Tangent t)+tangentAtEnd = atEnd . Tangent++--------------------------------------------------+-- Segment++type instance Codomain (Tangent (Segment Closed v)) = Codomain (Segment Closed v)++instance (VectorSpace v, Num (Scalar v))+ => Parametric (Tangent (Segment Closed v)) where+ Tangent (Linear (OffsetClosed v)) `atParam` _ = v+ Tangent (Cubic c1 c2 (OffsetClosed x2)) `atParam` p+ = (3*(3*p*p-4*p+1))*^c1 ^+^ (3*(2-3*p)*p)*^c2 ^+^ (3*p*p)*^x2++instance (VectorSpace v, Num (Scalar v))+ => EndValues (Tangent (Segment Closed v)) where+ atStart (Tangent (Linear (OffsetClosed v))) = v+ atStart (Tangent (Cubic c1 _ _)) = c1+ atEnd (Tangent (Linear (OffsetClosed v))) = v+ atEnd (Tangent (Cubic _ c2 (OffsetClosed x2))) = x2 ^-^ c2++--------------------------------------------------+-- Trail' and Trail++type instance Codomain (Tangent (Trail' c v)) = Codomain (Trail' c v)++instance ( Parametric (GetSegment (Trail' c v))+ , VectorSpace v+ , Num (Scalar v)+ )+ => Parametric (Tangent (Trail' c v)) where+ Tangent tr `atParam` p =+ case GetSegment tr `atParam` p of+ Nothing -> zeroV+ Just (_, seg, reparam) -> Tangent seg `atParam` (p ^. cloneIso reparam)++instance ( Parametric (GetSegment (Trail' c v))+ , EndValues (GetSegment (Trail' c v))+ , VectorSpace v+ , Num (Scalar v)+ )+ => EndValues (Tangent (Trail' c v)) where+ atStart (Tangent tr) =+ case atStart (GetSegment tr) of+ Nothing -> zeroV+ Just (_, seg, _) -> atStart (Tangent seg)+ atEnd (Tangent tr) =+ case atEnd (GetSegment tr) of+ Nothing -> zeroV+ Just (_, seg, _) -> atEnd (Tangent seg)++type instance Codomain (Tangent (Trail v)) = Codomain (Trail v)++instance ( InnerSpace v+ , OrderedField (Scalar v)+ , RealFrac (Scalar v)+ )+ => Parametric (Tangent (Trail v)) where+ Tangent tr `atParam` p+ = withTrail+ ((`atParam` p) . Tangent)+ ((`atParam` p) . Tangent)+ tr++instance ( InnerSpace v+ , OrderedField (Scalar v)+ , RealFrac (Scalar v)+ )+ => EndValues (Tangent (Trail v)) where+ atStart (Tangent tr) = withTrail (atStart . Tangent) (atStart . Tangent) tr+ atEnd (Tangent tr) = withTrail (atEnd . Tangent) (atEnd . Tangent) tr++------------------------------------------------------------+-- Normal+------------------------------------------------------------++-- | Compute the (unit) normal vector to a segment or trail at a+-- particular parameter.+--+-- Examples of more specific types this function can have include+--+-- * @Segment Closed R2 -> Double -> R2@+--+-- * @Trail' Line R2 -> Double -> R2@+--+-- * @Located (Trail R2) -> Double -> P2@+--+-- See the instances listed for the 'Tangent' newtype for more.+normalAtParam+ :: (Codomain (Tangent t) ~ R2, Parametric (Tangent t))+ => t -> Scalar (V t) -> R2+normalAtParam t p = normize (t `tangentAtParam` p)++-- | Compute the normal vector at the start of a segment or trail.+normalAtStart+ :: (Codomain (Tangent t) ~ R2, EndValues (Tangent t))+ => t -> R2+normalAtStart = normize . tangentAtStart++-- | Compute the normal vector at the end of a segment or trail.+normalAtEnd+ :: (Codomain (Tangent t) ~ R2, EndValues (Tangent t))+ => t -> R2+normalAtEnd = normize . tangentAtEnd++-- | Construct a normal vector from a tangent.+normize :: R2 -> R2+normize = negateV . perp . normalized
+ src/Diagrams/ThreeD.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.ThreeD+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- This module defines the three-dimensional vector space R^3,+-- three-dimensional transformations, and various predefined+-- three-dimensional shapes. This module re-exports useful+-- functionality from a group of more specific modules:+--+-- * "Diagrams.ThreeD.Types" defines basic types for two-dimensional+-- diagrams, including types representing the 3D Euclidean vector+-- space and various systems of representing directions.+--+-- * "Diagrams.ThreeD.Transform" defines R^3-specific transformations+-- such as rotation by an angle, and scaling, translation, and+-- reflection in the X, Y, and Z directions.+--+-- * "Diagrams.ThreeD.Shapes" defines three-dimensional solids,+-- e.g. spheres and cubes.+--+-- * "Diagrams.ThreeD.Vector" defines some special 3D vectors and+-- functions for converting between vectors and directions.+--+-- * "Diagrams.ThreeD.Light" and "Diagrams.ThreeD.Camera" define types needed+-- for rendering 3D geometry to (2D) images.+-----------------------------------------------------------------------------+module Diagrams.ThreeD+ ( module Diagrams.ThreeD.Types+ , module Diagrams.ThreeD.Transform+ , module Diagrams.ThreeD.Vector+ , module Diagrams.ThreeD.Shapes+ , module Diagrams.ThreeD.Light+ , module Diagrams.ThreeD.Camera+ ) where+++import Diagrams.ThreeD.Transform+import Diagrams.ThreeD.Vector+import Diagrams.ThreeD.Light+import Diagrams.ThreeD.Types+import Diagrams.ThreeD.Camera+import Diagrams.ThreeD.Shapes
+ src/Diagrams/ThreeD/Camera.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TemplateHaskell #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.ThreeD.Camera+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Types to specify viewpoint for 3D rendering.+--+-----------------------------------------------------------------------------++module Diagrams.ThreeD.Camera+ ( Camera -- do not export constructor+ -- These are safe to construct manually+ , PerspectiveLens(..), OrthoLens(..)+ , horizontalFieldOfView, verticalFieldOfView+ , orthoWidth, orthoHeight+ , camLoc, camForward, camUp, camRight, camLens+ , facing_ZCamera, mm50Camera+ , mm50, mm50Wide, mm50Narrow+ , aspect, camAspect+ )+ where++import Control.Lens (makeLenses)+import Data.Monoid+import Data.Cross++import Diagrams.Core+import Diagrams.ThreeD.Types+import Diagrams.ThreeD.Vector++-- Parameterize Camera on the lens type, so that Backends can express which+-- lenses they handle.+data Camera l = Camera+ { camLoc :: P3+ , forward :: R3+ , up :: R3+ , lens :: l+ }++class CameraLens l where+ -- | The natural aspect ratio of the projection.+ aspect :: l -> Double++-- | A perspective projection+data PerspectiveLens = PerspectiveLens+ { _horizontalFieldOfView :: Deg -- ^ Horizontal field of view.+ , _verticalFieldOfView :: Deg -- ^ Vertical field of view.+ }++makeLenses ''PerspectiveLens++instance CameraLens PerspectiveLens where+ aspect (PerspectiveLens h v) = angleRatio h v++-- | An orthographic projection+data OrthoLens = OrthoLens+ { _orthoWidth :: Double -- ^ Width+ , _orthoHeight :: Double -- ^ Height+ }++makeLenses ''OrthoLens++instance CameraLens OrthoLens where+ aspect (OrthoLens h v) = h / v++type instance V (Camera l) = R3++instance Transformable (Camera l) where+ transform t (Camera p f u l) =+ Camera (transform t p)+ (transform t f)+ (transform t u)+ l++instance IsPrim (Camera l)++instance Renderable (Camera l) NullBackend where+ render _ _ = mempty++-- | A camera at the origin facing along the negative Z axis, with its+-- up-axis coincident with the positive Y axis. The field of view is+-- chosen to match a 50mm camera on 35mm film. Note that Cameras take+-- up no space in the Diagram.+mm50Camera :: (Backend b R3, Renderable (Camera PerspectiveLens) b) => Diagram b R3+mm50Camera = facing_ZCamera mm50++-- | 'facing_ZCamera l' is a camera at the origin facing along the+-- negative Z axis, with its up-axis coincident with the positive Y+-- axis, with the projection defined by l.+facing_ZCamera :: (CameraLens l, Backend b R3, Renderable (Camera l) b) =>+ l -> Diagram b R3+facing_ZCamera l = mkQD (Prim $ Camera origin unit_Z unitY l)+ mempty mempty mempty (Query . const . Any $ False)++mm50, mm50Wide, mm50Narrow :: PerspectiveLens++-- | mm50 has the field of view of a 50mm lens on standard 35mm film,+-- hence an aspect ratio of 3:2.+mm50 = PerspectiveLens 40.5 27++-- | mm50Wide has the same vertical field of view as mm50, but an+-- aspect ratio of 1.6, suitable for wide screen computer monitors.+mm50Wide = PerspectiveLens 43.2 27++-- | mm50Narrow has the same vertical field of view as mm50, but an+-- aspect ratio of 4:3, for VGA and similar computer resulotions.+mm50Narrow = PerspectiveLens 36 27++camForward :: Direction d => Camera l -> d+camForward = direction . forward++camUp :: Direction d => Camera l -> d+camUp = direction . up++camRight :: Direction d => Camera l -> d+camRight c = direction right where+ right = cross3 (forward c) (up c)++camLens :: Camera l -> l+camLens = lens++camAspect :: CameraLens l => Camera l -> Double+camAspect = aspect . camLens
+ src/Diagrams/ThreeD/Light.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleContexts #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.ThreeD.Render+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Types to specify lighting for 3D rendering.+--+-----------------------------------------------------------------------------++module Diagrams.ThreeD.Light where++import Data.Colour+import Data.Monoid++import Diagrams.Core+import Diagrams.ThreeD.Types+import Diagrams.ThreeD.Vector++data PointLight = PointLight P3 (Colour Double)++data ParallelLight = ParallelLight R3 (Colour Double)++type instance V PointLight = R3+type instance V ParallelLight = R3++instance Transformable PointLight where+ transform t (PointLight p c) = PointLight (transform t p) c++instance Transformable ParallelLight where+ transform t (ParallelLight v c) = ParallelLight (transform t v) c++instance IsPrim PointLight+instance IsPrim ParallelLight++-- | Construct a Diagram with a single PointLight at the origin, which+-- takes up no space.+pointLight :: (Backend b R3, Renderable PointLight b)+ => Colour Double -- ^ The color of the light+ -> Diagram b R3+pointLight c = mkQD (Prim $ PointLight origin c) mempty mempty mempty+ (Query . const . Any $ False)++-- | Construct a Diagram with a single ParallelLight, which takes up no space.+parallelLight :: (Direction d, Backend b R3, Renderable ParallelLight b)+ => d -- ^ The direction in which the light travels.+ -> Colour Double -- ^ The color of the light.+ -> Diagram b R3+parallelLight d c = mkQD (Prim $ ParallelLight (fromDirection d) c)+ mempty mempty mempty (Query . const . Any $ False)
+ src/Diagrams/ThreeD/Transform.hs view
@@ -0,0 +1,159 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.ThreeD.Transform+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Transformations specific to three dimensions, with a few generic+-- transformations (uniform scaling, translation) also re-exported for+-- convenience.+--+-----------------------------------------------------------------------------++module Diagrams.ThreeD.Transform where++import Diagrams.Core+import qualified Diagrams.Core.Transform as T++import Diagrams.ThreeD.Types+import Diagrams.ThreeD.Vector+import Diagrams.Coordinates++import Control.Lens ((*~), (//~))+import Data.Semigroup++import Data.AffineSpace+import Data.Cross+import Data.VectorSpace++-- | Create a transformation which rotates by the given angle about+-- a line parallel the Z axis passing through the local origin.+-- A positive angle brings positive x-values towards the positive-y axis.+--+-- The angle can be expressed using any type which is an+-- instance of 'Angle'. For example, @aboutZ (1\/4 ::+-- 'Turn')@, @aboutZ (tau\/4 :: 'Rad')@, and @aboutZ (90 ::+-- 'Deg')@ all represent the same transformation, namely, a+-- counterclockwise rotation by a right angle. For more general rotations,+-- see 'rotationAbout'.+--+-- Note that writing @aboutZ (1\/4)@, with no type annotation, will+-- yield an error since GHC cannot figure out which sort of angle+-- you want to use.+aboutZ :: Angle a => a -> T3+aboutZ ang = fromLinear r (linv r) where+ r = rot theta <-> rot (-theta)+ Rad theta = convertAngle ang+ rot th (coords -> x :& y :& z) = (cos th * x - sin th * y) ^&+ (sin th * x + cos th * y) ^&+ z++-- | Like 'aboutZ', but rotates about the X axis, bringing positive y-values+-- towards the positive z-axis.+aboutX :: Angle a => a -> T3+aboutX ang = fromLinear r (linv r) where+ r = rot theta <-> rot (-theta)+ Rad theta = convertAngle ang+ rot th (coords -> x :& y :& z) = (x) ^&+ (cos th * y - sin th * z) ^&+ (sin th * y + cos th * z)++-- | Like 'aboutZ', but rotates about the Y axis, bringing postive+-- x-values towards the negative z-axis.+aboutY :: Angle a => a -> T3+aboutY ang = fromLinear r (linv r) where+ r = rot theta <-> rot (-theta)+ Rad theta = convertAngle ang+ rot th (coords -> x :& y :& z) = (cos th * x + sin th * z) ^&+ y ^&+ (-sin th * x + cos th * z)++-- | @rotationAbout p d a@ is a rotation about a line parallel to @d@+-- passing through @p@.+rotationAbout+ :: (Angle a, Direction d)+ => P3 -- ^ origin of rotation+ -> d -- ^ direction of rotation axis+ -> a -- ^ angle of rotation+ -> T3+rotationAbout p d a+ = mconcat [translation (negateV t),+ fromLinear r (linv r),+ translation t] where+ r = rot theta <-> rot (-theta)+ Rad theta = convertAngle a+ w = fromDirection d+ rot :: Double -> R3 -> R3+ rot th v = v ^* cos th ^+^+ cross3 w v ^* sin th ^+^+ w ^* ((w <.> v) * (1 - cos th))+ t = p .-. origin++-- | @pointAt about initial final@ produces a rotation which brings+-- the direction @initial@ to point in the direction @final@ by first+-- panning around @about@, then tilting about the axis perpendicular+-- to initial and final. In particular, if this can be accomplished+-- without tilting, it will be, otherwise if only tilting is+-- necessary, no panning will occur. The tilt will always be between+-- ± 1/4 turn.+pointAt :: Direction d => d -> d -> d -> T3+pointAt a i f = pointAt' (fromDirection a) (fromDirection i) (fromDirection f)++-- | pointAt' has the same behavior as 'pointAt', but takes vectors+-- instead of directions.+pointAt' :: R3 -> R3 -> R3 -> T3+pointAt' about initial final = tilt <> pan where+ inPanPlane = final ^-^ project final initial+ panAngle = angleBetween initial inPanPlane :: Turn+ pan = rotationAbout origin (direction about :: Spherical Turn) panAngle+ tiltAngle = angleBetween initial inPanPlane :: Turn+ tiltDir = direction $ cross3 inPanPlane about :: Spherical Turn+ tilt = rotationAbout origin tiltDir tiltAngle++-- Scaling -------------------------------------------------++-- | Construct a transformation which scales by the given factor in+-- the x direction.+scalingX :: Double -> T3+scalingX c = fromLinear s s+ where s = (_x *~ c) <-> (_x //~ c)++-- | Scale a diagram by the given factor in the x (horizontal)+-- direction. To scale uniformly, use 'scale'.+scaleX :: (Transformable t, V t ~ R3) => Double -> t -> t+scaleX = transform . scalingX++-- | Construct a transformation which scales by the given factor in+-- the y direction.+scalingY :: Double -> T3+scalingY c = fromLinear s s+ where s = (_y *~ c) <-> (_y //~ c)++-- | Scale a diagram by the given factor in the y (vertical)+-- direction. To scale uniformly, use 'scale'.+scaleY :: (Transformable t, V t ~ R3) => Double -> t -> t+scaleY = transform . scalingY++-- | Construct a transformation which scales by the given factor in+-- the z direction.+scalingZ :: Double -> T3+scalingZ c = fromLinear s s+ where s = (_z *~ c) <-> (_z //~ c)++-- | Scale a diagram by the given factor in the z direction. To scale+-- uniformly, use 'scale'.+scaleZ :: (Transformable t, V t ~ R3) => Double -> t -> t+scaleZ = transform . scalingZ++-- | Get the matrix equivalent of an affine transform, as a triple of+-- columns paired with the translation vector. This is mostly+-- useful for implementing backends.+onBasis :: T3 -> ((R3, R3, R3), R3)+onBasis t = ((x, y, z), v)+ where ((x:y:z:[]), v) = T.onBasis t
src/Diagrams/ThreeD/Types.hs view
@@ -1,10 +1,10 @@-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -21,20 +21,39 @@ module Diagrams.ThreeD.Types ( -- * 3D Euclidean space- R3, r3, unr3- , P3, p3, unp3+ R3, r3, unr3, mkR3+ , P3, p3, unp3, mkP3 , T3+ , r3Iso, p3Iso + -- * Two-dimensional angles+ -- | These are defined in "Diagrams.TwoD.Types" but+ -- reëxported here for convenience.+ , Angle(..)+ , Turn(Turn), asTurn+ , CircleFrac+ , Rad(Rad), asRad+ , Deg(Deg), asDeg++ , fullTurn, convertAngle, angleRatio++ -- * Directions in 3D+ , Direction(..)+ , Spherical(..)+ , asSpherical ) where -import Diagrams.Coordinates-import Diagrams.TwoD.Types-import Diagrams.Core+import Control.Applicative+import Control.Lens (Iso', iso, over, Wrapped, wrapped, _1, _2, _3) -import Control.Newtype+import Diagrams.Core+import Diagrams.TwoD.Types+import Diagrams.Coordinates -import Data.Basis-import Data.VectorSpace+import Data.AffineSpace.Point+import Data.Basis+import Data.Cross+import Data.VectorSpace ------------------------------------------------------------ -- 3D Euclidean space@@ -43,23 +62,31 @@ newtype R3 = R3 { unR3 :: (Double, Double, Double) } deriving (AdditiveGroup, Eq, Ord, Show, Read) -instance Newtype R3 (Double, Double, Double) where- pack = R3- unpack = unR3+r3Iso :: Iso' R3 (Double, Double, Double)+r3Iso = iso unR3 R3 -- | Construct a 3D vector from a triple of components. r3 :: (Double, Double, Double) -> R3-r3 = pack+r3 = R3 +-- | Curried version of `r3`.+mkR3 :: Double -> Double -> Double -> R3+mkR3 x y z = r3 (x, y, z)+ -- | Convert a 3D vector back into a triple of components. unr3 :: R3 -> (Double, Double, Double)-unr3 = unpack+unr3 = unR3 +-- | Lens wrapped isomorphisms for R3.+instance Wrapped (Double, Double, Double) (Double, Double, Double) R3 R3 where+ wrapped = iso r3 unr3+ {-# INLINE wrapped #-}+ type instance V R3 = R3 instance VectorSpace R3 where type Scalar R3 = Double- (*^) = over R3 . (*^)+ (*^) = over r3Iso . (*^) instance HasBasis R3 where type Basis R3 = Either () (Either () ()) -- = Basis (Double, Double, Double)@@ -75,7 +102,7 @@ type PrevDim R3 = R2 type Decomposition R3 = Double :& Double :& Double - (coords -> x :& y) & z = r3 (x,y,z)+ (coords -> x :& y) ^& z = r3 (x,y,z) coords (unR3 -> (x,y,z)) = x :& y :& z -- | Points in R^3.@@ -83,15 +110,80 @@ -- | Construct a 3D point from a triple of coordinates. p3 :: (Double, Double, Double) -> P3-p3 = pack . pack+p3 = P . R3 --- | Convert a 2D point back into a triple of coordinates.+-- | Convert a 3D point back into a triple of coordinates. unp3 :: P3 -> (Double, Double, Double)-unp3 = unpack . unpack+unp3 = unR3 . unPoint +p3Iso :: Iso' P3 (Double, Double, Double)+p3Iso = iso unp3 p3++-- | Curried version of `r3`.+mkP3 :: Double -> Double -> Double -> P3+mkP3 x y z = p3 (x, y, z)+ -- | Transformations in R^3. type T3 = Transformation R3 instance Transformable R3 where transform = apply +instance HasCross3 R3 where+ cross3 u v = r3 $ cross3 (unr3 u) (unr3 v)++--------------------------------------------------------------------------------+-- Direction++-- | Direction is a type class representing directions in R3. The interface is+-- based on that of the Angle class in 2D.++class Direction d where+ -- | Convert to polar angles+ toSpherical :: Angle a => d -> Spherical a++ -- | Convert from polar angles+ fromSpherical :: Angle a => Spherical a -> d++-- | A direction expressed as a pair of spherical coordinates.+-- `Spherical 0 0` is the direction of `unitX`. The first coordinate+-- represents rotation about the Z axis, the second rotation towards the Z axis.+data Spherical a = Spherical a a+ deriving (Show, Read, Eq)++instance Applicative Spherical where+ pure a = Spherical a a+ Spherical a b <*> Spherical c d = Spherical (a c) (b d)++instance Functor Spherical where+ fmap f s = pure f <*> s++instance (Angle a) => Direction (Spherical a) where+ toSpherical = fmap convertAngle+ fromSpherical = fmap convertAngle++-- | The identity function with a restricted type, for conveniently+-- restricting unwanted polymorphism. For example, @fromDirection+-- . asSpherical . camForward@ gives a unit vector pointing in the+-- direction of the camera view. Without @asSpherical@, the+-- intermediate type would be ambiguous.+asSpherical :: Spherical Turn -> Spherical Turn+asSpherical = id++instance HasX R3 where+ _x = r3Iso . _1++instance HasX P3 where+ _x = p3Iso . _1++instance HasY R3 where+ _y = r3Iso . _2++instance HasY P3 where+ _y = p3Iso . _2++instance HasZ R3 where+ _z = r3Iso . _3++instance HasZ P3 where+ _z = p3Iso . _3
+ src/Diagrams/ThreeD/Vector.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE FlexibleContexts+ , TypeFamilies+ , ViewPatterns+ #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.ThreeD.Vector+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Three-dimensional vectors.+--+-----------------------------------------------------------------------------+module Diagrams.ThreeD.Vector+ ( -- * Special 2D vectors+ unitX, unitY, unitZ, unit_X, unit_Y, unit_Z,++ -- * Converting between vectors and angles+ direction, fromDirection, angleBetween, angleBetweenDirs+ ) where++import Control.Lens (op)+import Data.VectorSpace+import Data.Cross++import Diagrams.ThreeD.Types+import Diagrams.Coordinates+++-- | The unit vector in the positive X direction.+unitX :: R3+unitX = 1 ^& 0 ^& 0++-- | The unit vector in the positive Y direction.+unitY :: R3+unitY = 0 ^& 1 ^& 0++-- | The unit vector in the positive Z direction.+unitZ :: R3+unitZ = 0 ^& 0 ^& 1++-- | The unit vector in the negative X direction.+unit_X :: R3+unit_X = (-1) ^& 0 ^& 0++-- | The unit vector in the negative Y direction.+unit_Y :: R3+unit_Y = 0 ^& (-1) ^& 0++-- | The unit vector in the negative Z direction.+unit_Z :: R3+unit_Z = 0 ^& 0 ^& (-1)+++-- | @direction v@ is the direction in which @v@ points. Returns an+-- unspecified value when given the zero vector as input.+direction :: Direction d => R3 -> d+direction v+ | r == 0 = fromSpherical $ Spherical zero zero+ | otherwise = fromSpherical $ Spherical θ φ where+ r = magnitude v+ (x,y,z) = unr3 v+ φ = Rad . asin $ z / r+ θ = Rad . atan2 y $ x+ zero = Rad $ 0++-- | @fromDirection d@ is the unit vector in the direction @d@.+fromDirection :: Direction d => d -> R3+fromDirection (toSpherical -> (Spherical θ' φ')) = r3 (x,y,z) where+ θ = op Rad $ θ'+ φ = op Rad $ φ'+ x = cos θ * cos φ+ y = sin θ * cos φ+ z = sin φ++-- | compute the positive angle between the two vectors in their common plane+angleBetween :: (Angle a, Num a, Ord a) => R3 -> R3 -> a+angleBetween v1 v2 = convertAngle . Rad $+ atan2 (magnitude $ cross3 v1 v2) (v1 <.> v2)++-- | compute the positive angle between the two vectors in their common plane+angleBetweenDirs :: (Direction d, Angle a, Num a, Ord a) => d -> d -> a+angleBetweenDirs d1 d2 = angleBetween (fromDirection d1) (fromDirection d2)
src/Diagrams/Trace.hs view
@@ -27,24 +27,28 @@ ) where -import Diagrams.Core (HasLinearMap, Point, Subdiagram,- location, origin, setTrace, trace)+import Diagrams.Core (HasLinearMap, Point, Subdiagram+ , location, origin, setTrace, trace+ , OrderedField) import Diagrams.Core.Trace import Data.Maybe-import Data.VectorSpace (Scalar, negateV)+import Data.Semigroup+import Data.VectorSpace (Scalar, negateV, InnerSpace) import Diagrams.Combinators (withTrace) -- | Compute the furthest point on the boundary of a subdiagram, -- beginning from the location (local origin) of the subdiagram and -- moving in the direction of the given vector. If there is no such -- point, the origin is returned; see also 'boundaryFromMay'.-boundaryFrom :: (HasLinearMap v, Ord (Scalar v)) => Subdiagram b v m -> v -> Point v+boundaryFrom :: (HasLinearMap v, OrderedField (Scalar v), InnerSpace v, Semigroup m)+ => Subdiagram b v m -> v -> Point v boundaryFrom s v = fromMaybe origin $ boundaryFromMay s v -- | Compute the furthest point on the boundary of a subdiagram, -- beginning from the location (local origin) of the subdiagram and -- moving in the direction of the given vector, or @Nothing@ if -- there is no such point.-boundaryFromMay :: (HasLinearMap v, Ord (Scalar v)) => Subdiagram b v m -> v -> Maybe (Point v)+boundaryFromMay :: (HasLinearMap v, OrderedField (Scalar v), Semigroup m, InnerSpace v)+ => Subdiagram b v m -> v -> Maybe (Point v) boundaryFromMay s v = traceP (location s) (negateV v) s
src/Diagrams/Trail.hs view
@@ -7,10 +7,15 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}+-- We have an orphan Transformable FingerTree instance here.+ ----------------------------------------------------------------------------- -- | -- Module : Diagrams.Trail@@ -91,9 +96,14 @@ , SegTree(..), trailMeasure, numSegs, offset + -- ** Extracting segments++ , GetSegment(..), getSegment+ ) where import Control.Arrow ((***))+import Control.Lens (AnIso', iso, view, op, Wrapped(..)) import Data.AffineSpace import Data.FingerTree (FingerTree, ViewL (..), ViewR (..), (<|), (|>))@@ -137,19 +147,27 @@ -- also easily slice and dice them according to the measures -- (/e.g./, split off the smallest number of segments from the -- beginning which have a combined arc length of at least 5).-newtype SegTree v = SegTree- { getSegTree :: FingerTree (SegMeasure v) (Segment Closed v) }++newtype SegTree v = SegTree (FingerTree (SegMeasure v) (Segment Closed v)) deriving (Eq, Ord, Show) +instance Wrapped (FingerTree (SegMeasure v) (Segment Closed v))+ (FingerTree (SegMeasure v) (Segment Closed v))+ (SegTree v)+ (SegTree v)+ where wrapped = iso SegTree $ \(SegTree x) -> x+ type instance V (SegTree v) = v deriving instance (OrderedField (Scalar v), InnerSpace v) => Monoid (SegTree v) deriving instance (OrderedField (Scalar v), InnerSpace v) => FT.Measured (SegMeasure v) (SegTree v)-deriving instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v))- => Transformable (SegTree v) +instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v))+ => Transformable (SegTree v) where+ transform t = SegTree . transform t . op SegTree+ type instance Codomain (SegTree v) = v instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v))@@ -181,7 +199,7 @@ | otherwise = case FT.viewl after of EmptyL -> emptySplit seg :< after' ->- case seg `splitAtParam` (snd . properFraction $ p * tSegs) of+ case seg `splitAtParam` (snd . propFrac $ p * tSegs) of (seg1, seg2) -> ( SegTree $ before |> seg1 , SegTree $ seg2 <| after' )@@ -190,6 +208,9 @@ tSegs = numSegs t emptySplit = (SegTree t, SegTree t) + reverseDomain (SegTree t) = SegTree $ FT.reverse t'+ where t' = FT.fmap' reverseSegment t+ -- XXX seems like it should be possible to collapse some of the -- above cases into one? @@ -220,7 +241,7 @@ in (p - 1)/tSegs + 1 | otherwise = case FT.viewl after of EmptyL -> 0- seg :< after' ->+ seg :< _ -> let p = arcLengthToParam (eps/2) seg (l - arcLength (eps/2) (SegTree before)) in (numSegs before + p) / tSegs@@ -248,14 +269,14 @@ FT.Measured (SegMeasure v) a ) => a -> c-numSegs = fromIntegral . trailMeasure 0 (getSum . getSegCount)+numSegs = fromIntegral . trailMeasure 0 (getSum . op SegCount) -- | Compute the total offset of anything measured by 'SegMeasure'. offset :: ( Floating (Scalar v), Ord (Scalar v), InnerSpace v, FT.Measured (SegMeasure v) t ) => t -> v-offset = trailMeasure zeroV (getTotalOffset . oeOffset)+offset = trailMeasure zeroV (op TotalOffset . view oeOffset) ------------------------------------------------------------ -- Trails ------------------------------------------------@@ -330,8 +351,8 @@ -- | A generic eliminator for 'Trail'', taking functions specifying -- what to do in the case of a line or a loop. withTrail' :: (Trail' Line v -> r) -> (Trail' Loop v -> r) -> Trail' l v -> r-withTrail' line loop t@(Line{}) = line t-withTrail' line loop t@(Loop{}) = loop t+withTrail' line _ t@(Line{}) = line t+withTrail' _ loop t@(Loop{}) = loop t deriving instance Show v => Show (Trail' l v) deriving instance Eq v => Eq (Trail' l v)@@ -361,7 +382,7 @@ getEnvelope = withTrail' ftEnv (ftEnv . cutLoop) where ftEnv :: Trail' Line v -> Envelope v- ftEnv (Line t) = trailMeasure mempty oeEnvelope $ t+ ftEnv (Line t) = trailMeasure mempty (view oeEnvelope) $ t instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v)) => Renderable (Trail' o v) NullBackend where@@ -371,13 +392,22 @@ => Parametric (Trail' l v) where atParam t p = withTrail' (\(Line segT) -> segT `atParam` p)- (\l -> cutLoop l `atParam` p')+ (\l -> cutLoop l `atParam` mod1 p) t- where- pf = snd . properFraction $ p- p' | p >= 0 = pf- | otherwise = 1 + pf +-- | Compute the remainder mod 1. Convenient for constructing loop+-- parameterizations that wrap around.+mod1 :: RealFrac a => a -> a+mod1 p = p'+ where+ pf = snd . propFrac $ p+ p' | p >= 0 = pf+ | otherwise = 1 + pf++-- Get rid of defaulting warnings+propFrac :: RealFrac a => a -> (Int, a)+propFrac = properFraction+ instance Num (Scalar v) => DomainBounds (Trail' l v) instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v))@@ -389,6 +419,8 @@ where (t1, t2) = splitAtParam t p + reverseDomain = reverseLine+ instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v)) => HasArcLength (Trail' l v) where arcLengthBounded eps =@@ -403,6 +435,137 @@ tr --------------------------------------------------+-- Extracting segments++-- | A newtype wrapper around trails which exists solely for its+-- 'Parametric', 'DomainBounds' and 'EndValues' instances. The idea+-- is that if @tr@ is a trail, you can write, /e.g./+--+-- @+-- getSegment tr `atParam` 0.6+-- @+--+-- or+--+-- @+-- atStart (getSegment tr)+-- @+--+-- to get the segment at parameter 0.6 or the first segment in the+-- trail, respectively.+--+-- The codomain for 'GetSegment', /i.e./ the result you get from+-- calling 'atParam', 'atStart', or 'atEnd', is @Maybe (v, Segment+-- Closed v, AnIso' (Scalar v) (Scalar v))@. @Nothing@ results if+-- the trail is empty; otherwise, you get:+--+-- * the offset from the start of the trail to the beginning of the+-- segment,+--+-- * the segment itself, and+--+-- * a reparameterization isomorphism: in the forward direction, it+-- translates from parameters on the whole trail to a parameters+-- on the segment. Note that for technical reasons you have to+-- call 'cloneIso' on the @AnIso'@ value to get a real isomorphism+-- you can use.+newtype GetSegment t = GetSegment t++-- | Create a 'GetSegment' wrapper around a trail, after which you can+-- call 'atParam', 'atStart', or 'atEnd' to extract a segment.+getSegment :: t -> GetSegment t+getSegment = GetSegment++type instance V (GetSegment t) = V t+type instance Codomain (GetSegment t)+ = Maybe+ ( V t -- offset from trail start to segment start+ , Segment Closed (V t) -- the segment+ , AnIso' (Scalar (V t)) (Scalar (V t)) -- reparameterization, trail <-> segment+ )++-- | Parameters less than 0 yield the first segment; parameters+-- greater than 1 yield the last. A parameter exactly at the+-- junction of two segments yields the second segment (/i.e./ the+-- one with higher parameter values).+instance (InnerSpace v, OrderedField (Scalar v))+ => Parametric (GetSegment (Trail' Line v)) where+ atParam (GetSegment (Line (SegTree ft))) p+ | p <= 0+ = case FT.viewl ft of+ EmptyL -> Nothing+ seg :< _ -> Just (zeroV, seg, reparam 0)++ | p >= 1+ = case FT.viewr ft of+ EmptyR -> Nothing+ ft' :> seg -> Just (offset ft', seg, reparam (n-1))++ | otherwise+ = let (before, after) = FT.split ((p*n <) . numSegs) $ ft+ in case FT.viewl after of+ EmptyL -> Nothing+ seg :< _ -> Just (offset before, seg, reparam (numSegs before))+ where+ n = numSegs ft+ reparam k = iso (subtract k . (*n))+ ((/n) . (+ k))++-- | The parameterization for loops wraps around, /i.e./ parameters+-- are first reduced \"mod 1\".+instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v))+ => Parametric (GetSegment (Trail' Loop v)) where+ atParam (GetSegment l) p = atParam (GetSegment (cutLoop l)) (mod1 p)++instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v))+ => Parametric (GetSegment (Trail v)) where+ atParam (GetSegment t) p+ = withTrail+ ((`atParam` p) . GetSegment)+ ((`atParam` p) . GetSegment)+ t++instance DomainBounds t => DomainBounds (GetSegment t) where+ domainLower (GetSegment t) = domainLower t+ domainUpper (GetSegment t) = domainUpper t++instance (InnerSpace v, OrderedField (Scalar v))+ => EndValues (GetSegment (Trail' Line v)) where+ atStart (GetSegment (Line (SegTree ft)))+ = case FT.viewl ft of+ EmptyL -> Nothing+ seg :< _ ->+ let n = numSegs ft+ in Just (zeroV, seg, iso (*n) (/n))++ atEnd (GetSegment (Line (SegTree ft)))+ = case FT.viewr ft of+ EmptyR -> Nothing+ ft' :> seg ->+ let n = numSegs ft+ in Just (offset ft', seg, iso (subtract (n-1) . (*n))+ ((/n) . (+ (n-1)))+ )++instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v))+ => EndValues (GetSegment (Trail' Loop v)) where+ atStart (GetSegment l) = atStart (GetSegment (cutLoop l))+ atEnd (GetSegment l) = atEnd (GetSegment (cutLoop l))++instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v))+ => EndValues (GetSegment (Trail v)) where+ atStart (GetSegment t)+ = withTrail+ (\l -> atStart (GetSegment l))+ (\l -> atStart (GetSegment l))+ t+ atEnd (GetSegment t)+ = withTrail+ (\l -> atEnd (GetSegment l))+ (\l -> atEnd (GetSegment l))+ t++-------------------------------------------------- -- The Trail type -- | @Trail@ is a wrapper around @Trail'@, hiding whether the@@ -484,6 +647,8 @@ => Sectionable (Trail v) where splitAtParam t p = withLine ((wrapLine *** wrapLine) . (`splitAtParam` p)) t + reverseDomain = reverseTrail+ instance (InnerSpace v, OrderedField (Scalar v), RealFrac (Scalar v)) => HasArcLength (Trail v) where arcLengthBounded = withLine . arcLengthBounded@@ -575,10 +740,10 @@ -- vectors, where each vector represents the offset from one vertex -- to the next. See also 'fromOffsets'. ----- <<diagrams/lineFromOffsetsEx.svg#diagram=lineFromOffsetsEx&width=300>>+-- <<diagrams/src_Diagrams_Trail_lineFromOffsetsEx.svg#diagram=lineFromOffsetsEx&width=300>> -- -- > import Diagrams.Coordinates--- > lineFromOffsetsEx = strokeLine $ lineFromOffsets [ 2 & 1, 2 & (-1), 2 & 0.5 ]+-- > lineFromOffsetsEx = strokeLine $ lineFromOffsets [ 2 ^& 1, 2 ^& (-1), 2 ^& 0.5 ] lineFromOffsets :: (InnerSpace v, OrderedField (Scalar v)) => [v] -> Trail' Line v lineFromOffsets = lineFromSegments . map straight@@ -603,11 +768,11 @@ -- construct, say, a @'Located' ('Trail'' 'Line' v)@ or a @'Located' -- ('Trail' v)@. ----- <<diagrams/lineFromVerticesEx.svg#diagram=lineFromVerticesEx&width=300>>+-- <<diagrams/src_Diagrams_Trail_lineFromVerticesEx.svg#diagram=lineFromVerticesEx&width=300>> -- -- > import Diagrams.Coordinates -- > lineFromVerticesEx = pad 1.1 . centerXY . strokeLine--- > $ lineFromVertices [origin, 0 & 1, 1 & 2, 5 & 1]+-- > $ lineFromVertices [origin, 0 ^& 1, 1 ^& 2, 5 ^& 1] lineFromVertices :: (InnerSpace v, OrderedField (Scalar v)) => [Point v] -> Trail' Line v lineFromVertices [] = emptyLine@@ -632,14 +797,13 @@ -- know happens to end where it starts, and then call 'glueLine' to -- turn it into a loop. ----- <<diagrams/glueLineEx.svg#diagram=glueLineEx&width=500>>+-- <<diagrams/src_Diagrams_Trail_glueLineEx.svg#diagram=glueLineEx&width=500>> ----- > import Diagrams.Coordinates--- > glueLineEx = pad 1.1 . hcat' with {sep = 1}+-- > glueLineEx = pad 1.1 . hcat' (with & sep .~ 1) -- > $ [almostClosed # strokeLine, almostClosed # glueLine # strokeLoop] -- > -- > almostClosed :: Trail' Line R2--- > almostClosed = fromOffsets [2 & (-1), (-3) & (-0.5), (-2) & 1, 1 & 0.5]+-- > almostClosed = fromOffsets $ map r2 [(2, -1), (-3, -0.5), (-2, 1), (1, 0.5)] -- -- @glueLine@ is left inverse to 'cutLoop', that is, --@@ -677,9 +841,9 @@ -- closeLine . lineFromVertices $ ps -- @ ----- <<diagrams/closeLineEx.svg#diagram=closeLineEx&width=500>>+-- <<diagrams/src_Diagrams_Trail_closeLineEx.svg#diagram=closeLineEx&width=500>> ----- > closeLineEx = pad 1.1 . centerXY . hcat' with {sep = 1}+-- > closeLineEx = pad 1.1 . centerXY . hcat' (with & sep .~ 1) -- > $ [almostClosed # strokeLine, almostClosed # closeLine # strokeLoop] closeLine :: Trail' Line v -> Trail' Loop v closeLine (Line t) = Loop t (Linear OffsetOpen)@@ -707,7 +871,7 @@ (_ , Cubic c1 c2 OffsetOpen) -> Line (SegTree (t |> Cubic c1 c2 off)) where offV :: v- offV = negateV . trailMeasure zeroV (getTotalOffset . oeOffset) $ t+ offV = negateV . trailMeasure zeroV (op TotalOffset .view oeOffset) $ t off = OffsetClosed offV -- | @cutTrail@ is a variant of 'cutLoop' for 'Trail'; it is the is@@ -770,7 +934,7 @@ -- -- but is more efficient. ----- <<diagrams/trailOffsetEx.svg#diagram=trailOffsetEx&width=300>>+-- <<diagrams/src_Diagrams_Trail_trailOffsetEx.svg#diagram=trailOffsetEx&width=300>> -- -- > trailOffsetEx = (strokeLine almostClosed <> showOffset) # centerXY # pad 1.1 -- > where showOffset = fromOffsets [trailOffset (wrapLine almostClosed)]@@ -790,7 +954,7 @@ -- there is no corresponding @loopOffset@ function because by -- definition it would be constantly zero.) lineOffset :: (InnerSpace v, OrderedField (Scalar v)) => Trail' Line v -> v-lineOffset (Line t) = trailMeasure zeroV (getTotalOffset . oeOffset) t+lineOffset (Line t) = trailMeasure zeroV (op TotalOffset . view oeOffset) t -- | Extract the vertices of a concretely located trail. Note that -- for loops, the starting vertex will /not/ be repeated at the end.@@ -802,7 +966,7 @@ -- Note that it does not make sense to ask for the vertices of a -- 'Trail' by itself; if you want the vertices of a trail -- with the first vertex at, say, the origin, you can use--- @trailVertices . (`at` origin)@.+-- @trailVertices . (\`at\` origin)@. trailVertices :: (InnerSpace v, OrderedField (Scalar v)) => Located (Trail v) -> [Point v] trailVertices (viewLoc -> (p,t))
src/Diagrams/TrailLike.hs view
@@ -30,6 +30,7 @@ import Data.AffineSpace ((.-.)) import Data.VectorSpace+import Control.Lens (view, wrapped) import Diagrams.Core import Diagrams.Located@@ -95,7 +96,7 @@ -- | Translationally invariant things are trail-like as long as the -- underlying type is. instance TrailLike t => TrailLike (TransInv t) where- trailLike = TransInv . trailLike+ trailLike = view wrapped . trailLike -- | 'Located' things are trail-like as long as the underlying type -- is. The location is taken to be the location of the input@@ -110,7 +111,14 @@ -- | Construct a trail-like thing from a list of segments, with the -- origin as the location. ----- XXX example/picture+-- <<diagrams/src_Diagrams_TrailLike_fromSegmentsEx.svg#diagram=fromSegmentsEx&height=200>>+--+-- > fromSegmentsEx = fromSegments+-- > [ straight (r2 (1,1))+-- > , bézier3 (r2 (1,1)) unitX unit_Y+-- > , straight unit_X+-- > ]+-- > # centerXY # pad 1.1 fromSegments :: TrailLike t => [Segment Closed (V t)] -> t fromSegments = fromLocSegments . (`at` origin) @@ -121,7 +129,15 @@ -- | Construct a trail-like thing of linear segments from a list -- of offsets, with the origin as the location. ----- XXX example/picture+-- <<diagrams/src_Diagrams_TrailLike_fromOffsetsEx.svg#diagram=fromOffsetsEx&width=300>>+--+-- > fromOffsetsEx = fromOffsets+-- > [ unitX+-- > , unitX # rotateBy (1/6)+-- > , unitX # rotateBy (-1/6)+-- > , unitX+-- > ]+-- > # centerXY # pad 1.1 fromOffsets :: TrailLike t => [V t] -> t fromOffsets = trailLike . (`at` origin) . trailFromOffsets @@ -135,7 +151,21 @@ -- vertices are given, the empty trail is used with the origin as -- the location. ----- XXX example/picture+-- <<diagrams/src_Diagrams_TrailLike_fromVerticesEx.svg#diagram=fromVerticesEx&width=300>>+--+-- > import Data.List (transpose)+-- >+-- > fromVerticesEx =+-- > ( [ pentagon 1+-- > , pentagon 1.3 # rotateBy (1/15)+-- > , pentagon 1.5 # rotateBy (2/15)+-- > ]+-- > # transpose+-- > # concat+-- > )+-- > # fromVertices+-- > # closeTrail # strokeTrail+-- > # centerXY # pad 1.1 fromVertices :: TrailLike t => [Point (V t)] -> t fromVertices [] = trailLike (emptyTrail `at` origin) fromVertices ps@(p:_) = trailLike (trailFromSegments (segmentsFromVertices ps) `at` p)@@ -145,12 +175,26 @@ segmentsFromVertices vvs@(_:vs) = map straight (zipWith (flip (.-.)) vvs vs) -- | Create a linear trail between two given points.+--+-- <<diagrams/src_Diagrams_TrailLike_twiddleEx.svg#diagram=twiddleEx&width=300>>+--+-- > twiddleEx+-- > = mconcat ((~~) <$> hexagon 1 <*> hexagon 1)+-- > # centerXY # pad 1.1 (~~) :: TrailLike t => Point (V t) -> Point (V t) -> t p1 ~~ p2 = fromVertices [p1, p2] -- | Given a concretely located trail, \"explode\" it by turning each -- segment into its own separate trail. Useful for (say) applying a -- different style to each segment.+--+-- <<diagrams/src_Diagrams_TrailLike_explodeTrailEx.svg#diagram=explodeTrailEx&width=300>>+--+-- > explodeTrailEx+-- > = pentagon 1+-- > # explodeTrail -- generate a list of diagrams+-- > # zipWith lc [orange, green, yellow, red, blue]+-- > # mconcat # centerXY # pad 1.1 explodeTrail :: (VectorSpace (V t), TrailLike t) => Located (Trail (V t)) -> [t] explodeTrail = map (mkTrail . fromFixedSeg) . fixTrail where
src/Diagrams/TwoD.hs view
@@ -42,6 +42,9 @@ -- * "Diagrams.TwoD.Shapes" defines other two-dimensional shapes, -- e.g. various polygons. --+-- * "Diagrams.TwoD.Arrow" contains tools for drawing arrows between+-- things.+-- -- * "Diagrams.TwoD.Text" defines primitive text diagrams. -- -- * "Diagrams.TwoD.Image" allows importing external images into diagrams.@@ -58,24 +61,27 @@ ----------------------------------------------------------------------------- module Diagrams.TwoD ( -- * R^2- R2, r2, unr2- , P2, p2, unp2+ R2, r2, unr2, mkR2+ , P2, p2, unp2, mkP2 , T2 , unitX, unitY, unit_X, unit_Y- , direction, fromDirection, e+ , direction, angleBetween, fromDirection -- * Angles , tau , Angle(..)- , Turn(..), CircleFrac, Rad(..), Deg(..)- , fullCircle, convertAngle+ , Turn(..), asTurn, CircleFrac+ , Rad(..), asRad+ , Deg(..), asDeg+ , fullTurn, fullCircle, convertAngle -- * Paths -- ** Stroking- , stroke, stroke', strokeT, strokeT', strokeLine, strokeLoop- , strokeLocT, strokeLocLine, strokeLocLoop+ , stroke, stroke', strokeTrail, strokeT, strokeTrail', strokeT'+ , strokeLine, strokeLoop+ , strokeLocTrail, strokeLocT, strokeLocLine, strokeLocLoop , FillRule(..), fillRule- , StrokeOpts(..)+ , StrokeOpts(..), vertexNames, queryFillRule -- ** Clipping , clipBy@@ -93,10 +99,13 @@ , arc' , arcCW , wedge+ , arcBetween+ , annularWedge -- ** General polygons , polygon, polyTrail- , PolygonOpts(..), PolyType(..), PolyOrientation(..)+ , PolygonOpts(..), polyType, polyOrient, polyCenter+ , PolyType(..), PolyOrientation(..) -- ** Star polygons , StarOpts(..), star@@ -108,6 +117,7 @@ , square , pentagon , hexagon+ , heptagon , septagon , octagon , nonagon@@ -121,14 +131,40 @@ -- ** Other shapes , roundedRect, roundedRect'- , RoundedRectOpts(..)+ , RoundedRectOpts(..), radiusTL, radiusTR, radiusBL, radiusBR + -- ** Arrows+ , arrow, arrow'+ , arrowAt, arrowAt'+ , arrowBetween, arrowBetween'+ , connect, connect'+ , connectPerim, connectPerim'+ , connectOutside, connectOutside'+ , straightShaft+ , module Diagrams.TwoD.Arrowheads++ , ArrowOpts(..)++ , arrowHead+ , arrowTail+ , arrowShaft+ , headSize+ , tailSize+ , headGap+ , tailGap+ , headColor+ , headStyle+ , tailColor+ , tailStyle+ , shaftColor+ , shaftStyle+ -- * Text , text, topLeftText, alignedText, baselineText , font, fontSize, italic, oblique, bold -- * Images- , image+ , Image, image -- * Transformations -- ** Rotation@@ -175,6 +211,11 @@ , alignX, alignY , centerX, centerY, centerXY + -- * Snugging+ , snugL, snugR, snugT, snugB, snugTL, snugTR, snugBL, snugBR+ , snugX, snugY+ , snugCenterX, snugCenterY, snugCenterXY+ -- * Size -- ** Computing size , width, height, size2D, sizeSpec2D@@ -190,13 +231,15 @@ -- * Visual aids for understanding the internal model , showOrigin , showOrigin'- , OriginOpts(..)+ , OriginOpts(..), oColor, oScale, oMinSize , showLabels ) where import Diagrams.TwoD.Align import Diagrams.TwoD.Arc+import Diagrams.TwoD.Arrow+import Diagrams.TwoD.Arrowheads import Diagrams.TwoD.Combinators import Diagrams.TwoD.Ellipse import Diagrams.TwoD.Image
src/Diagrams/TwoD/Adjust.hs view
@@ -40,8 +40,6 @@ import Data.Default.Class -import Data.Colour.Names (black)- -- | Set default attributes of a 2D diagram (in case they have not -- been set): --
src/Diagrams/TwoD/Align.hs view
@@ -1,6 +1,5 @@-{-# LANGUAGE FlexibleContexts- , TypeFamilies- #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Align@@ -12,86 +11,141 @@ -- "Diagrams.Align" for more general alignment combinators. -- -- The basic idea is that alignment is achieved by moving diagrams'--- local origins relative to their envelopes. For example, to align--- several diagrams along their tops, we first move their local--- origins to the upper edge of their envelopes (using e.g. @map--- 'alignTop'@), and then put them together with their local origins--- along a horizontal line (using e.g. 'hcat' from--- "Diagrams.TwoD.Combinators").+-- local origins relative to their envelopes or traces (or some other+-- sort of boundary). For example, to align several diagrams along+-- their tops, we first move their local origins to the upper edge of+-- their boundary (using e.g. @map 'alignTop'@), and then put them+-- together with their local origins along a horizontal line (using+-- e.g. 'hcat' from "Diagrams.TwoD.Combinators"). -- ----------------------------------------------------------------------------- module Diagrams.TwoD.Align ( -- * Absolute alignment+ -- ** Align by envelope alignL, alignR, alignT, alignB , alignTL, alignTR, alignBL, alignBR + -- ** Align by trace+ , snugL, snugR, snugT, snugB+ , snugTL, snugTR, snugBL, snugBR+ -- * Relative alignment- , alignX, alignY+ , alignX, snugX, alignY, snugY -- * Centering , centerX, centerY, centerXY+ , snugCenterX, snugCenterY, snugCenterXY ) where -import Diagrams.Core+import Diagrams.Core -import Diagrams.TwoD.Types-import Diagrams.TwoD.Vector-import Diagrams.Align+import Diagrams.Align+import Diagrams.TwoD.Types+import Diagrams.TwoD.Vector -import Data.VectorSpace+import Data.VectorSpace -- | Align along the left edge, i.e. translate the diagram in a -- horizontal direction so that the local origin is on the left edge -- of the envelope.-alignL :: (Alignable a, V a ~ R2) => a -> a+alignL :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a alignL = align (negateV unitX) +snugL :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugL = snug (negateV unitX)+ -- | Align along the right edge.-alignR :: (Alignable a, V a ~ R2) => a -> a+alignR :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a alignR = align unitX +snugR :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugR = snug unitX++ -- | Align along the top edge.-alignT :: (Alignable a, V a ~ R2) => a -> a+alignT :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a alignT = align unitY +snugT:: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugT = snug unitY+ -- | Align along the bottom edge.-alignB :: (Alignable a, V a ~ R2) => a -> a+alignB :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a alignB = align (negateV unitY) -alignTL, alignTR, alignBL, alignBR :: (Alignable a, V a ~ R2) => a -> a+snugB :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugB = snug (negateV unitY)++alignTL, alignTR, alignBL, alignBR :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a alignTL = alignT . alignL alignTR = alignT . alignR alignBL = alignB . alignL alignBR = alignB . alignR --- | @alignX@ moves the local origin horizontally as follows:+snugTL, snugTR, snugBL, snugBR+ :: (Fractional (Scalar (V a)), Alignable a, Traced a, HasOrigin a, V a ~ R2)+ => a -> a+snugTL = snugT . snugL+snugTR = snugT . snugR+snugBL = snugB . snugL+snugBR = snugB . snugR++-- | @alignX@ and @snugX@ move the local origin horizontally as follows: ----- * @alignX (-1)@ moves the local origin to the left edge of the envelope;+-- * @alignX (-1)@ moves the local origin to the left edge of the boundary; -- -- * @align 1@ moves the local origin to the right edge; -- -- * any other argument interpolates linearly between these. For -- example, @alignX 0@ centers, @alignX 2@ moves the origin one -- \"radius\" to the right of the right edge, and so on.-alignX :: (Alignable a, V a ~ R2) => Double -> a -> a+--+-- * @snugX@ works the same way.++alignX :: (Alignable a, HasOrigin a, V a ~ R2) => Double -> a -> a alignX = alignBy unitX +-- | See the documentation for 'alignX'.+snugX :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => Double -> a -> a+snugX = snugBy unitX+ -- | Like 'alignX', but moving the local origin vertically, with an -- argument of @1@ corresponding to the top edge and @(-1)@ corresponding -- to the bottom edge.-alignY :: (Alignable a, V a ~ R2) => Double -> a -> a+alignY :: (Alignable a, HasOrigin a, V a ~ R2) => Double -> a -> a alignY = alignBy unitY +snugY :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => Double -> a -> a+snugY = snugBy unitY+ -- | Center the local origin along the X-axis.-centerX :: (Alignable a, V a ~ R2) => a -> a+centerX :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a centerX = alignBy unitX 0 +snugCenterX :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugCenterX = snugBy unitX 0+ -- | Center the local origin along the Y-axis.-centerY :: (Alignable a, V a ~ R2) => a -> a+centerY :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a centerY = alignBy unitY 0 +snugCenterY :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugCenterY = snugBy unitY 0+ -- | Center along both the X- and Y-axes.-centerXY :: (Alignable a, V a ~ R2) => a -> a+centerXY :: (Alignable a, HasOrigin a, V a ~ R2) => a -> a centerXY = centerX . centerY++snugCenterXY :: (Fractional (Scalar (V a)), Alignable a, Traced a,+ HasOrigin a, V a ~ R2) => a -> a+snugCenterXY = snugCenterX . snugCenterY
src/Diagrams/TwoD/Arc.hs view
@@ -19,22 +19,24 @@ , bezierFromSweep , wedge+ , arcBetween+ , annularWedge ) where -import Diagrams.Coordinates import Diagrams.Core import Diagrams.Located (at)-import Diagrams.Path import Diagrams.Segment import Diagrams.Trail import Diagrams.TrailLike import Diagrams.TwoD.Transform import Diagrams.TwoD.Types-import Diagrams.TwoD.Vector (e, unitX)+import Diagrams.TwoD.Vector (direction, e, unitX) import Diagrams.Util (tau, ( # )) +import Data.AffineSpace ((.-.)) import Data.Semigroup ((<>))-import Data.VectorSpace (negateV, (*^), (^-^))+import Data.VectorSpace (magnitude, negateV, (*^), (^-^))+import Diagrams.Coordinates -- For details of this approximation see: -- http://www.tinaja.com/glib/bezcirc2.pdf@@ -46,7 +48,7 @@ bezierFromSweepQ1 :: Rad -> Segment Closed R2 bezierFromSweepQ1 s = fmap (^-^ v) . rotate (s/2) $ bezier3 c2 c1 p0 where p0@(coords -> x :& y) = rotate (s/2) v- c1 = ((4-x)/3) & ((1-x)*(3-x)/(3*y))+ c1 = ((4-x)/3) ^& ((1-x)*(3-x)/(3*y)) c2 = reflectY c1 v = unitX @@ -89,18 +91,18 @@ -- 'Trail' of a radius one arc counterclockwise between the two angles. arcT :: Angle a => a -> a -> Trail R2 arcT start end- | e < s = arcT s (e + fromIntegral d)- | otherwise = (if sweep >= tau then glueTrail else id)- $ trailFromSegments bs+ | end' < start' = arcT start' (end' + fromIntegral d)+ | otherwise = (if sweep >= tau then glueTrail else id)+ $ trailFromSegments bs where sweep = convertAngle $ end - start bs = map (rotate start) . bezierFromSweep $ sweep -- We want to compare the start and the end and in case -- there isn't some law about 'Angle' ordering, we use a -- known 'Angle' for that.- s = convertAngle start :: Turn- e = convertAngle end- d = ceiling (s - e) :: Integer+ start' = convertAngle start :: Turn+ end' = convertAngle end+ d = ceiling (start' - end') :: Integer -- | Given a start angle @s@ and an end angle @e@, @'arc' s e@ is the -- path of a radius one arc counterclockwise between the two angles.@@ -124,6 +126,11 @@ -- the two angles. If a negative radius is given, the arc will -- be clockwise, otherwise it will be counterclockwise. The origin -- of the arc is its center.+--+-- <<diagrams/src_Diagrams_TwoD_Arc_arc'Ex.svg#diagram=arc'Ex&width=300>>+--+-- > arc'Ex = mconcat [ arc' r 0 (1/4 :: Turn) | r <- [0.5,-1,1.5] ]+-- > # centerXY # pad 1.1 arc' :: (Angle a, TrailLike p, V p ~ R2) => Double -> a -> a -> p arc' r start end = trailLike $ scale (abs r) ts `at` (rotate start $ p2 (abs r,0)) where ts | r < 0 = reverseTrail $ arcT end start@@ -131,8 +138,72 @@ -- | Create a circular wedge of the given radius, beginning at the -- first angle and extending counterclockwise to the second.+--+-- <<diagrams/src_Diagrams_TwoD_Arc_wedgeEx.svg#diagram=wedgeEx&width=400>>+--+-- > wedgeEx = hcat' (with & sep .~ 0.5)+-- > [ wedge 1 (0 :: Turn) (1/4)+-- > , wedge 1 (7/30 :: Turn) (11/30)+-- > , wedge 1 (1/8 :: Turn) (7/8)+-- > ]+-- > # fc blue+-- > # centerXY # pad 1.1 wedge :: (Angle a, TrailLike p, V p ~ R2) => Double -> a -> a -> p-wedge r a1 a2 = trailLike . (`at` origin) . wrapLine+wedge r a1 a2 = trailLike . (`at` origin) . glueTrail . wrapLine $ fromOffsets [r *^ e a1] <> arc a1 a2 # scale r <> fromOffsets [r *^ negateV (e a2)]++-- | @arcBetween p q height@ creates an arc beginning at @p@ and+-- ending at @q@, with its midpoint at a distance of @abs height@+-- away from the straight line from @p@ to @q@. A positive value of+-- @height@ results in an arc to the left of the line from @p@ to+-- @q@; a negative value yields one to the right.+--+-- <<diagrams/src_Diagrams_TwoD_Arc_arcBetweenEx.svg#diagram=arcBetweenEx&width=300>>+--+-- > arcBetweenEx = mconcat+-- > [ arcBetween origin (p2 (2,1)) ht | ht <- [-0.2, -0.1 .. 0.2] ]+-- > # centerXY # pad 1.1+arcBetween :: (TrailLike t, V t ~ R2) => P2 -> P2 -> Double -> t+arcBetween p q ht = trailLike (a # rotateBy (direction v) # moveTo p)+ where+ h = abs ht+ isStraight = h < 0.00001+ v = q .-. p+ d = magnitude (q .-. p)+ th = acos ((d*d - 4*h*h)/(d*d + 4*h*h))+ r = d/(2*sin th)+ mid | ht >= 0 = tau/4+ | otherwise = 3*tau/4+ st = mid - Rad th+ end = mid + Rad th+ a | isStraight+ = fromOffsets [d *^ unitX]+ | otherwise+ = arc st end+ # scale r+ # translateY ((if ht > 0 then negate else id) (r-h))+ # translateX (d/2)+ # (if ht > 0 then reverseLocTrail else id)++-- | Create an annular wedge of the given radii, beginning at the+-- first angle and extending counterclockwise to the second.+-- The radius of the outer circle is given first.+--+-- <<diagrams/src_Diagrams_TwoD_Arc_annularWedgeEx.svg#diagram=annularWedgeEx&width=400>>+--+-- > annularWedgeEx = hcat' (with & sep .~ 0.50)+-- > [ annularWedge 1 0.5 (0 :: Turn) (1/4)+-- > , annularWedge 1 0.3 (7/30 :: Turn) (11/30)+-- > , annularWedge 1 0.7 (1/8 :: Turn) (7/8)+-- > ]+-- > # fc blue+-- > # centerXY # pad 1.1+annularWedge :: (Angle a, TrailLike p, V p ~ R2) => Double -> Double -> a -> a -> p+annularWedge r1' r2' a1 a2 = trailLike . (`at` o) . glueTrail . wrapLine+ $ fromOffsets [(r1'-r2') *^ e a1]+ <> arc a1 a2 # scale r1'+ <> fromOffsets [(r1'-r2') *^ negateV (e a2)]+ <> arcCW a2 a1 # scale r2'+ where o = origin # translate (r2' *^ e a1)
+ src/Diagrams/TwoD/Arrow.hs view
@@ -0,0 +1,513 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.TwoD.Arrow+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Drawing arrows in two dimensions. For a tutorial on drawing arrows+-- using this module, see the diagrams website:+-- <http://projects.haskell.org/diagrams/doc/arrow.html>.+--+-----------------------------------------------------------------------------+++module Diagrams.TwoD.Arrow+ ( -- * Examples+ -- ** Example 1+-- | <<diagrams/src_Diagrams_TwoD_Arrow_example1.svg#diagram=example1&width=500>>+--+-- > -- Connecting two diagrams at their origins.+-- >+-- > sq = square 2 # showOrigin # lc darkgray # lw 0.07+-- > ds = (sq # named "left") ||| strutX 3 ||| (sq # named "right")+-- >+-- > shaft = cubicSpline False ( map p2 [(0, 0), (1, 0), (1, 0.2), (2, 0.2)])+-- >+-- > example1 = ds # connect' (with & arrowHead .~ dart & headSize .~ 0.6+-- > & tailSize .~ 0.5 & arrowTail .~ quill+-- > & shaftStyle %~ lw 0.02 & arrowShaft .~ shaft)+-- > "left" "right" # pad 1.1++ -- ** Example 2++-- | <<diagrams/src_Diagrams_TwoD_Arrow_example2.svg#diagram=example2&width=500>>+--+-- > -- Comparing connect, connectPerim, and arrowAt.+-- >+-- > oct = octagon 1 # lc darkgray # lw 0.10 # showOrigin+-- > dias = oct # named "first" ||| strut 3 ||| oct # named "second"+-- >+-- > -- Connect two diagrams and two points on their trails.+-- > ex12 = dias # connect "first" "second"+-- > # connectPerim "first" "second" (15/16 :: Turn) (9/16 :: Turn)+-- >+-- > -- Place an arrow at (0,0) the size and direction of (0,1).+-- > ex3 = arrowAt origin unit_Y+-- >+-- > example2 = (ex12 <> ex3) # centerXY # pad 1.1++ -- * Creating arrows+ arrow+ , arrow'+ , arrowAt+ , arrowAt'+ , arrowBetween+ , arrowBetween'+ , connect+ , connect'+ , connectPerim+ , connectPerim'+ , connectOutside+ , connectOutside'+ , straightShaft++ -- * Options+ , ArrowOpts(..)++ , arrowHead+ , arrowTail+ , arrowShaft+ , headSize+ , tailSize+ , headGap+ , tailGap+ , headColor+ , headStyle+ , tailColor+ , tailStyle+ , shaftColor+ , shaftStyle++ -- | See "Diagrams.TwoD.Arrowheads" for a list of standard+ -- arrowheads and help creating your own.+ , module Diagrams.TwoD.Arrowheads+ ) where++import Control.Arrow (first)+import Control.Lens (Lens', Setter',+ generateSignatures,+ lensRules, makeLensesWith,+ (%~), (&), (.~), (^.))+import Data.AffineSpace+import Data.Default.Class+import Data.Functor ((<$>))+import Data.Maybe (fromJust, fromMaybe)+import Data.Monoid (mempty, (<>))+import Data.Monoid.Coproduct (untangle)+import Data.Monoid.Split+import Data.Semigroup (option)+import Data.VectorSpace++import Data.Colour hiding (atop)+import Diagrams.Attributes+import Diagrams.Core+import Diagrams.Core.Types (QDiaLeaf (..), mkQD')++import Diagrams.Parametric+import Diagrams.Path+import Diagrams.Solve (quadForm)+import Diagrams.Tangent (tangentAtEnd, tangentAtStart)+import Diagrams.Trail+import Diagrams.TwoD.Arrowheads+import Diagrams.TwoD.Path (strokeT)+import Diagrams.TwoD.Transform (rotate, rotateBy, translateX)+import Diagrams.TwoD.Transform.ScaleInv (scaleInvPrim)+import Diagrams.TwoD.Types+import Diagrams.TwoD.Vector (direction, unitX, unit_X)+import Diagrams.Util (( # ))++data ArrowOpts+ = ArrowOpts+ { _arrowHead :: ArrowHT+ , _arrowTail :: ArrowHT+ , _arrowShaft :: Trail R2+ , _headSize :: Double+ , _tailSize :: Double+ , _headGap :: Double+ , _tailGap :: Double+ , _headStyle :: Style R2+ , _tailStyle :: Style R2+ , _shaftStyle :: Style R2+ }++-- | Straight line arrow shaft.+straightShaft :: Trail R2+straightShaft = trailFromOffsets [unitX]++instance Default ArrowOpts where+ def = ArrowOpts+ { _arrowHead = dart+ , _arrowTail = noTail+ , _arrowShaft = trailFromOffsets [unitX]+ , _headSize = 0.3+ , _tailSize = 0.3+ , _headGap = 0+ , _tailGap = 0++ -- See note [Default arrow style attributes]+ , _headStyle = mempty+ , _tailStyle = mempty+ , _shaftStyle = mempty+ }++makeLensesWith (lensRules & generateSignatures .~ False) ''ArrowOpts++-- | A shape to place at the head of the arrow.+arrowHead :: Lens' ArrowOpts ArrowHT++-- | A shape to place at the tail of the arrow.+arrowTail :: Lens' ArrowOpts ArrowHT++-- | The trail to use for the arrow shaft.+arrowShaft :: Lens' ArrowOpts (Trail R2)++-- | Radius of a circumcircle around the head.+headSize :: Lens' ArrowOpts Double++-- | Radius of a circumcircle around the tail.+tailSize :: Lens' ArrowOpts Double++-- | Distance to leave between the head and the target point.+headGap :: Lens' ArrowOpts Double+-- | Distance to leave between the starting point and the tail.+tailGap :: Lens' ArrowOpts Double++-- | Style to apply to the head. @headStyle@ is modified by using the lens+-- combinator @%~@ to change the current style. For example, to change+-- an opaque black arrowhead to translucent orange:+-- @(with & headStyle %~ fc orange . opacity 0.75)@.+headStyle :: Lens' ArrowOpts (Style R2)++-- | Style to apply to the tail. See `headStyle`.+tailStyle :: Lens' ArrowOpts (Style R2)++-- | Style to apply to the shaft. See `headStyle`.+shaftStyle :: Lens' ArrowOpts (Style R2)++-- | A lens for setting or modifying the color of an arrowhead. For+-- example, one may write @... (with & headColor .~ blue)@ to get an+-- arrow with a blue head, or @... (with & headColor %~ blend 0.5+-- white)@ to make an arrow's head a lighter color. For more general+-- control over the style of arrowheads, see 'headStyle'.+--+-- Note that the most general type of @headColor@ would be+--+-- @+-- (Color c, Color c') => Setter ArrowOpts ArrowOpts c c'+-- @+--+-- but that can cause problems for type inference when setting the+-- color. However, using it at that more general type may+-- occasionally be useful, for example, if you want to apply some+-- opacity to a color, as in @... (with & headColor %~+-- (\`withOpacity\` 0.5))@. If you want the more general type, you+-- can use @'headStyle' . 'styleFillColor'@ in place of @headColor@.+headColor :: Color c => Setter' ArrowOpts c+headColor = headStyle . styleFillColor++-- | A lens for setting or modifying the color of an arrow+-- tail. See 'headColor'.+tailColor :: Color c => Setter' ArrowOpts c+tailColor = tailStyle . styleFillColor++-- | A lens for setting or modifying the color of an arrow+-- shaft. See 'headColor'.+shaftColor :: Color c => Setter' ArrowOpts c+shaftColor = shaftStyle . styleLineColor++-- Set the default shaft style of an `ArrowOpts` record by applying the+-- default style after all other styles have been applied.+-- The semigroup stucture of the lw attribute will insure that the default+-- is only used if it has not been set in @opts@.+shaftSty :: ArrowOpts -> Style R2+shaftSty opts = opts^.shaftStyle++-- Set the default head style. See `shaftSty`.+headSty :: ArrowOpts -> Style R2+headSty opts = fc black (opts^.headStyle)++-- Set the default tail style. See `shaftSty`.+tailSty :: ArrowOpts -> Style R2+tailSty opts = fc black (opts^.tailStyle)++-- | Calculate the length of the portion of the horizontal line that passes+-- through the origin and is inside of p.+xWidth :: (Traced t, V t ~ R2) => t -> Double+xWidth p = a + b+ where+ a = fromMaybe 0 (magnitude <$> traceV origin unitX p)+ b = fromMaybe 0 (magnitude <$> traceV origin unit_X p)++-- | Get the line color from the shaft to use as the fill color for the joint.+colorJoint :: Style v -> Style v+colorJoint sStyle =+ let c = fmap getLineColor . getAttr $ sStyle in+ case c of+ Nothing -> fillColor (black :: Colour Double) -- default color for joints+ $ mempty+ Just c' -> fillColor c' $ mempty++-- | Get line width from a style.+widthOfJoint :: Style v -> Double+widthOfJoint sStyle =+ let w = fmap getLineWidth . getAttr $ sStyle in+ case w of+ Nothing -> 0.01 -- this case should never happen.+ Just w' -> w'++-- | Combine the head and its joint into a single scale invariant diagram+-- and move the origin to the attachment point. Return the diagram+-- and its width.+mkHead :: Renderable (Path R2) b => ArrowOpts -> (Diagram b R2, Double)+mkHead opts = ( (j <> h) # moveOriginBy (jWidth *^ unit_X) # lw 0+ , hWidth + jWidth)+ where+ (h', j') = (opts^.arrowHead) (opts^.headSize) (widthOfJoint $ shaftSty opts)+ hWidth = xWidth h'+ jWidth = xWidth j'+ h = scaleInvPrim h' unitX # applyStyle (headSty opts)+ j = scaleInvPrim j' unitX # applyStyle (colorJoint (opts^.shaftStyle))++-- | Just like mkHead only the attachment point is on the right.+mkTail :: Renderable (Path R2) b => ArrowOpts -> (Diagram b R2, Double)+mkTail opts = ( (t <> j) # moveOriginBy (jWidth *^ unitX) # lw 0+ , tWidth + jWidth)+ where+ (t', j') = (opts^.arrowTail) (opts^.tailSize) (widthOfJoint $ shaftSty opts)+ tWidth = xWidth t'+ jWidth = xWidth j'+ t = scaleInvPrim t' unitX # applyStyle (tailSty opts)+ j = scaleInvPrim j' unitX # applyStyle (colorJoint (opts^.shaftStyle))++-- | Make a trail with the same angles and offset as an arrow with tail width+-- tw, head width hw and shaft of tr, such that the magnituted of the shaft+-- offset is size. Used for calculating the offset of an arrow.+spine :: Trail R2 -> Double -> Double -> Double -> Trail R2+spine tr tw hw size = tS <> tr # scale size <> hS+ where+ tSpine = trailFromOffsets [(normalized . tangentAtStart) $ tr] # scale tw+ hSpine = trailFromOffsets [(normalized . tangentAtEnd) $ tr] # scale hw+ hS = if hw > 0 then hSpine else mempty+ tS = if tw > 0 then tSpine else mempty++-- | Calculate the amount required to scale a shaft trail so that an arrow with+-- head width hw and tail width tw has offset t.+scaleFactor :: Trail R2 -> Double -> Double -> Double -> Double+scaleFactor tr tw hw t++ -- Let tv be a vector representing the tail width, i.e. a vector+ -- of length tw tangent to the trail's start; similarly for hv.+ -- Let v be the vector offset of the trail.+ --+ -- Then we want to find k such that+ --+ -- || tv + k*v + hv || = t.+ --+ -- We can solve by squaring both sides and expanding the LHS as a+ -- dot product, resulting in a quadratic in k.++ = case quadForm+ (magnitudeSq v)+ (2* (v <.> (tv ^+^ hv)))+ (magnitudeSq (tv ^+^ hv) - t*t)+ of+ [] -> 1 -- no scale works, just return 1+ [s] -> s -- single solution+ ss -> maximum ss+ -- we will usually get both a positive and a negative solution;+ -- return the maximum (i.e. positive) solution+ where+ tv = tw *^ (tangentAtStart tr # normalized)+ hv = hw *^ (tangentAtEnd tr # normalized)+ v = trailOffset tr++-- | @arrow len@ creates an arrow of length @len@ with default+-- parameters, starting at the origin and ending at the point+-- @(len,0)@.+arrow :: Renderable (Path R2) b => Double -> Diagram b R2+arrow len = arrow' def len++-- | @arrow' opts len@ creates an arrow of length @len@ using the+-- given options, starting at the origin and ending at the point+-- @(len,0)@. In particular, it scales the given 'arrowShaft' so+-- that the entire arrow has length @len@.+arrow' :: Renderable (Path R2) b => ArrowOpts -> Double -> Diagram b R2+arrow' opts len = mkQD' (DelayedLeaf delayedArrow)++ -- We must approximate the envelope and trace by just drawing the+ -- arrow from the origin to (len,0) and using its envelope and+ -- trace. That may not end up being exactly right (if the arrow+ -- gets scaled, the shaft may get a bit longer or shorter, and so+ -- on) but it's close enough.+ (getEnvelope approx) (getTrace approx) mempty mempty+ where++ -- Once we learn the global transformation context this arrow is+ -- drawn in, we can apply it to the origin and (len,0) to find out+ -- the actual final points between which this arrow should be+ -- drawn. We need to know this to draw it correctly, since the+ -- head and tail are scale invariant, and hence the precise points+ -- between which we need to draw the shaft do not transform+ -- uniformly as the transformation applied to the entire arrow.+ -- See https://github.com/diagrams/diagrams-lib/issues/112.+ delayedArrow da =++ -- Note we only take the *unfrozen* transformation. The frozen+ -- transformation *do* affect scale-invariant objects like+ -- arrowheads, and will still be higher up in the tree (so we+ -- don't need to apply it here).+ let (unfrozenTr, globalSty) = option mempty (first unsplitR . untangle) . fst $ da+ in dArrow globalSty unfrozenTr len++ unsplitR (M m) = m+ unsplitR (_ :| m) = m++ approx = dArrow mempty mempty len++ -- Build an arrow and set its endpoints to the image under tr of origin and (len,0).+ dArrow sty tr ln = (h' <> t' <> shaft)+ # moveOriginBy (tWidth *^ (unit_X # rotateBy tAngle))+ # rotateBy (direction (q .-. p) - dir)+ # moveTo p+ where++ p = origin # transform tr+ q = origin # translateX ln # transform tr++ -- Use the existing line color for head, tail, and shaft by+ -- default (can be overridden by explicitly setting headStyle,+ -- tailStyle, or shaftStyle).+ globalLC = getLineColor <$> getAttr sty+ opts' = opts+ & headStyle %~ maybe id fillColor globalLC+ & tailStyle %~ maybe id fillColor globalLC+ & shaftStyle %~ maybe id lineColor globalLC++ -- Make the head and tail and save their widths.+ (h, hWidth') = mkHead opts'+ (t, tWidth') = mkTail opts'++ rawShaftTrail = opts^.arrowShaft+ shaftTrail+ = rawShaftTrail+ -- rotate it so it is pointing in the positive X direction+ # rotateBy (- direction (trailOffset rawShaftTrail))+ -- apply the context transformation -- in case it includes+ -- things like flips and shears (the possibility of shears+ -- is why we must rotate it to a neutral position first)+ # transform tr++ -- Adjust the head width and tail width to take gaps into account+ tWidth = tWidth' + opts^.tailGap+ hWidth = hWidth' + opts^.headGap++ -- Calculate the angles that the head and tail should point.+ tAngle = direction . tangentAtStart $ shaftTrail :: Turn+ hAngle = direction . tangentAtEnd $ shaftTrail :: Turn++ -- Calculte the scaling factor to apply to the shaft shaftTrail so that the entire+ -- arrow will be of length len. Then apply it to the shaft and make the+ -- shaft into a Diagram with using its style.+ sf = scaleFactor shaftTrail tWidth hWidth (magnitude (q .-. p))+ shaftTrail' = shaftTrail # scale sf+ shaft = strokeT shaftTrail' # applyStyle (shaftSty opts)++ -- Adjust the head and tail to point in the directions of the shaft ends.+ h' = h # rotateBy hAngle+ # moveTo (origin .+^ shaftTrail' `atParam` domainUpper shaftTrail')+ t' = t # rotateBy tAngle++ -- Find out what direction the arrow is pointing so we can set it back+ -- to point in the direction unitX when we are done.+ dir = direction (trailOffset $ spine shaftTrail tWidth hWidth sf)++-- | @arrowBetween s e@ creates an arrow pointing from @s@ to @e@+-- with default parameters.+arrowBetween :: Renderable (Path R2) b => P2 -> P2 -> Diagram b R2+arrowBetween = arrowBetween' def++-- | @arrowBetween' opts s e@ creates an arrow pointing from @s@ to+-- @e@ using the given options. In particular, it scales and+-- rotates @arrowShaft@ to go between @s@ and @e@, taking head,+-- tail, and gaps into account.+arrowBetween'+ :: Renderable (Path R2) b =>+ ArrowOpts -> P2 -> P2 -> Diagram b R2+arrowBetween' opts s e = arrowAt' opts s (e .-. s)++-- | Create an arrow starting at s with length and direction determined by+-- the vectore v.+arrowAt :: Renderable (Path R2) b => P2 -> R2 -> Diagram b R2+arrowAt s v = arrowAt' def s v++arrowAt'+ :: Renderable (Path R2) b =>+ ArrowOpts -> P2 -> R2 -> Diagram b R2+arrowAt' opts s v = arrow' opts len # rotateBy dir # moveTo s+ where+ len = magnitude v+ dir = direction v++-- | Connect two diagrams with a straight arrow.+connect+ :: (Renderable (Path R2) b, IsName n1, IsName n2)+ => n1 -> n2 -> (Diagram b R2 -> Diagram b R2)+connect = connect' def++-- | Connect two diagrams with an arbitrary arrow.+connect'+ :: (Renderable (Path R2) b, IsName n1, IsName n2)+ => ArrowOpts -> n1 -> n2 -> (Diagram b R2 -> Diagram b R2)+connect' opts n1 n2 =+ withName n1 $ \sub1 ->+ withName n2 $ \sub2 ->+ let [s,e] = map location [sub1, sub2]+ in atop (arrowBetween' opts s e)++-- | Connect two diagrams at point on the perimeter of the diagrams, choosen+-- by angle.+connectPerim+ :: (Renderable (Path R2) b, IsName n1, IsName n2, Angle a)+ => n1 -> n2 -> a -> a+ -> (Diagram b R2 -> Diagram b R2)+connectPerim = connectPerim' def++connectPerim'+ :: (Renderable (Path R2) b, IsName n1, IsName n2, Angle a)+ => ArrowOpts -> n1 -> n2 -> a -> a+ -> (Diagram b R2 -> Diagram b R2)+connectPerim' opts n1 n2 a1 a2 =+ withName n1 $ \sub1 ->+ withName n2 $ \sub2 ->+ let [os, oe] = map location [sub1, sub2]+ s = fromMaybe os (maxTraceP os (unitX # rotate a1) sub1)+ e = fromMaybe oe (maxTraceP oe (unitX # rotate a2) sub2)+ in atop (arrowBetween' opts s e)++-- | Draw an arrow from diagram named "n1" to diagram named "n2". The+-- arrow lies on the line between the centres of the diagrams, but is+-- drawn so that it stops at the boundaries of the diagrams, using traces+-- to find the intersection points.+connectOutside+ :: (Renderable (Path R2) b, IsName n1, IsName n2)+ => n1 -> n2 -> (Diagram b R2 -> Diagram b R2)+connectOutside = connectOutside' def++connectOutside'+ :: (Renderable (Path R2) b, IsName n1, IsName n2)+ => ArrowOpts -> n1 -> n2 -> (Diagram b R2 -> Diagram b R2)+connectOutside' opts n1 n2 =+ withName n1 $ \b1 ->+ withName n2 $ \b2 ->+ let v = location b2 .-. location b1+ midpoint = location b1 .+^ (v/2)+ s = fromJust $ traceP midpoint (-v) b1+ e = fromJust $ traceP midpoint v b2+ in atop (arrowBetween' opts s e)
+ src/Diagrams/TwoD/Arrowheads.hs view
@@ -0,0 +1,338 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.TwoD.Arrowheads+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Standard arrowheads and tails. Each arrowhead or tail is designed+-- to be drawn filled, with a line width of 0, and is normalized to+-- fit inside a circle of diameter 1.+--+-----------------------------------------------------------------------------++module Diagrams.TwoD.Arrowheads+ (+ -- * Arrowheads+ -- ** Standard arrowheads+ tri+ , dart+ , spike+ , thorn+ , missile+ , noHead++ -- ** Configurable arrowheads+ -- | Creates arrowheads of the same shape as the standard heads but+ -- where the angle parameter is used to specify the angle to the top+ -- left point of the arrowhead.+ , arrowheadTriangle+ , arrowheadDart+ , arrowheadSpike+ , arrowheadThorn+ , arrowheadMissile++ -- * Arrow tails+ -- ** Standard arrow tails+ , tri'+ , dart'+ , spike'+ , thorn'+ , missile'+ , noTail+ , quill+ , block++ -- ** Configurable arrow tails++ , arrowtailQuill+ , arrowtailBlock++ -- * Internals+ , ArrowHT+ ) where++import Control.Lens ((&), (.~))+import Data.Default.Class+import Data.AffineSpace+import Data.Functor ((<$>))+import Data.Maybe (fromMaybe)+import Data.Monoid (mempty, (<>))+import Data.VectorSpace++import Diagrams.Core+import Diagrams.CubicSpline (cubicSpline)+import Diagrams.Path+import Diagrams.Segment+import Diagrams.Trail+import Diagrams.TwoD.Align+import Diagrams.TwoD.Arc (arc')+import Diagrams.TwoD.Path ()+import Diagrams.TwoD.Polygons+import Diagrams.TwoD.Shapes+import Diagrams.TwoD.Transform+import Diagrams.TwoD.Types+import Diagrams.TwoD.Vector (e, unitX, unit_X)+import Diagrams.Util (( # ))++-----------------------------------------------------------------------------++type ArrowHT = Double -> Double -> (Path R2, Path R2)++htRadius :: Double+htRadius = 0.5++scaleR :: (Transformable t, Scalar (V t) ~ Double) => t -> t+scaleR = scale htRadius++unit_X2 :: R2+unit_X2 = scaleR unit_X++closedPath :: (Floating (Scalar v), Ord (Scalar v), InnerSpace v) => Trail v -> Path v+closedPath = pathFromTrail . closeTrail++-- Heads ------------------------------------------------------------------+-- > drawHead h = arrowAt' (with & arrowHead .~ h & shaftStyle %~ lw 0)+-- > origin (r2 (0.001, 0))+-- > <> square 0.5 # alignL # lw 0++-- | Isoceles triangle style. The above example specifies an angle of `2/5 Turn`.++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_tri25Ex.svg#diagram=tri25Ex&width=120>>++-- > tri25Ex = arrowAt' (with & arrowHead .~ arrowheadTriangle (2/5 :: Turn) & shaftStyle %~ lw 0)+-- > origin (r2 (0.001, 0))+-- > <> square 0.6 # alignL # lw 0+arrowheadTriangle :: Angle a => a -> ArrowHT+arrowheadTriangle theta = aHead+ where+ aHead size _ = (p, mempty)+ where+ p = polygon (def & polyType .~ PolyPolar [theta, (-2 * theta)]+ (repeat (htRadius * size)) & polyOrient .~ NoOrient) # alignL++-- | Isoceles triangle with linear concave base. Inkscape type 1 - dart like.+arrowheadDart :: Angle a => a -> ArrowHT+arrowheadDart theta = aHead+ where+ aHead size shaftWidth = (dartP # moveOriginTo (dartVertices !! 2), joint)+ where+ a = toTurn theta+ r = htRadius * size+ dartP = polygon (def & polyType .~ PolyPolar [a, 1/2 - a, 1/2 - a]+ [r, r, 0.1 * size, r] & polyOrient .~ NoOrient)+ dartVertices = (concat . pathVertices) $ dartP+ m = magnitude (dartVertices !! 1 .-. dartVertices !! 3)+ s = 1 - shaftWidth / m+ v1 = (dartVertices !! 1 .-. dartVertices !! 2) # scale s+ v2 = (dartVertices !! 3 .-. dartVertices !! 2) # scale s+ joint = (closedPath $ trailFromVertices [ dartVertices !! 2+ , dartVertices !! 1 .-^ v1+ , dartVertices !! 3 .-^ v2+ , dartVertices !! 2 ]) # alignR++-- | Isoceles triangle with curved concave base. Inkscape type 2.+arrowheadSpike :: Angle a => a -> ArrowHT+arrowheadSpike theta = aHead+ where+ aHead size shaftWidth = (barb # moveOriginBy (m *^ unit_X) , joint)+ where+ a = e theta # scaleR+ a' = reflectY a+ l1 = trailFromSegments [straight (unit_X2 ^+^ a)]+ l2 = trailFromSegments [reverseSegment . straight $ (unit_X2 ^+^ a')]+ c = reflectX $ arc' htRadius theta (-theta)+ barb = (closedPath $ (l1 <> c <> l2)) # scale size+ m = xWidth barb --c `atParam` 0.5+ b = Rad $ asin ((shaftWidth / 2) / (htRadius * size))+ c' = arc' htRadius (-b ) b # scale size+ joint = (closedPath $ (c')) # centerY # alignR+ xWidth p = pa + pb+ where+ pa = fromMaybe 0 (magnitude <$> traceV origin unitX p)+ pb = fromMaybe 0 (magnitude <$> traceV origin unit_X p)++-- | Curved sides, linear concave base. Illustrator CS5 #3+arrowheadThorn :: Angle a => a -> Double -> ArrowHT+arrowheadThorn theta r = aHead+ where+ aHead size shaftWidth = (thornP # moveOriginTo (thornVertices !! 2), joint)+ where+ a = e theta # scaleR+ c1 = curvedSide theta+ l1 = straight $ (reflectY a) ^-^ (unit_X2 # scale r)+ l2 = straight $ unit_X2 # scale r ^-^ a+ c2 = c1 # rotate (-theta)+ thornP = (closedPath $ trailFromSegments [c1, l1, l2, c2]) # scale size+ thornVertices = (concat . pathVertices) $ thornP+ m = magnitude (thornVertices !! 1 .-. thornVertices !! 3)+ s = 1 - shaftWidth / m+ v1 = (thornVertices !! 1 .-. thornVertices !! 2) # scale s+ v2 = (thornVertices !! 3 .-. thornVertices !! 2) # scale s+ joint = (closedPath $ trailFromVertices [ thornVertices !! 2+ , thornVertices !! 1 .-^ v1+ , thornVertices !! 3 .-^ v2+ , thornVertices !! 2 ]) # alignR++-- | Make a side for the thorn head.+curvedSide :: Angle a => a -> Segment Closed R2+curvedSide theta = bezier3 ctrl1 ctrl2 end+ where+ v0 = scaleR unit_X+ v1 = e theta # scaleR+ ctrl1 = v0 # scaleR+ ctrl2 = v0 ^+^ (v1 # scaleR)+ end = v0 ^+^ v1++-- | Transform an arrowhead/tail by fitting a cubic spline to it's vertices.+-- XXX Rear vertices of the arrowhead will extend outside of the unit circle.+-- XXX and the joint is a rectancgle as opposed to the correct shape.+smoothArrowhead :: ArrowHT -> ArrowHT+smoothArrowhead f = aHead+ where+ aHead size shaftWidth = (h, j)+ where+ (h', _) = f size shaftWidth+ h = smooth $ pathVertices h'+ -- XXX replace square joint with actual shape+ j = square shaftWidth # scaleX 0.25 alignR+ smooth [] = mempty+ smooth (x:xs) = cubicSpline True x <> smooth xs++arrowheadMissile :: Angle a => a -> ArrowHT+arrowheadMissile theta = smoothArrowhead $ arrowheadDart theta++-- Standard heads ---------------------------------------------------------+noHead :: ArrowHT+noHead _ _ = (mempty, mempty)++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_triEx.svg#diagram=triEx&width=100>>++-- > triEx = drawHead tri+tri :: ArrowHT+tri = arrowheadTriangle (1/3 :: Turn)++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_spikeEx.svg#diagram=spikeEx&width=100>>++-- > spikeEx = drawHead spike+spike :: ArrowHT+spike = arrowheadSpike (3/8 :: Turn)++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_thornEx.svg#diagram=thornEx&width=100>>++-- > thornEx = drawHead thorn+thorn :: ArrowHT+thorn = arrowheadThorn (3/8 :: Turn) 1++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_dartEx.svg#diagram=dartEx&width=100>>++-- > dartEx = drawHead dart+dart :: ArrowHT+dart = arrowheadDart (2/5 :: Turn)++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_missileEx.svg#diagram=missileEx&width=100>>++-- > missileEx = drawHead missile+missile :: ArrowHT+missile = arrowheadMissile (2/5 :: Turn)++-- Tails ------------------------------------------------------------------+-- > drawTail t = arrowAt' (with & arrowTail .~ t & shaftStyle %~ lw 0 & arrowHead .~ noHead)+-- > origin (r2 (0.001, 0))+-- > <> square 0.5 # alignL # lw 0++-- | Utility function to convert any arrowhead to an arrowtail, i.e.+-- attached at the start of the trail.+headToTail :: ArrowHT -> ArrowHT+headToTail hd = tl+ where+ tl size shaftWidth = (t, j)+ where+ (t', j') = hd size shaftWidth+ t = reflectX t'+ j = reflectX j'++arrowtailBlock :: Angle a => a -> ArrowHT+arrowtailBlock theta = aTail+ where+ aTail size _ = (t, mempty)+ where+ t = square 1 # scaleX x # scaleY y # scale size # alignR+ a' = e theta # scaleR+ a = a' ^-^ (reflectY a')+ y = magnitude a+ b = a' ^-^ (reflectX a')+ x = magnitude b++-- | The angle is where the top left corner intersects the circle.+arrowtailQuill :: Angle a => a -> ArrowHT+arrowtailQuill theta =aTail+ where+ aTail size shaftWidth = (t, j)+ where+ t = ( closedPath $ trailFromVertices [v0, v1, v2, v3, v4, v5, v0] )+ # scale size # alignR+ theta' = toTurn theta+ v0 = p2 (0.5, 0)+ v2 = p2 (unr2 $ e theta' # scaleR)+ v1 = v2 # translateX (5/4 * htRadius)+ v3 = p2 (-0.1, 0)+ v4 = v2 # reflectY+ v5 = v4 # translateX (5/4 * htRadius)+ s = 1 - shaftWidth / magnitude (v1 .-. v5)+ n1 = v0 # translateY (0.5 * shaftWidth)+ n2 = v1 .-^ ((v1 .-. v0) # scale s)+ n3 = v5 .-^ ((v5 .-. v0) # scale s)+ n4 = n1 # reflectY+ j = ( closedPath $ trailFromVertices+ [ v0, n1, n2, v0, n3, n4, v0 ])++-- Standard tails ---------------------------------------------------------++noTail :: ArrowHT+noTail _ _ = (mempty, mempty)++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_tri'Ex.svg#diagram=tri'Ex&width=100>>++-- > tri'Ex = drawTail tri'+tri' :: ArrowHT+tri' = headToTail tri++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_spike'Ex.svg#diagram=spike'Ex&width=100>>++-- > spike'Ex = drawTail spike'+spike' :: ArrowHT+spike' = headToTail spike++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_thorn'Ex.svg#diagram=thorn'Ex&width=100>>++-- > thorn'Ex = drawTail thorn'+thorn' :: ArrowHT+thorn' = headToTail thorn++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_dart'Ex.svg#diagram=dart'Ex&width=100>>++-- > dart'Ex = drawTail dart'+dart' :: ArrowHT+dart' = headToTail dart++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_missile'Ex.svg#diagram=missile'Ex&width=100>>++-- > missile'Ex = drawTail missile'+missile' :: ArrowHT+missile' = headToTail missile++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_quillEx.svg#diagram=quillEx&width=100>>++-- > quillEx = drawTail quill+quill :: ArrowHT+quill = arrowtailQuill (2/5 :: Turn)++-- | <<diagrams/src_Diagrams_TwoD_Arrowheads_blockEx.svg#diagram=blockEx&width=100>>++-- > blockEx = drawTail block+block :: ArrowHT+block = arrowtailBlock (2/5 :: Turn)
src/Diagrams/TwoD/Combinators.hs view
@@ -54,7 +54,6 @@ import Diagrams.TrailLike import Diagrams.TwoD.Align import Diagrams.TwoD.Path ()-import Diagrams.TwoD.Segment import Diagrams.TwoD.Shapes import Diagrams.TwoD.Transform (scaleX, scaleY) import Diagrams.TwoD.Types@@ -77,7 +76,7 @@ -- -- to place @c@ above @d@. The local origin of the resulting -- combined diagram is the same as the local origin of the first.--- @(===)@ is associative and has 'mempty' as an identity. See the+-- @(|||)@ is associative and has 'mempty' as an identity. See the -- documentation of 'beside' for more information. (===) :: (Juxtaposable a, V a ~ R2, Semigroup a) => a -> a -> a (===) = beside (negateV unitY)@@ -158,13 +157,13 @@ -- centered local origin. Note that @strutX (-w)@ behaves the same as -- @strutX w@. strutX :: (Backend b R2, Monoid' m) => Double -> QDiagram b R2 m-strutX d = strut (d & 0)+strutX d = strut (d ^& 0) -- | @strutY h@ is an empty diagram with height @h@, width 0, and a -- centered local origin. Note that @strutY (-h)@ behaves the same as -- @strutY h@. strutY :: (Backend b R2, Monoid' m) => Double -> QDiagram b R2 m-strutY d = strut (0 & d)+strutY d = strut (0 ^& d) -- | @padX s@ \"pads\" a diagram in the x-direction, expanding its -- envelope horizontally by a factor of @s@ (factors between 0 and 1@@ -193,6 +192,7 @@ -- the envelope is inset instead. -- -- See the documentation for 'extrudeEnvelope' for more information.+extrudeLeft :: Monoid' m => Double -> QDiagram b R2 m -> QDiagram b R2 m extrudeLeft s | s >= 0 = extrudeEnvelope $ unitX ^* negate s | otherwise = intrudeEnvelope $ unitX ^* negate s@@ -202,6 +202,7 @@ -- the envelope is inset instead. -- -- See the documentation for 'extrudeEnvelope' for more information.+extrudeRight :: Monoid' m => Double -> QDiagram b R2 m -> QDiagram b R2 m extrudeRight s | s >= 0 = extrudeEnvelope $ unitX ^* s | otherwise = intrudeEnvelope $ unitX ^* s@@ -211,6 +212,7 @@ -- the envelope is inset instead. -- -- See the documentation for 'extrudeEnvelope' for more information.+extrudeBottom :: Monoid' m => Double -> QDiagram b R2 m -> QDiagram b R2 m extrudeBottom s | s >= 0 = extrudeEnvelope $ unitY ^* negate s | otherwise = intrudeEnvelope $ unitY ^* negate s@@ -220,6 +222,7 @@ -- the envelope is inset instead. -- -- See the documentation for 'extrudeEnvelope' for more information.+extrudeTop :: Monoid' m => Double -> QDiagram b R2 m -> QDiagram b R2 m extrudeTop s | s >= 0 = extrudeEnvelope $ unitY ^* s | otherwise = intrudeEnvelope $ unitY ^* s
src/Diagrams/TwoD/Curvature.hs view
@@ -19,18 +19,16 @@ , squaredRadiusOfCurvature ) where -import Data.AffineSpace import Data.Monoid.Inf+import Data.NumInstances.Tuple () import Data.VectorSpace import Control.Arrow (first, second) import Control.Monad (join) -import Diagrams.Core- import Diagrams.Segment+import Diagrams.Tangent import Diagrams.TwoD.Types-import Diagrams.TwoD.Vector -- | Curvature measures how curved the segment is at a point. One intuition -- for the concept is how much you would turn the wheel when driving a car@@ -51,19 +49,19 @@ -- -- Lets consider the following curve: ----- <<diagrams/diagramA.svg#diagram=diagramA&height=200&width=400>>+-- <<diagrams/src_Diagrams_TwoD_Curvature_diagramA.svg#diagram=diagramA&height=200&width=400>> -- -- The curve starts with positive curvature, ----- <<diagrams/diagramPos.svg#diagram=diagramPos&height=200&width=400>>+-- <<diagrams/src_Diagrams_TwoD_Curvature_diagramPos.svg#diagram=diagramPos&height=200&width=400>> -- -- approaches zero curvature ----- <<diagrams/diagramZero.svg#diagram=diagramZero&height=200&width=400>>+-- <<diagrams/src_Diagrams_TwoD_Curvature_diagramZero.svg#diagram=diagramZero&height=200&width=400>> -- -- then has negative curvature ----- <<diagrams/diagramNeg.svg#diagram=diagramNeg&height=200&width=400>>+-- <<diagrams/src_Diagrams_TwoD_Curvature_diagramNeg.svg#diagram=diagramNeg&height=200&width=400>> -- -- > {-# LANGUAGE GADTs #-} -- >@@ -71,7 +69,7 @@ -- > import Data.Monoid.Inf -- > import Diagrams.Coordinates -- >--- > segmentA = Cubic (12 & 0) (8 & 10) (OffsetClosed (20 & 8))+-- > segmentA = Cubic (12 ^& 0) (8 ^& 10) (OffsetClosed (20 ^& 8)) -- > -- > curveA = lw 0.1 . stroke . fromSegments $ [segmentA] -- >@@ -79,7 +77,7 @@ -- > -- > diagramPos = diagramWithRadius 0.2 -- >--- > diagramZero = diagramWithRadius 0.5+-- > diagramZero = diagramWithRadius 0.45 -- > -- > diagramNeg = diagramWithRadius 0.8 -- >@@ -94,7 +92,7 @@ -- > | otherwise = go (radiusOfCurvature bez t) -- > where -- > v@(x,y) = unr2 $ firstDerivative b c d t--- > vp = (-y) & x+-- > vp = (-y) ^& x -- > -- > firstDerivative b c d t = let tt = t*t in (3*(3*tt-4*t+1))*^b + (3*(2-3*t)*t)*^c + (3*tt)*^d -- >@@ -144,17 +142,12 @@ -- the denominator respectively. curvaturePair :: (Num t, Num (Scalar t), VectorSpace t) => Segment Closed (t, t) -> Scalar t -> (t, t)-curvaturePair (Linear _) t = (0,1) -- Linear segments always have zero curvature (infinite radius).-curvaturePair (Cubic b c (OffsetClosed d)) t = ((x'*y'' - y'*x''), (x'*x' + y'*y')^(3 :: Integer))+curvaturePair (Linear _) _ = (0,1) -- Linear segments always have zero curvature (infinite radius).+curvaturePair seg@(Cubic b c (OffsetClosed d)) t = ((x'*y'' - y'*x''), (x'*x' + y'*y')^(3 :: Integer)) where- (x' ,y' ) = firstDerivative b c d t -- TODO: Use the generalized unr2- (x'',y'') = secondDerivative b c d t-- firstDerivative b c d t = (3*(3*tt-4*t+1))*^b + (3*(2-3*t)*t)*^c + (3*tt)*^d- where- tt = t * t-- secondDerivative b c d t = (6*(3*t-2))*^b + (6-18*t)*^c + (6*t)*^d+ (x' ,y' ) = seg `tangentAtParam` t+ (x'',y'') = secondDerivative+ secondDerivative = (6*(3*t-2))*^b + (6-18*t)*^c + (6*t)*^d -- TODO: We should be able to generalize this to higher dimensions. See -- <http://en.wikipedia.org/wiki/Curvature>
src/Diagrams/TwoD/Ellipse.hs view
@@ -25,7 +25,6 @@ import Diagrams.Core import Diagrams.Located (at)-import Diagrams.Path import Diagrams.TrailLike import Diagrams.TwoD.Arc import Diagrams.TwoD.Transform
src/Diagrams/TwoD/Image.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE TypeFamilies- , FlexibleContexts- , MultiParamTypeClasses- #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Image@@ -15,10 +15,12 @@ module Diagrams.TwoD.Image (- Image(..)+ Image(..), imgFile, imgSize, imgTransf , image ) where +import Control.Lens (makeLenses)+ import Diagrams.Core import Diagrams.Path@@ -33,10 +35,12 @@ -- | An external image primitive, representing an image the backend -- should import from another file when rendering.-data Image = Image { imgFile :: FilePath- , imgSize :: SizeSpec2D- , imgTransf :: T2+data Image = Image { _imgFile :: FilePath+ , _imgSize :: SizeSpec2D+ , _imgTransf :: T2 }++makeLenses ''Image type instance V Image = R2
src/Diagrams/TwoD/Model.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Model@@ -15,16 +16,15 @@ ( -- * Showing the local origin showOrigin , showOrigin'- , OriginOpts(..)+ , OriginOpts(..), oColor, oScale, oMinSize , showLabels ) where -import Diagrams.Core-import Diagrams.Core.Names--import Diagrams.Path+import Control.Lens (makeLenses, (^.)) +import Diagrams.Core import Diagrams.Attributes+import Diagrams.Path import Diagrams.TwoD.Ellipse import Diagrams.TwoD.Path import Diagrams.TwoD.Size (size2D)@@ -47,6 +47,16 @@ -- Marking the origin ------------------------------------------------------------ +data OriginOpts = OriginOpts { _oColor :: Colour Double+ , _oScale :: Double+ , _oMinSize :: Double+ }++makeLenses ''OriginOpts++instance Default OriginOpts where+ def = OriginOpts red (1/50) 0.001+ -- | Mark the origin of a diagram by placing a red dot 1/50th its size. showOrigin :: (Renderable (Path R2) b, Backend b R2, Monoid' m) => QDiagram b R2 m -> QDiagram b R2 m@@ -58,26 +68,17 @@ => OriginOpts -> QDiagram b R2 m -> QDiagram b R2 m showOrigin' oo d = o <> d where o = stroke (circle sz)- # fc (oColor oo)+ # fc (oo^.oColor) # lw 0 # fmap (const mempty)- (w,h) = size2D d ^* oScale oo- sz = maximum [w, h, oMinSize oo]--data OriginOpts = OriginOpts { oColor :: Colour Double- , oScale :: Double- , oMinSize :: Double- }--instance Default OriginOpts where- def = OriginOpts red (1/50) 0.001-+ (w,h) = size2D d ^* oo^.oScale+ sz = maximum [w, h, oo^.oMinSize] ------------------------------------------------------------ -- Labeling named points ------------------------------------------------------------ -showLabels :: (Renderable Text b, Backend b R2)+showLabels :: (Renderable Text b, Backend b R2, Semigroup m) => QDiagram b R2 m -> QDiagram b R2 Any showLabels d = ( mconcat@@ -89,4 +90,4 @@ ) <> fmap (const (Any False)) d where- SubMap m = subMap d+ SubMap m = d^.subMap
src/Diagrams/TwoD/Offset.hs view
@@ -1,41 +1,73 @@-{-# LANGUAGE GADTs #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Offset--- Copyright : (c) 2012 diagrams-lib team (see LICENSE)+-- Copyright : (c) 2013 diagrams-lib team (see LICENSE) -- License : BSD-style (see LICENSE) -- Maintainer : diagrams-discuss@googlegroups.com ----- Compute offsets to segments in two dimensions.--- +-- Compute offsets to segments in two dimensions. More details can be +-- found in the manual at +-- <http://projects.haskell.org/diagrams/doc/manual.html#offsets-of-segments-trails-and-paths>.+-- ------------------------------------------------------------------------------module Diagrams.TwoD.Offset - ( offsetSegment+module Diagrams.TwoD.Offset+ ( + -- * Offsets+ + offsetSegment++ , OffsetOpts(..), offsetJoin, offsetMiterLimit, offsetEpsilon+ , offsetTrail+ , offsetTrail'+ , offsetPath+ , offsetPath'++ -- * Expansions++ , ExpandOpts(..), expandJoin, expandMiterLimit, expandCap, expandEpsilon+ , expandTrail+ , expandTrail'+ , expandPath+ , expandPath'+ ) where +import Control.Applicative+import Control.Lens hiding (at, moveTo)+ import Data.AffineSpace+import Data.Monoid import Data.Monoid.Inf import Data.VectorSpace +import Data.Default.Class+ import Diagrams.Core +import Diagrams.Attributes+import Diagrams.Located import Diagrams.Parametric import Diagrams.Path import Diagrams.Segment-import Diagrams.Trail+import Diagrams.Trail hiding (offset, isLoop)+import Diagrams.TrailLike+import Diagrams.TwoD.Arc import Diagrams.TwoD.Curvature-import Diagrams.TwoD.Transform+import Diagrams.TwoD.Path () import Diagrams.TwoD.Types--perp :: R2 -> R2-perp v = rotateBy (-1/4) v+import Diagrams.TwoD.Vector (perp, direction) unitPerp :: R2 -> R2 unitPerp = normalized . perp perpAtParam :: Segment Closed R2 -> Double -> R2-perpAtParam (Linear (OffsetClosed a)) t = unitPerp a -perpAtParam s@(Cubic _ _ _) t = unitPerp a+perpAtParam (Linear (OffsetClosed a)) _ = -unitPerp a+perpAtParam s@(Cubic _ _ _) t = -unitPerp a where (Cubic a _ _) = snd $ splitAtParam s t @@ -46,7 +78,9 @@ -- length. -- -- Cubic segments require a search for a subdivision of cubic segments that--- gives an approximation of the offset within the given epsilon tolerance.+-- gives an approximation of the offset within the given epsilon factor+-- (the given epsilon factor is applied to the radius giving a concrete epsilon+-- value). -- We must do this because the offset of a cubic is not a cubic itself (the -- degree of the curve increases). Cubics do, however, approach constant -- curvature as we subdivide. In light of this we scale the handles of@@ -57,39 +91,96 @@ -- In the following example the blue lines are the original segments and -- the alternating green and red lines are the resulting offset trail segments. ----- <<diagrams/cubicOffsetExample.svg#diagram=cubicOffsetExample&width=600>>+-- <<diagrams/src_Diagrams_TwoD_Offset_cubicOffsetExample.svg#diagram=cubicOffsetExample&width=600>> -- -- Note that when the original curve has a cusp, the offset curve forms a -- radius around the cusp, and when there is a loop in the original curve, -- there can be two cusps in the offset curve. ---offsetSegment :: Double -- ^ Epsilon value that represents the maximum ++-- | Options for specifying line join and segment epsilon for an offset+-- involving multiple segments.+data OffsetOpts = OffsetOpts+ { _offsetJoin :: LineJoin+ , _offsetMiterLimit :: Double+ , _offsetEpsilon :: Double+ } deriving (Eq, Show)++makeLensesWith (lensRules & generateSignatures .~ False) ''OffsetOpts++-- | Specifies the style of join for between adjacent offset segments.+offsetJoin :: Lens' OffsetOpts LineJoin++-- | Specifies the miter limit for the join.+offsetMiterLimit :: Lens' OffsetOpts Double++-- | Epsilon perimeter for 'offsetSegment'.+offsetEpsilon :: Lens' OffsetOpts Double++-- | The default offset options use the default 'LineJoin' ('LineJoinMiter'), a+-- miter limit of 10, and epsilon factor of 0.01.+instance Default OffsetOpts where+ def = OffsetOpts def 10 0.01++-- | Options for specifying how a 'Trail' should be expanded.+data ExpandOpts = ExpandOpts+ { _expandJoin :: LineJoin+ , _expandMiterLimit :: Double+ , _expandCap :: LineCap+ , _expandEpsilon :: Double+ } deriving (Eq, Show)++makeLensesWith (lensRules & generateSignatures .~ False) ''ExpandOpts++-- | Specifies the style of join for between adjacent offset segments.+expandJoin :: Lens' ExpandOpts LineJoin++-- | Specifies the miter limit for the join.+expandMiterLimit :: Lens' ExpandOpts Double++-- | Specifies how the ends are handled.+expandCap :: Lens' ExpandOpts LineCap++-- | Epsilon perimeter for 'offsetSegment'.+expandEpsilon :: Lens' ExpandOpts Double++++-- | The default 'ExpandOpts' is the default 'LineJoin' ('LineJoinMiter'),+-- miter limit of 10, default 'LineCap' ('LineCapButt'), and epsilon factor+-- of 0.01.+instance Default ExpandOpts where+ def = ExpandOpts def 10 def 0.01++offsetSegment :: Double -- ^ Epsilon factor that when multiplied to the+ -- absolute value of the radius gives a+ -- value that represents the maximum -- allowed deviation from the true offset. In -- the current implementation each result segment -- should be bounded by arcs that are plus or- -- minus epsilon from the radius of curvature of+ -- minus epsilon factor from the radius of curvature of -- the offset. -> Double -- ^ Offset from the original segment, positive is -- on the right of the curve, negative is on the -- left.- -> Segment Closed R2 -- ^ Original segment- -> (Point R2, Trail R2) -- ^ Resulting offset point and trail.-offsetSegment _ r s@(Linear (OffsetClosed a)) = (origin .+^ va, trailFromSegments [s])- where va = r *^ unitPerp a+ -> Segment Closed R2 -- ^ Original segment+ -> Located (Trail R2) -- ^ Resulting located (at the offset) trail.+offsetSegment _ r s@(Linear (OffsetClosed a)) = trailFromSegments [s] `at` origin .+^ va+ where va = -r *^ unitPerp a -offsetSegment epsilon r s@(Cubic a b (OffsetClosed c)) = (origin .+^ va, t)+offsetSegment epsilon r s@(Cubic a b (OffsetClosed c)) = t `at` origin .+^ va where t = trailFromSegments (go (radiusOfCurvature s 0.5)) -- Perpendiculars to handles.- va = r *^ unitPerp a- vc = r *^ unitPerp (c - b)+ va = -r *^ unitPerp a+ vc = -r *^ unitPerp (c ^-^ b) -- Split segments.- ss = (\(a,b) -> [a,b]) $ splitAtParam s 0.5- subdivided = concatMap (trailSegments . snd . offsetSegment epsilon r) ss+ ss = (\(x,y) -> [x,y]) $ splitAtParam s 0.5+ subdivided = concatMap (trailSegments . unLoc . offsetSegment epsilon r) ss -- Offset with handles scaled based on curvature.- offset factor = bezier3 (a^*factor) ((b - c)^*factor + c + vc - va) (c + vc - va)- + offset factor = bezier3 (a^*factor) ((b ^-^ c)^*factor ^+^ c ^+^ vc ^-^ va) (c ^+^ vc ^-^ va)+ -- We observe a corner. Subdivide right away. go (Finite 0) = subdivided -- We have some curvature@@ -104,30 +195,349 @@ -- o = offset $ case roc of Infinity -> 1 -- Do the right thing.- Finite sr -> 1 + r / sr + Finite sr -> 1 + r / sr - close = and [epsilon > (magnitude (p o + va - p s - pp s))- | t <- [0.25, 0.5, 0.75]- , let p = (`atParam` t)- , let pp = (r *^) . (`perpAtParam` t)+ close = and [epsilon * abs r > (magnitude (p o ^+^ va ^-^ p s ^-^ pp s))+ | t' <- [0.25, 0.5, 0.75]+ , let p = (`atParam` t')+ , let pp = (r *^) . (`perpAtParam` t') ] -- > import Diagrams.TwoD.Offset -- >--- > showExample :: Segment R2 -> Diagram SVG R2+-- > showExample :: Segment Closed R2 -> Diagram SVG R2 -- > showExample s = pad 1.1 . centerXY $ d # lc blue # lw 0.1 <> d' # lw 0.1 -- > where--- > d = stroke $ Path [(origin, Trail [s] False)]--- > d' = mconcat . zipWith lc colors . map stroke . uncurry explodeTrail+-- > d = stroke . fromSegments $ [s]+-- > d' = mconcat . zipWith lc colors . map stroke . explodeTrail -- > $ offsetSegment 0.1 (-1) s--- > +-- > -- > colors = cycle [green, red]--- > +-- > -- > cubicOffsetExample :: Diagram SVG R2 -- > cubicOffsetExample = hcat . map showExample $--- > [ Cubic (10 & 0) ( 5 & 18) (10 & 20)--- > , Cubic ( 0 & 20) ( 10 & 10) ( 5 & 10)--- > , Cubic (10 & 20) ( 0 & 10) (10 & 0)--- > , Cubic (10 & 20) ((-5) & 10) (10 & 0)+-- > [ bezier3 (10 ^& 0) ( 5 ^& 18) (10 ^& 20)+-- > , bezier3 ( 0 ^& 20) ( 10 ^& 10) ( 5 ^& 10)+-- > , bezier3 (10 ^& 20) ( 0 ^& 10) (10 ^& 0)+-- > , bezier3 (10 ^& 20) ((-5) ^& 10) (10 ^& 0) -- > ]++-- Similar to (=<<). This is when we want to map a function across something+-- located, but the result of the mapping will be transformable so we can+-- collapse the Located into the result. This assumes that Located has the+-- meaning of merely taking something that cannot be translated and lifting+-- it into a space with translation.+bindLoc :: (Transformable b, V a ~ V b) => (a -> b) -> Located a -> b+bindLoc f = join' . mapLoc f+ where+ join' (viewLoc -> (p,a)) = translate (p .-. origin) a++-- While we build offsets and expansions we will use the [Located (Segment Closed R2)]+-- and [Located (Trail R2)] intermediate representations.+locatedTrailSegments :: (InnerSpace v, OrderedField (Scalar v))+ => Located (Trail v) -> [Located (Segment Closed v)]+locatedTrailSegments t = zipWith at (trailSegments (unLoc t)) (trailVertices t)++-- | Offset a 'Trail' with options and by a given radius. This generates a new+-- trail that is always radius 'r' away from the given 'Trail' (depending on+-- the line join option) on the right.+--+-- The styles applied to an outside corner can be seen here (with the original+-- trail in blue and the result of 'offsetTrail'' in green):+--+-- <<diagrams/src_Diagrams_TwoD_Offset_offsetTrailExample.svg#diagram=offsetTrailExample&width=600>>+--+-- When a negative radius is given, the offset trail will be on the left:+--+-- <<diagrams/src_Diagrams_TwoD_Offset_offsetTrailLeftExample.svg#diagram=offsetTrailLeftExample&width=200>>+--+-- When offseting a counter-clockwise loop a positive radius gives an outer loop+-- while a negative radius gives an inner loop (both counter-clockwise).+--+-- <<diagrams/src_Diagrams_TwoD_Offset_offsetTrailOuterExample.svg#diagram=offsetTrailOuterExample&width=300>>+--+offsetTrail' :: OffsetOpts+ -> Double -- ^ Radius of offset. A negative value gives an offset on+ -- the left for a line and on the inside for a counter-clockwise+ -- loop.+ -> Located (Trail R2)+ -> Located (Trail R2)+offsetTrail' opts r t = joinSegments j isLoop (opts^.offsetMiterLimit) r ends . offset $ t+ where+ offset = map (bindLoc (offsetSegment (opts^.offsetEpsilon) r)) . locatedTrailSegments+ ends | isLoop = (\(a:as) -> as ++ [a]) . trailVertices $ t+ | otherwise = tail . trailVertices $ t+ j = fromLineJoin (opts^.offsetJoin)++ isLoop = withTrail (const False) (const True) (unLoc t)++-- | Offset a 'Trail' with the default options and a given radius. See 'offsetTrail''.+offsetTrail :: Double -> Located (Trail R2) -> Located (Trail R2)+offsetTrail = offsetTrail' def++-- | Offset a 'Path' by applying 'offsetTrail'' to each trail in the path.+offsetPath' :: OffsetOpts -> Double -> Path R2 -> Path R2+offsetPath' opts r = mconcat+ . map (bindLoc (trailLike . offsetTrail' opts r) . (`at` origin))+ . op Path++-- | Offset a 'Path' with the default options and given radius. See 'offsetPath''.+offsetPath :: Double -> Path R2 -> Path R2+offsetPath = offsetPath' def++-- TODO: Include arrowheads on examples to indicate direction so the "left" and+-- "right" make sense.+--+-- > import Diagrams.TwoD.Offset+-- > import Data.Default.Class+-- >+-- > corner :: Located (Trail R2)+-- > corner = fromVertices (map p2 [(0, 0), (10, 0), (5, 6)]) `at` origin+-- >+-- > offsetTrailExample :: Diagram SVG R2+-- > offsetTrailExample = pad 1.1 . centerXY . lw 0.2 . hcat' (def & sep .~ 1 )+-- > . map (uncurry showStyle)+-- > $ [ (LineJoinMiter, "LineJoinMiter")+-- > , (LineJoinRound, "LineJoinRound")+-- > , (LineJoinBevel, "LineJoinBevel")+-- > ]+-- > where+-- > showStyle j s = centerXY (trailLike corner # lc blue+-- > <> trailLike (offsetTrail' (def & offsetJoin .~ j) 2 corner) # lc green)+-- > === (strutY 3 <> text s # font "Helvetica" # bold)+-- >+-- > offsetTrailLeftExample :: Diagram SVG R2+-- > offsetTrailLeftExample = pad 1.1 . centerXY . lw 0.2+-- > $ (trailLike c # lc blue)+-- > <> (lc green . trailLike+-- > . offsetTrail' (def & offsetJoin .~ LineJoinRound) (-2) $ c)+-- > where+-- > c = reflectY corner+-- >+-- > offsetTrailOuterExample :: Diagram SVG R2+-- > offsetTrailOuterExample = pad 1.1 . centerXY . lw 0.2+-- > $ (trailLike c # lc blue)+-- > <> (lc green . trailLike+-- > . offsetTrail' (def & offsetJoin .~ LineJoinRound) 2 $ c)+-- > where+-- > c = hexagon 5++withTrailL :: (Located (Trail' Line v) -> r) -> (Located (Trail' Loop v) -> r) -> Located (Trail v) -> r+withTrailL f g l = withTrail (f . (`at` p)) (g . (`at` p)) (unLoc l)+ where+ p = loc l++-- | Expand a 'Trail' with the given options and radius 'r' around a given 'Trail'.+-- Expanding can be thought of as generating the loop that, when filled, represents+-- stroking the trail with a radius 'r' brush.+--+-- The cap styles applied to an outside corner can be seen here (with the original+-- trail in white and the result of 'expandTrail'' filled in green):+--+-- <<diagrams/src_Diagrams_TwoD_Offset_expandTrailExample.svg#diagram=expandTrailExample&width=600>>+--+-- Loops result in a path with an inner and outer loop:+--+-- <<diagrams/src_Diagrams_TwoD_Offset_expandLoopExample.svg#diagram=expandLoopExample&width=300>>+--+expandTrail' :: ExpandOpts+ -> Double -- ^ Radius of offset. Only non-negative values allowed.+ -- For a line this gives a loop of the offset. For a+ -- loop this gives two loops, the outer counter-clockwise+ -- and the inner clockwise.+ -> Located (Trail R2)+ -> Path R2+expandTrail' o r t+ | r < 0 = error "expandTrail' with negative radius"+ -- TODO: consider just reversing the path instead of this error.+ | otherwise = withTrailL (pathFromLocTrail . expandLine o r) (expandLoop o r) t++expandLine :: ExpandOpts -> Double -> Located (Trail' Line R2) -> Located (Trail R2)+expandLine opts r (mapLoc wrapLine -> t) = caps cap r s e (f r) (f $ -r)+ where+ offset r' = map (bindLoc (offsetSegment (opts^.expandEpsilon) r')) . locatedTrailSegments+ f r' = joinSegments (fromLineJoin (opts^.expandJoin)) False (opts^.expandMiterLimit) r' ends . offset r' $ t+ ends = tail . trailVertices $ t+ s = atStart t+ e = atEnd t+ cap = fromLineCap (opts^.expandCap)++expandLoop :: ExpandOpts -> Double -> Located (Trail' Loop R2) -> Path R2+expandLoop opts r (mapLoc wrapLoop -> t) = (trailLike $ f r) <> (trailLike . reverseDomain . f $ -r)+ where+ offset r' = map (bindLoc (offsetSegment (opts^.expandEpsilon) r')) . locatedTrailSegments+ f r' = joinSegments (fromLineJoin (opts^.expandJoin)) True (opts^.expandMiterLimit) r' ends . offset r' $ t+ ends = (\(a:as) -> as ++ [a]) . trailVertices $ t++-- | Expand a 'Trail' with the given radius and default options. See 'expandTrail''.+expandTrail :: Double -> Located (Trail R2) -> Path R2+expandTrail = expandTrail' def++-- | Expand a 'Path' using 'expandTrail'' on each trail in the path.+expandPath' :: ExpandOpts -> Double -> Path R2 -> Path R2+expandPath' opts r = mconcat+ . map (bindLoc (expandTrail' opts r) . (`at` origin))+ . op Path++-- | Expand a 'Path' with the given radius and default options. See 'expandPath''.+expandPath :: Double -> Path R2 -> Path R2+expandPath = expandPath' def++-- > import Diagrams.TwoD.Offset+-- > import Data.Default.Class+-- >+-- > expandTrailExample :: Diagram SVG R2+-- > expandTrailExample = pad 1.1 . centerXY . hcat' (def & sep .~ 1)+-- > . map (uncurry showStyle)+-- > $ [ (LineCapButt, "LineCapButt")+-- > , (LineCapRound, "LineCapRound")+-- > , (LineCapSquare, "LineCapSquare")+-- > ]+-- > where+-- > showStyle c s = centerXY (trailLike corner # lc white # lw 0.2+-- > <> stroke (expandTrail'+-- > (def & expandJoin .~ LineJoinRound+-- > & expandCap .~ c+-- > ) 2 corner)+-- > # lw 0 # fc green)+-- > === (strutY 3 <> text s # font "Helvetica" # bold)+-- >+-- > expandLoopExample :: Diagram SVG R2+-- > expandLoopExample = pad 1.1 . centerXY $ ((strokeLocT t # lw 0.2 # lc white)+-- > <> (stroke t' # lw 0 # fc green))+-- > where+-- > t = mapLoc glueTrail $ fromVertices (map p2 [(0, 0), (5, 0), (10, 5), (10, 10), (0, 0)])+-- > t' = expandTrail' (def & expandJoin .~ LineJoinRound) 1 t+++-- | When we expand a line (the original line runs through the center of offset+-- lines at r and -r) there is some choice in what the ends will look like.+-- If we are using a circle brush we should see a half circle at each end.+-- Similar caps could be made for square brushes or simply stopping exactly at+-- the end with a straight line (a perpendicular line brush).+--+-- caps takes the radius and the start and end points of the original line and+-- the offset trails going out and coming back. The result is a new list of+-- trails with the caps included.+caps :: (Double -> P2 -> P2 -> P2 -> Trail R2)+ -> Double -> P2 -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Located (Trail R2)+caps cap r s e fs bs = mapLoc glueTrail $ mconcat+ [ cap r s (atStart bs) (atStart fs)+ , unLoc fs+ , cap r e (atEnd fs) (atEnd bs)+ , reverseDomain (unLoc bs)+ ] `at` atStart bs++-- | Take a LineCap style and give a function for building the cap from+fromLineCap :: LineCap -> Double -> P2 -> P2 -> P2 -> Trail R2+fromLineCap c = case c of+ LineCapButt -> capCut+ LineCapRound -> capArc+ LineCapSquare -> capSquare++-- | Builds a cap that directly connects the ends.+capCut :: Double -> P2 -> P2 -> P2 -> Trail R2+capCut _r _c a b = fromSegments [straight (b .-. a)]++-- | Builds a cap with a square centered on the end.+capSquare :: Double -> P2 -> P2 -> P2 -> Trail R2+capSquare _r c a b = unLoc $ fromVertices [ a, a .+^ v, b .+^ v, b ]+ where+ v = perp (a .-. c)++-- | Builds an arc to fit with a given radius, center, start, and end points.+-- A Negative r means a counter-clockwise arc+capArc :: Double -> P2 -> P2 -> P2 -> Trail R2+capArc r c a b = trailLike . moveTo c $ fs+ where+ fs | r < 0 = scale (-r) $ arcVCW (a .-. c) (b .-. c)+ | otherwise = scale r $ arcV (a .-. c) (b .-. c)++-- Arc helpers+arcV :: (TrailLike t, V t ~ R2) => R2 -> R2 -> t+arcV u v = arc (direction u) (direction v :: Turn)++arcVCW :: (TrailLike t, V t ~ R2) => R2 -> R2 -> t+arcVCW u v = arcCW (direction u) (direction v :: Turn)+++-- | Join together a list of located trails with the given join style. The+-- style is given as a function to compute the join given the local information+-- of the original vertex, the previous trail, and the next trail. The result+-- is a single located trail. A join radius is also given to aid in arc joins.+--+-- Note: this is not a general purpose join and assumes that we are joining an+-- offset trail. For instance, a fixed radius arc will not fit between arbitrary+-- trails without trimming or extending.+joinSegments :: (Double -> Double -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Trail R2)+ -> Bool+ -> Double+ -> Double+ -> [Point R2]+ -> [Located (Trail R2)]+ -> Located (Trail R2)+joinSegments _ _ _ _ _ [] = mempty `at` origin+joinSegments _ _ _ _ [] _ = mempty `at` origin+joinSegments j isLoop ml r es ts@(t:_) = t'+ where+ t' | isLoop = mapLoc (glueTrail . (<> mconcat (take (length ts) $ ss es (ts ++ [t])))) t+ | otherwise = mapLoc (<> mconcat (ss es ts)) t+ ss es' ts' = [j ml r e a b <> unLoc b | (e,(a,b)) <- zip es' . (zip <*> tail) $ ts']++-- | Take a join style and give the join function to be used by joinSegments.+fromLineJoin+ :: LineJoin -> Double -> Double -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Trail R2+fromLineJoin j = case j of+ LineJoinMiter -> joinSegmentIntersect+ LineJoinRound -> joinSegmentArc+ LineJoinBevel -> joinSegmentClip++-- TODO: The joinSegmentCut option is not in our standard line joins. I don't know+-- how useful it is graphically, I mostly had it as it was useful for debugging+{-+-- | Join with segments going back to the original corner.+joinSegmentCut :: Double -> Double -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Trail R2+joinSegmentCut _ _ e a b = fromSegments+ [ straight (e .-. atEnd a)+ , straight (atStart b .-. e)+ ]+-}++-- | Join by directly connecting the end points. On an inside corner this+-- creates negative space for even-odd fill. Here is where we would want to+-- use an arc or something else in the future.+joinSegmentClip :: Double -> Double -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Trail R2+joinSegmentClip _ _ _ a b = fromSegments [straight $ atStart b .-. atEnd a]++-- | Join with a radius arc. On an inside corner this will loop around the interior+-- of the offset trail. With a winding fill this will not be visible.+joinSegmentArc :: Double -> Double -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Trail R2+joinSegmentArc _ r e a b = capArc r e (atEnd a) (atStart b)++-- | Join to the intersection of the incoming trails projected tangent to their ends.+-- If the intersection is beyond the miter limit times the radius, stop at the limit.+joinSegmentIntersect+ :: Double -> Double -> P2 -> Located (Trail R2) -> Located (Trail R2) -> Trail R2+joinSegmentIntersect miterLimit r e a b = + if cross < 0.000001+ then clip+ else case traceP pa va t of+ -- clip join when we excede the miter limit. We could instead+ -- Join at exactly the miter limit, but standard behavior seems+ -- to be clipping.+ Nothing -> clip+ Just p+ -- If trace gave us garbage...+ | p `distance` pb > abs (miterLimit * r) -> clip+ | otherwise -> unLoc $ fromVertices [ pa, p, pb ]+ where+ t = straight (miter vb) `at` pb+ va = unitPerp (pa .-. e)+ vb = -unitPerp (pb .-. e)+ pa = atEnd a+ pb = atStart b+ miter v = (abs (miterLimit * r)) *^ v+ clip = joinSegmentClip miterLimit r e a b+ cross = let (xa,ya) = unr2 va; (xb,yb) = unr2 vb in abs (xa * yb - xb * ya)+
src/Diagrams/TwoD/Path.hs view
@@ -3,6 +3,8 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-orphans #-}@@ -23,14 +25,15 @@ module Diagrams.TwoD.Path ( -- * Constructing path-based diagrams - stroke, stroke', strokeT, strokeT', strokeLine, strokeLoop- , strokeLocT, strokeLocLine, strokeLocLoop+ stroke, stroke', strokeTrail, strokeT, strokeTrail', strokeT'+ , strokeLine, strokeLoop+ , strokeLocTrail, strokeLocT, strokeLocLine, strokeLocLoop -- ** Stroke options , FillRule(..) , FillRuleA(..), getFillRule, fillRule- , StrokeOpts(..)+ , StrokeOpts(..), vertexNames, queryFillRule -- ** Inside/outside testing @@ -42,6 +45,9 @@ ) where import Control.Applicative (liftA2)+import Control.Lens ( makeWrapped, makeLensesWith, (.~), (^.)+ , generateSignatures, lensRules, op+ , Lens, Lens', unwrapped) import qualified Data.Foldable as F import Data.Semigroup import Data.Typeable@@ -59,7 +65,7 @@ import Diagrams.Solve import Diagrams.Trail import Diagrams.TrailLike-import Diagrams.TwoD.Segment+import Diagrams.TwoD.Segment () import Diagrams.TwoD.Types import Diagrams.Util (tau) @@ -79,12 +85,66 @@ . lineSegments instance Traced (Path R2) where- getTrace = F.foldMap getTrace . pathTrails+ getTrace = F.foldMap getTrace . op Path ------------------------------------------------------------ -- Constructing path-based diagrams ---------------------- ------------------------------------------------------------ +-- | Enumeration of algorithms or \"rules\" for determining which+-- points lie in the interior of a (possibly self-intersecting)+-- closed path.+data FillRule = Winding -- ^ Interior points are those with a nonzero+ -- /winding/ /number/. See+ -- <http://en.wikipedia.org/wiki/Nonzero-rule>.+ | EvenOdd -- ^ Interior points are those where a ray+ -- extended infinitely in a particular+ -- direction crosses the path an odd number+ -- of times. See+ -- <http://en.wikipedia.org/wiki/Even-odd_rule>.+ deriving (Eq, Show)++instance Default FillRule where+ def = Winding++-- | A record of options that control how a path is stroked.+-- @StrokeOpts@ is an instance of 'Default', so a @StrokeOpts@+-- records can be created using @'with' { ... }@ notation.+data StrokeOpts a+ = StrokeOpts+ { _vertexNames :: [[a]]++ , _queryFillRule :: FillRule++ }++makeLensesWith (generateSignatures .~ False $ lensRules) ''StrokeOpts++-- | Atomic names that should be assigned to the vertices of the path so that+-- they can be referenced later. If there are not enough names, the extra+-- vertices are not assigned names; if there are too many, the extra names+-- are ignored. Note that this is a /list of lists/ of names, since paths+-- can consist of multiple trails. The first list of names are assigned to+-- the vertices of the first trail, the second list to the second trail, and+-- so on.+--+-- The default value is the empty list.++vertexNames :: forall a a'. Lens (StrokeOpts a) (StrokeOpts a') [[a]] [[a']]++-- | The fill rule used for determining which points are inside the path.+-- The default is 'Winding'. NOTE: for now, this only affects the resulting+-- diagram's 'Query', /not/ how it will be drawn! To set the fill rule+-- determining how it is to be drawn, use the 'fillRule' function.+queryFillRule :: forall a. Lens' (StrokeOpts a) FillRule+++instance Default (StrokeOpts a) where+ def = StrokeOpts+ { _vertexNames = []+ , _queryFillRule = def+ }+ -- | Convert a path into a diagram. The resulting diagram has the -- names 0, 1, ... assigned to each of the path's vertices. --@@ -111,75 +171,46 @@ -- ... }@ syntax may be used. stroke' :: (Renderable (Path R2) b, IsName a) => StrokeOpts a -> Path R2 -> Diagram b R2 stroke' opts path- | null (pathTrails p1) = mkP p2- | null (pathTrails p2) = mkP p1- | otherwise = mkP p1 <> mkP p2+ | null (pLines ^. unwrapped) = mkP pLoops+ | null (pLoops ^. unwrapped) = mkP pLines+ | otherwise = mkP pLines <> mkP pLoops where- (p1,p2) = partitionPath (isLine . unLoc) path+ (pLines,pLoops) = partitionPath (isLine . unLoc) path mkP p = mkQD (Prim p) (getEnvelope p) (getTrace p) (fromNames . concat $- zipWith zip (vertexNames opts) ((map . map) subPoint (pathVertices p))+ zipWith zip (opts^.vertexNames) ((map . map) subPoint (pathVertices p)) )- (Query $ Any . flip (runFillRule (queryFillRule opts)) p)+ (Query $ Any . flip (runFillRule (opts^.queryFillRule)) p) --- | A record of options that control how a path is stroked.--- @StrokeOpts@ is an instance of 'Default', so a @StrokeOpts@--- records can be created using @'with' { ... }@ notation.-data StrokeOpts a- = StrokeOpts- { vertexNames :: [[a]] -- ^ Atomic names that should be assigned- -- to the vertices of the path so that- -- they can be referenced later. If- -- there are not enough names, the extra- -- vertices are not assigned names; if- -- there are too many, the extra names- -- are ignored. Note that this is a- -- /list of lists/ of names, since paths- -- can consist of multiple trails. The- -- first list of names are assigned to- -- the vertices of the first trail, the- -- second list to the second trail, and- -- so on.- --- -- The default value is the empty list. - , queryFillRule :: FillRule- -- ^ The fill rule used for determining- -- which points are inside the path.- -- The default is 'Winding'. NOTE: for- -- now, this only affects the resulting- -- diagram's 'Query', /not/ how it will- -- be drawn! To set the fill rule- -- determining how it is to be drawn,- -- use the 'fillRule' function.- }--instance Default (StrokeOpts a) where- def = StrokeOpts- { vertexNames = []- , queryFillRule = Winding- }- -- | A composition of 'stroke' and 'pathFromTrail' for conveniently -- converting a trail directly into a diagram. -- -- Note that a bug in GHC 7.0.1 causes a context stack overflow when--- inferring the type of 'stroke' and hence of @strokeT@ as well.+-- inferring the type of 'stroke' and hence of @strokeTrail@ as well. -- The solution is to give a type signature to expressions involving--- @strokeT@, or (recommended) upgrade GHC (the bug is fixed in 7.0.2+-- @strokeTrail@, or (recommended) upgrade GHC (the bug is fixed in 7.0.2 -- onwards).-strokeT :: (Renderable (Path R2) b)- => Trail R2 -> Diagram b R2-strokeT = stroke . pathFromTrail+strokeTrail :: (Renderable (Path R2) b) => Trail R2 -> Diagram b R2+strokeTrail = stroke . pathFromTrail +-- | Deprecated synonym for 'strokeTrail'.+strokeT :: (Renderable (Path R2) b) => Trail R2 -> Diagram b R2+strokeT = strokeTrail+ -- | A composition of 'stroke'' and 'pathFromTrail' for conveniently -- converting a trail directly into a diagram.+strokeTrail' :: (Renderable (Path R2) b, IsName a)+ => StrokeOpts a -> Trail R2 -> Diagram b R2+strokeTrail' opts = stroke' opts . pathFromTrail++-- | Deprecated synonym for 'strokeTrail''. strokeT' :: (Renderable (Path R2) b, IsName a) => StrokeOpts a -> Trail R2 -> Diagram b R2-strokeT' opts = stroke' opts . pathFromTrail+strokeT' = strokeTrail' -- | A composition of 'strokeT' and 'wrapLine' for conveniently -- converting a line directly into a diagram.@@ -192,9 +223,13 @@ strokeLoop = strokeT . wrapLoop -- | A convenience function for converting a @Located Trail@ directly--- into a diagram; @strokeLocT = stroke . trailLike@.+-- into a diagram; @strokeLocTrail = stroke . trailLike@.+strokeLocTrail :: (Renderable (Path R2) b) => Located (Trail R2) -> Diagram b R2+strokeLocTrail = stroke . trailLike++-- | Deprecated synonym for 'strokeLocTrail'. strokeLocT :: (Renderable (Path R2) b) => Located (Trail R2) -> Diagram b R2-strokeLocT = stroke . trailLike+strokeLocT = strokeLocTrail -- | A convenience function for converting a @Located@ line directly -- into a diagram; @strokeLocLine = stroke . trailLike . mapLoc wrapLine@.@@ -210,27 +245,19 @@ -- Inside/outside testing ------------------------------------------------------------ --- | Enumeration of algorithms or \"rules\" for determining which--- points lie in the interior of a (possibly self-intersecting)--- closed path.-data FillRule = Winding -- ^ Interior points are those with a nonzero- -- /winding/ /number/. See- -- <http://en.wikipedia.org/wiki/Nonzero-rule>.- | EvenOdd -- ^ Interior points are those where a ray- -- extended infinitely in a particular- -- direction crosses the path an odd number- -- of times. See- -- <http://en.wikipedia.org/wiki/Even-odd_rule>.- deriving (Eq) + runFillRule :: FillRule -> P2 -> Path R2 -> Bool runFillRule Winding = isInsideWinding runFillRule EvenOdd = isInsideEvenOdd newtype FillRuleA = FillRuleA (Last FillRule)- deriving (Typeable, Semigroup)+ deriving (Typeable, Semigroup, Show) instance AttributeClass FillRuleA +instance Default FillRuleA where+ def = FillRuleA $ Last $ def+ -- | Extract the fill rule from a 'FillRuleA' attribute. getFillRule :: FillRuleA -> FillRule getFillRule (FillRuleA (Last r)) = r@@ -263,7 +290,7 @@ -- | Compute the sum of /signed/ crossings of a path as we travel in the -- positive x direction from a given point. crossings :: P2 -> Path R2 -> Int-crossings p = F.sum . map (trailCrossings p) . pathTrails+crossings p = F.sum . map (trailCrossings p) . op Path -- | Compute the sum of signed crossings of a trail starting from the -- given point in the positive x direction.@@ -313,8 +340,11 @@ -- concatenation, so applying multiple clipping paths is sensible. -- The clipping region is the intersection of all the applied -- clipping paths.-newtype Clip = Clip { getClip :: [Path R2] }+newtype Clip = Clip [Path R2] deriving (Typeable, Semigroup)++makeWrapped ''Clip+ instance AttributeClass Clip type instance V Clip = R2
src/Diagrams/TwoD/Polygons.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} @@ -20,7 +21,7 @@ -- * Polygons PolyType(..) , PolyOrientation(..)- , PolygonOpts(..)+ , PolygonOpts(..), polyType, polyOrient, polyCenter , polygon , polyTrail@@ -44,13 +45,12 @@ ) where +import Control.Lens hiding (transform, at, (<.>), (&), (#)) import Control.Monad (forM, liftM) import Control.Monad.ST (ST, runST) import Data.Array.ST (STUArray, newArray, readArray, writeArray)-import qualified Data.Foldable as F import Data.List (maximumBy, minimumBy)-import qualified Data.List.NonEmpty as NEL import Data.Maybe (catMaybes) import Data.Monoid (mconcat, mempty) import Data.Ord (comparing)@@ -64,7 +64,6 @@ import Diagrams.Located import Diagrams.Path import Diagrams.Points (centroid)-import Diagrams.Segment import Diagrams.Trail import Diagrams.TrailLike import Diagrams.TwoD.Transform@@ -138,20 +137,24 @@ -- | Options for specifying a polygon. data PolygonOpts = PolygonOpts- { polyType :: PolyType- -- ^ Specification for the polygon's vertices.+ { _polyType :: PolyType+ , _polyOrient :: PolyOrientation+ , _polyCenter :: P2+ } - , polyOrient :: PolyOrientation- -- ^ Should a rotation be applied to the- -- polygon in order to orient it in a- -- particular way?+makeLensesWith (generateSignatures .~ False $ lensRules) ''PolygonOpts - , polyCenter :: P2- -- ^ Should a translation be applied to the- -- polygon in order to place the center at a- -- particular location?- }+-- | Specification for the polygon's vertices.+polyType :: Lens' PolygonOpts PolyType +-- | Should a rotation be applied to the polygon in order to orient it in a+-- particular way?+polyOrient :: Lens' PolygonOpts PolyOrientation++-- | Should a translation be applied to the polygon in order to place the center+-- at a particular location?+polyCenter :: Lens' PolygonOpts P2+ -- | The default polygon is a regular pentagon of radius 1, centered -- at the origin, aligned to the x-axis. instance Default PolygonOpts where@@ -161,11 +164,11 @@ polyTrail :: PolygonOpts -> Located (Trail R2) polyTrail po = transform ori tr where- tr = case polyType po of+ tr = case po^.polyType of PolyPolar ans szs -> polyPolarTrail ans szs PolySides ans szs -> polySidesTrail ans szs PolyRegular n r -> polyRegularTrail n r- ori = case polyOrient po of+ ori = case po^.polyOrient of OrientH -> orient unit_Y tr OrientV -> orient unitX tr OrientTo v -> orient v tr@@ -219,7 +222,7 @@ (n1,x,n2) = maximumBy (comparing (distAlong v . sndOf3)) (zip3 (tail (cycle xs)) xs (last xs : init xs)) distAlong w ((.-. origin) -> p) = signum (w <.> p) * magnitude (project w p)- sndOf3 (_,x,_) = x+ sndOf3 (_,b,_) = b a = minimumBy (comparing abs) . map (angleFromNormal . (.-. x)) $ [n1,n2] v' = normalized v angleFromNormal o
src/Diagrams/TwoD/Segment.hs view
@@ -2,6 +2,11 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} +{-# OPTIONS_GHC -fno-warn-orphans #-}+-- Orphan Traced instances for Segment Closed R2 and FixedSegment R2.+-- They can't go in Traced; but they shouldn't really go in+-- Diagrams.Segment either because we only have Traced instances for+-- the special case of R2. ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Segment@@ -23,7 +28,6 @@ import Data.VectorSpace import Diagrams.Core-import Diagrams.Core.Trace import Diagrams.Located import Diagrams.Parametric@@ -64,7 +68,6 @@ let v0 = p0' .-. p0 det = perp v1 <.> v0- perp v = rotateBy (-1/4) v p = p1 .-. p0 t0 = (perp v1 <.> p) / det t1 = (perp v0 <.> p) / det
src/Diagrams/TwoD/Shapes.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} -----------------------------------------------------------------------------@@ -25,6 +26,7 @@ , square , pentagon , hexagon+ , heptagon , septagon , octagon , nonagon@@ -39,13 +41,12 @@ -- * Other shapes , roundedRect- , RoundedRectOpts(..)+ , RoundedRectOpts(..), radiusTL, radiusTR, radiusBL, radiusBR , roundedRect' ) where import Diagrams.Core -import Diagrams.Coordinates import Diagrams.Located (at) import Diagrams.Path import Diagrams.Segment@@ -58,53 +59,54 @@ import Diagrams.Util +import Control.Lens (makeLenses, op, (.~), (^.), (&)) import Data.Default.Class import Data.Semigroup -- | Create a centered horizontal (L-R) line of the given length. ----- <<diagrams/hruleEx.svg#diagram=hruleEx&width=300>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_hruleEx.svg#diagram=hruleEx&width=300>> ----- > hruleEx = vcat' with {sep = 0.2} (map hrule [1..5])+-- > hruleEx = vcat' (with & sep .~ 0.2) (map hrule [1..5]) -- > # centerXY # pad 1.1 hrule :: (TrailLike t, V t ~ R2) => Double -> t-hrule d = trailLike $ trailFromSegments [straight (d & 0)] `at` (p2 (-d/2,0))+hrule d = trailLike $ trailFromSegments [straight $ r2 (d, 0)] `at` (p2 (-d/2,0)) -- | Create a centered vertical (T-B) line of the given length. ----- <<diagrams/vruleEx.svg#diagram=vruleEx&height=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_vruleEx.svg#diagram=vruleEx&height=100>> ----- > vruleEx = hcat' with {sep = 0.2} (map vrule [1, 1.2 .. 2])+-- > vruleEx = hcat' (with & sep .~ 0.2) (map vrule [1, 1.2 .. 2]) -- > # centerXY # pad 1.1 vrule :: (TrailLike t, V t ~ R2) => Double -> t-vrule d = trailLike $ trailFromSegments [straight (0 & (-d))] `at` (p2 (0,d/2))+vrule d = trailLike $ trailFromSegments [straight $ r2 (0, (-d))] `at` (p2 (0,d/2)) -- | A square with its center at the origin and sides of length 1, -- oriented parallel to the axes. ----- <<diagrams/unitSquareEx.svg#diagram=unitSquareEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_unitSquareEx.svg#diagram=unitSquareEx&width=100>> unitSquare :: (TrailLike t, V t ~ R2) => t-unitSquare = polygon with { polyType = PolyRegular 4 (sqrt 2 / 2)- , polyOrient = OrientH }+unitSquare = polygon (def & polyType .~ PolyRegular 4 (sqrt 2 / 2)+ & polyOrient .~ OrientH) -- > unitSquareEx = unitSquare # pad 1.1 # showOrigin -- | A square with its center at the origin and sides of the given -- length, oriented parallel to the axes. ----- <<diagrams/squareEx.svg#diagram=squareEx&width=200>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_squareEx.svg#diagram=squareEx&width=200>> square :: (TrailLike t, Transformable t, V t ~ R2) => Double -> t square d = rect d d --- > squareEx = hcat' with {sep = 0.5} [square 1, square 2, square 3]+-- > squareEx = hcat' (with & sep .~ 0.5) [square 1, square 2, square 3] -- > # centerXY # pad 1.1 # lw 0.03 -- | @rect w h@ is an axis-aligned rectangle of width @w@ and height -- @h@, centered at the origin. ----- <<diagrams/rectEx.svg#diagram=rectEx&width=150>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_rectEx.svg#diagram=rectEx&width=150>> rect :: (TrailLike t, Transformable t, V t ~ R2) => Double -> Double -> t-rect w h = trailLike . head . pathTrails $ unitSquare # scaleX w # scaleY h+rect w h = trailLike . head . op Path $ unitSquare # scaleX w # scaleY h -- > rectEx = rect 1 0.7 # pad 1.1 @@ -136,18 +138,18 @@ -- -- The polygon will be oriented with one edge parallel to the x-axis. regPoly :: (TrailLike t, V t ~ R2) => Int -> Double -> t-regPoly n l = polygon with { polyType =+regPoly n l = polygon (def & polyType .~ PolySides (repeat (1/ fromIntegral n :: Turn)) (replicate (n-1) l)- , polyOrient = OrientH- }+ & polyOrient .~ OrientH+ ) -- > shapeEx sh = sh 1 # pad 1.1 -- > triangleEx = shapeEx triangle -- > pentagonEx = shapeEx pentagon -- > hexagonEx = shapeEx hexagon--- > septagonEx = shapeEx septagon+-- > heptagonEx = shapeEx heptagon -- > octagonEx = shapeEx octagon -- > nonagonEx = shapeEx nonagon -- > decagonEx = shapeEx decagon@@ -161,70 +163,86 @@ -- | An equilateral triangle, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/triangleEx.svg#diagram=triangleEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_triangleEx.svg#diagram=triangleEx&width=100>> triangle :: (TrailLike t, V t ~ R2) => Double -> t triangle = regPoly 3 -- | A regular pentagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/pentagonEx.svg#diagram=pentagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_pentagonEx.svg#diagram=pentagonEx&width=100>> pentagon :: (TrailLike t, V t ~ R2) => Double -> t pentagon = regPoly 5 -- | A regular hexagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/hexagonEx.svg#diagram=hexagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_hexagonEx.svg#diagram=hexagonEx&width=100>> hexagon :: (TrailLike t, V t ~ R2) => Double -> t hexagon = regPoly 6 --- | A regular septagon, with sides of the given length and base+-- | A regular heptagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/septagonEx.svg#diagram=septagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_heptagonEx.svg#diagram=heptagonEx&width=100>>+heptagon :: (TrailLike t, V t ~ R2) => Double -> t+heptagon = regPoly 7++-- | A synonym for 'heptagon'. It is, however, completely inferior,+-- being a base admixture of the Latin /septum/ (seven) and the+-- Greek γωνία (angle). septagon :: (TrailLike t, V t ~ R2) => Double -> t-septagon = regPoly 7+septagon = heptagon -- | A regular octagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/octagonEx.svg#diagram=octagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_octagonEx.svg#diagram=octagonEx&width=100>> octagon :: (TrailLike t, V t ~ R2) => Double -> t octagon = regPoly 8 -- | A regular nonagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/nonagonEx.svg#diagram=nonagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_nonagonEx.svg#diagram=nonagonEx&width=100>> nonagon :: (TrailLike t, V t ~ R2) => Double -> t nonagon = regPoly 9 -- | A regular decagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/decagonEx.svg#diagram=decagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_decagonEx.svg#diagram=decagonEx&width=100>> decagon :: (TrailLike t, V t ~ R2) => Double -> t decagon = regPoly 10 -- | A regular hendecagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/hendecagonEx.svg#diagram=hendecagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_hendecagonEx.svg#diagram=hendecagonEx&width=100>> hendecagon :: (TrailLike t, V t ~ R2) => Double -> t hendecagon = regPoly 11 -- | A regular dodecagon, with sides of the given length and base -- parallel to the x-axis. ----- <<diagrams/dodecagonEx.svg#diagram=dodecagonEx&width=100>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_dodecagonEx.svg#diagram=dodecagonEx&width=100>> dodecagon :: (TrailLike t, V t ~ R2) => Double -> t dodecagon = regPoly 12 ------------------------------------------------------------ -- Other shapes ------------------------------------------ ------------------------------------------------------------+data RoundedRectOpts = RoundedRectOpts { _radiusTL :: Double+ , _radiusTR :: Double+ , _radiusBL :: Double+ , _radiusBR :: Double+ } +makeLenses ''RoundedRectOpts++instance Default RoundedRectOpts where+ def = RoundedRectOpts 0 0 0 0+ -- | @roundedRect w h r@ generates a closed trail, or closed path -- centered at the origin, of an axis-aligned rectangle with width -- @w@, height @h@, and circular rounded corners of radius @r@. If@@ -236,21 +254,21 @@ -- a different radius for each corner individually, use -- 'roundedRect'' instead. ----- <<diagrams/roundedRectEx.svg#diagram=roundedRectEx&width=400>>+-- <<diagrams/src_Diagrams_TwoD_Shapes_roundedRectEx.svg#diagram=roundedRectEx&width=400>> ----- > roundedRectEx = pad 1.1 . centerXY $ hcat' with { sep = 0.2 }+-- > roundedRectEx = pad 1.1 . centerXY $ hcat' (with & sep .~ 0.2) -- > [ roundedRect 0.5 0.4 0.1 -- > , roundedRect 0.5 0.4 (-0.1)--- > , roundedRect' 0.7 0.4 with { radiusTL = 0.2--- > , radiusTR = -0.2--- > , radiusBR = 0.1 }+-- > , roundedRect' 0.7 0.4 (with & radiusTL .~ 0.2+-- > & radiusTR .~ -0.2+-- > & radiusBR .~ 0.1) -- > ] roundedRect :: (TrailLike t, V t ~ R2) => Double -> Double -> Double -> t-roundedRect w h r = roundedRect' w h (with { radiusTL = r,- radiusBR = r,- radiusTR = r,- radiusBL = r})+roundedRect w h r = roundedRect' w h (def & radiusTL .~ r+ & radiusBR .~ r+ & radiusTR .~ r+ & radiusBL .~ r) -- | @roundedRect'@ works like @roundedRect@ but allows you to set the radius of -- each corner indivually, using @RoundedRectOpts@. The default corner radius is 0.@@ -279,7 +297,7 @@ rBL = clampCnr radiusBR radiusTL radiusTR radiusBL rTR = clampCnr radiusTL radiusBR radiusBL radiusTR rBR = clampCnr radiusBL radiusTR radiusTL radiusBR- clampCnr rx ry ro r = let (rx',ry',ro',r') = (rx opts, ry opts, ro opts, r opts)+ clampCnr rx ry ro r = let (rx',ry',ro',r') = (opts^.rx, opts^.ry, opts^.ro, opts^.r) in clampDiag ro' . clampAdj h ry' . clampAdj w rx' $ r' -- prevent curves of adjacent corners from overlapping clampAdj len adj r = if abs r > len/2@@ -294,11 +312,3 @@ | r < 0 = doArc 3 2 | otherwise = doArc 0 1 where doArc d d' = arc' r ((k+d)/4) ((k+d')/4:: Turn)--data RoundedRectOpts = RoundedRectOpts { radiusTL :: Double- , radiusTR :: Double- , radiusBL :: Double- , radiusBR :: Double- }-instance Default RoundedRectOpts where- def = RoundedRectOpts 0 0 0 0
src/Diagrams/TwoD/Size.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-}++{-# OPTIONS_GHC -funbox-strict-fields #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Size@@ -78,15 +80,15 @@ ------------------------------------------------------------ -- | A specification of a (requested) rectangular size.-data SizeSpec2D = Width Double -- ^ Specify an explicit+data SizeSpec2D = Width !Double -- ^ Specify an explicit -- width. The height should be -- determined automatically (so -- as to preserve aspect ratio).- | Height Double -- ^ Specify an explicit+ | Height !Double -- ^ Specify an explicit -- height. The width should be -- determined automatically (so -- as to preserve aspect ratio).- | Dims Double Double -- ^ An explicit specification+ | Dims !Double !Double -- ^ An explicit specification -- of a width and height. | Absolute -- ^ Absolute size: use whatever -- size an object already has;
src/Diagrams/TwoD/Text.hs view
@@ -1,9 +1,8 @@-{-# LANGUAGE DeriveDataTypeable- , GeneralizedNewtypeDeriving- , FlexibleContexts- , TypeFamilies- , MultiParamTypeClasses- #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module : Diagrams.TwoD.Text@@ -31,15 +30,16 @@ , FontWeight(..), FontWeightA, getFontWeight, fontWeight, bold ) where -import Diagrams.Attributes-import Diagrams.Core-import Diagrams.TwoD.Types+import Diagrams.Attributes+import Diagrams.Core+import Diagrams.Core.Envelope (pointEnvelope)+import Diagrams.TwoD.Types -import Data.AffineSpace ((.-.))+import Data.AffineSpace ((.-.)) -import Data.Semigroup+import Data.Semigroup -import Data.Colour+import Data.Colour import Data.Default.Class @@ -72,9 +72,11 @@ data TextAlignment = BaselineText | BoxAlignedText Double Double mkText :: Renderable Text b => TextAlignment -> String -> Diagram b R2-mkText a t = recommendFillColor black -- See Note [recommendFillColor]+mkText a t = recommendFillColor (black :: Colour Double)+ -- See Note [recommendFillColor]+ $ mkQD (Prim (Text mempty a t))- mempty+ (pointEnvelope origin) mempty mempty mempty
src/Diagrams/TwoD/Transform.hs view
@@ -45,29 +45,22 @@ , shearingX, shearX , shearingY, shearY - -- * Scale invariance- , ScaleInv(..), scaleInv, scaleInvPrim-- -- * component-wise+ -- * Utilities , onBasis+ , avgScale ) where import Diagrams.Core import qualified Diagrams.Core.Transform as T -import Control.Newtype (over)--import Diagrams.Coordinates import Diagrams.Transform import Diagrams.TwoD.Size (height, width) import Diagrams.TwoD.Types import Diagrams.TwoD.Vector (direction)--import Data.Semigroup+import Diagrams.Coordinates import Data.AffineSpace--import Control.Arrow (first, second)+import Data.Semigroup -- Rotation ------------------------------------------------ @@ -78,7 +71,7 @@ where r = rot theta <-> rot (-theta) Rad theta = convertAngle ang- rot th (coords -> x :& y) = (cos th * x - sin th * y) & (sin th * x + cos th * y)+ rot th (coords -> x :& y) = (cos th * x - sin th * y) ^& (sin th * x + cos th * y) -- | Rotate about the local origin by the given angle. Positive angles -- correspond to counterclockwise rotation, negative to@@ -118,7 +111,7 @@ -- the x (horizontal) direction. scalingX :: Double -> T2 scalingX c = fromLinear s s- where s = (over r2 . first) (*c) <-> (over r2 . first) (/c)+ where s = (\(R2 x y) -> R2 (x*c) y) <-> (\(R2 x y) -> R2 (x/c) y) -- | Scale a diagram by the given factor in the x (horizontal) -- direction. To scale uniformly, use 'scale'.@@ -129,7 +122,7 @@ -- the y (vertical) direction. scalingY :: Double -> T2 scalingY c = fromLinear s s- where s = (over r2 . second) (*c) <-> (over r2 . second) (/c)+ where s = (\(R2 x y) -> R2 x (y*c)) <-> (\(R2 x y) -> R2 x (y/c)) -- | Scale a diagram by the given factor in the y (vertical) -- direction. To scale uniformly, use 'scale'.@@ -167,7 +160,7 @@ -- | Construct a transformation which translates by the given distance -- in the x (horizontal) direction. translationX :: Double -> T2-translationX x = translation (x & 0)+translationX x = translation (x ^& 0) -- | Translate a diagram by the given distance in the x (horizontal) -- direction.@@ -177,7 +170,7 @@ -- | Construct a transformation which translates by the given distance -- in the y (vertical) direction. translationY :: Double -> T2-translationY y = translation (0 & y)+translationY y = translation (0 ^& y) -- | Translate a diagram by the given distance in the y (vertical) -- direction.@@ -223,11 +216,11 @@ -- | @shearingX d@ is the linear transformation which is the identity on -- y coordinates and sends @(0,1)@ to @(d,1)@. shearingX :: Double -> T2-shearingX d = fromLinear (over r2 (sh d) <-> over r2 (sh (-d)))- (over r2 (sh' d) <-> over r2 (sh' (-d)))- where sh k (x, y) = (x+k*y, y)- sh' k = swap . sh k . swap- swap (x,y) = (y,x)+shearingX d = fromLinear (sh d <-> sh (-d))+ (sh' d <-> sh' (-d))+ where sh k (R2 x y) = R2 (x+k*y) y+ sh' k = swap . sh k . swap+ swap (R2 x y) = R2 y x -- | @shearX d@ performs a shear in the x-direction which sends -- @(0,1)@ to @(d,1)@.@@ -237,122 +230,58 @@ -- | @shearingY d@ is the linear transformation which is the identity on -- x coordinates and sends @(1,0)@ to @(1,d)@. shearingY :: Double -> T2-shearingY d = fromLinear (over r2 (sh d) <-> over r2 (sh (-d)))- (over r2 (sh' d) <-> over r2 (sh' (-d)))- where sh k (x,y) = (x, y+k*x)- sh' k = swap . sh k . swap- swap (x,y) = (y,x)+shearingY d = fromLinear (sh d <-> sh (-d))+ (sh' d <-> sh' (-d))+ where sh k (R2 x y) = R2 x (y+k*x)+ sh' k = swap . sh k . swap+ swap (R2 x y) = R2 y x -- | @shearY d@ performs a shear in the y-direction which sends -- @(1,0)@ to @(1,d)@. shearY :: (Transformable t, V t ~ R2) => Double -> t -> t shearY = transform . shearingY ---- Scale invariance ----------------------------------------+-- | Get the matrix equivalent of the linear transform,+-- (as a pair of columns) and the translation vector. This+-- is mostly useful for implementing backends.+onBasis :: Transformation R2 -> ((R2, R2), R2)+onBasis t = ((x, y), v)+ where ((x:y:[]), v) = T.onBasis t --- | The @ScaleInv@ wrapper creates two-dimensional /scale-invariant/--- objects. Intuitively, a scale-invariant object is affected by--- transformations like translations and rotations, but not by scales.------ However, this is problematic when it comes to /non-uniform/--- scales (/e.g./ @scaleX 2 . scaleY 3@) since they can introduce a--- perceived rotational component. The prototypical example is an--- arrowhead on the end of a path, which should be scale-invariant.--- However, applying a non-uniform scale to the path but not the--- arrowhead would leave the arrowhead pointing in the wrong--- direction.------ Moreover, for objects whose local origin is not at the local--- origin of the parent diagram, any scale can result in a--- translational component as well.------ The solution is to also store a point (indicating the location,--- /i.e./ the local origin) and a unit vector (indicating the--- /direction/) along with a scale-invariant object. A--- transformation to be applied is decomposed into rotational and--- translational components as follows:+-- | Compute the \"average\" amount of scaling performed by a+-- transformation. Satisfies the properties ----- * The transformation is applied to the direction vector, and the--- difference in angle between the original direction vector and its--- image under the transformation determines the rotational--- component. The rotation is applied with respect to the stored--- location, rather than the global origin.+-- @+-- avgScale (scaling k) == k+-- avgScale (t1 <> t2) == avgScale t1 * avgScale t2+-- @ ----- * The vector from the location to the image of the location under--- the transformation determines the translational component.--data ScaleInv t =- ScaleInv- { unScaleInv :: t- , scaleInvDir :: R2- , scaleInvLoc :: P2- }- deriving (Show)---- | Create a scale-invariant object pointing in the given direction,--- located at the origin.-scaleInv :: t -> R2 -> ScaleInv t-scaleInv t d = ScaleInv t d origin--type instance V (ScaleInv t) = R2--instance (V t ~ R2, HasOrigin t) => HasOrigin (ScaleInv t) where- moveOriginTo p (ScaleInv t v l) = ScaleInv (moveOriginTo p t) v (moveOriginTo p l)--instance (V t ~ R2, Transformable t) => Transformable (ScaleInv t) where- transform tr (ScaleInv t v l) = ScaleInv (trans . rot $ t) (rot v) l'- where- angle :: Rad- angle = direction (transform tr v) - direction v- rot :: (Transformable t, V t ~ R2) => t -> t- rot = rotateAbout l angle- l' = transform tr l- trans = translate (l' .-. l)+-- Backends which do not support stroking in the context of an+-- arbitrary transformation may instead call 'avgScale' on+-- \"frozen\" transformations and multiply the line width by the+-- resulting value.+avgScale :: T2 -> Double+avgScale t = sqrt (abs (x1*y2 - y1*x2))+ where ((unr2 -> (x1,y1), unr2 -> (x2,y2)), _) = onBasis t --- This is how we handle freezing properly with ScaleInv wrappers.--- Normal transformations are applied ignoring scaling; "frozen"--- transformations (i.e. transformations applied after a freeze) are--- applied directly to the underlying object, scales and all. We must--- take care to transform the reference point and direction vector--- appropriately.-instance (V t ~ R2, Transformable t) => IsPrim (ScaleInv t) where- transformWithFreeze t1 t2 s = ScaleInv t'' d'' origin''- where- -- first, apply t2 normally, i.e. ignoring scaling- s'@(ScaleInv t' _ _) = transform t2 s+{- - -- now apply t1 to get the new direction and origin- (ScaleInv _ d'' origin'') = transform t1 s'+avgScale is computed as the square root of the positive+determinant. Proofs for the specified properties: - -- but apply t1 directly to the underlying thing, scales and all.- t'' = transform t1 t'+1. sqrt (|det (scaling k)|) = sqrt (k^2) = k+2. sqrt (|det t1|) * sqrt (|det t2|)+ = sqrt (|det t1| * |det t2|)+ = sqrt (|det t1 * det t2|)+ = sqrt (|det (t1 * t2)|) -instance (Renderable t b, V t ~ R2) => Renderable (ScaleInv t) b where- render b = render b . unScaleInv+From wikipedia: --- | Create a diagram from a single scale-invariant primitive. The--- vector argument specifies the direction in which the primitive is--- \"pointing\" (for the purpose of keeping it rotated correctly--- under non-uniform scaling). The primitive is assumed to be--- \"located\" at the origin (for the purpose of translating it--- correctly under scaling).------ Note that the resulting diagram will have an /empty/ envelope,--- trace, and query. The reason is that the envelope, trace, and--- query cannot be cached---applying a transformation would cause--- the cached envelope, etc. to get \"out of sync\" with the--- scale-invariant object. The intention, at any rate, is that--- scale-invariant things will be used only as \"decorations\" (/e.g./--- arrowheads) which should not affect the envelope, trace, and--- query.-scaleInvPrim :: (Transformable t, Renderable t b, V t ~ R2, Monoid m)- => t -> R2 -> QDiagram b R2 m-scaleInvPrim t d = mkQD (Prim $ scaleInv t d) mempty mempty mempty mempty+ A geometric interpretation can be given to the value of the+ determinant of a square matrix with real entries: the absolute+ value of the determinant gives the scale factor by which area or+ volume (or a higher dimensional analogue) is multiplied under the+ associated linear transformation, while its sign indicates whether+ the transformation preserves orientation. --- | Get the matrix equivalent of the linear transform,--- (as a pair of columns) and the translation vector. This--- is mostly useful for implementing backends.-onBasis :: Transformation R2 -> ((R2, R2), R2)-onBasis t = ((x, y), v)- where ((x:y:[]), v) = T.onBasis t+-}
+ src/Diagrams/TwoD/Transform/ScaleInv.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.TwoD.Transform.ScaleInv+-- Copyright : (c) 2012-2013 diagrams-lib team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Wrapper for creating scale-invariant objects in two dimensions.+--+-----------------------------------------------------------------------------++module Diagrams.TwoD.Transform.ScaleInv+ ( ScaleInv(..)+ , scaleInvObj, scaleInvDir, scaleInvLoc+ , scaleInv, scaleInvPrim )+ where++import Control.Lens (makeLenses, view)+import Data.AffineSpace ((.-.))+import Data.Semigroup++import Diagrams.Core+import Diagrams.TwoD.Transform+import Diagrams.TwoD.Types+import Diagrams.TwoD.Vector++-- | The @ScaleInv@ wrapper creates two-dimensional /scale-invariant/+-- objects. Intuitively, a scale-invariant object is affected by+-- transformations like translations and rotations, but not by scales.+--+-- However, this is problematic when it comes to /non-uniform/+-- scales (/e.g./ @scaleX 2 . scaleY 3@) since they can introduce a+-- perceived rotational component. The prototypical example is an+-- arrowhead on the end of a path, which should be scale-invariant.+-- However, applying a non-uniform scale to the path but not the+-- arrowhead would leave the arrowhead pointing in the wrong+-- direction.+--+-- Moreover, for objects whose local origin is not at the local+-- origin of the parent diagram, any scale can result in a+-- translational component as well.+--+-- The solution is to also store a point (indicating the location,+-- /i.e./ the local origin) and a unit vector (indicating the+-- /direction/) along with a scale-invariant object. A+-- transformation to be applied is decomposed into rotational and+-- translational components as follows:+--+-- * The transformation is applied to the direction vector, and the+-- difference in angle between the original direction vector and its+-- image under the transformation determines the rotational+-- component. The rotation is applied with respect to the stored+-- location, rather than the global origin.+--+-- * The vector from the location to the image of the location under+-- the transformation determines the translational component.++data ScaleInv t =+ ScaleInv+ { _scaleInvObj :: t+ , _scaleInvDir :: R2+ , _scaleInvLoc :: P2+ }+ deriving (Show)++makeLenses ''ScaleInv++-- | Create a scale-invariant object pointing in the given direction,+-- located at the origin.+scaleInv :: t -> R2 -> ScaleInv t+scaleInv t d = ScaleInv t d origin++type instance V (ScaleInv t) = R2++instance (V t ~ R2, HasOrigin t) => HasOrigin (ScaleInv t) where+ moveOriginTo p (ScaleInv t v l) = ScaleInv (moveOriginTo p t) v (moveOriginTo p l)++instance (V t ~ R2, Transformable t) => Transformable (ScaleInv t) where+ transform tr (ScaleInv t v l) = ScaleInv (trans . rot $ t) (rot v) l'+ where+ angle :: Rad+ angle = direction (transform tr v) - direction v+ rot :: (Transformable t, V t ~ R2) => t -> t+ rot = rotateAbout l angle+ l' = transform tr l+ trans = translate (l' .-. l)++{- Proof that the above satisfies the monoid action laws.++ 1. transform mempty (ScaleInv t v l)+ = ScaleInv (trans . rot $ t) (rot v) l'+ { l' = transform mempty l = l }+ { trans = translate (l' .-. l)+ = translate (l .-. l)+ = translate zeroV+ = id+ }+ { rot = rotateAbout l angle+ = rotateAbout l (direction (transform mempty v) - direction v)+ = rotateAbout l (direction v - direction v)+ = rotateAbout l 0+ = id+ }+ = ScaleInv t v l++ 2. transform t1 (transform t2 (ScaleInv t v l))+ = let angle = direction (transform t2 v) - direction v+ rot = rotateAbout l angle+ l' = transform t2 l+ trans = translate (l' .-. l)+ in+ transform t1 (ScaleInv (trans . rot $ t) (rot v) l')++ = let angle = direction (transform t2 v) - direction v+ rot = rotateAbout l angle+ l' = transform t2 l+ trans = translate (l' .-. l)+ angle2 = direction (transform t1 (rot v)) - direction (rot v)+ rot2 = rotateAbout l' angle2+ l'2 = transform t1 l'+ trans2 = translate (l'2 .-. l')+ in+ ScaleInv (trans2 . rot2 . trans . rot $ t) (rot2 . rot $ v) l'2++ { l'2 = transform t1 l'+ = transform t1 (transform t2 l)+ = transform (t1 <> t2) l+ }+ { trans2 = translate (l'2 .-. l')+ = translate (transform (t1 <> t2) l .-. transform t2 l)+ = translate (transform t1 l .-. l)+ }+ { rot v = rotateAbout l angle v+ = rotate angle `under` translation (origin .-. l) $ v+ = rotate angle v+ }+ { angle2 = direction (transform t1 (rot v)) - direction (rot v)+ = direction (transform t1 (rotate angle v)) - direction (rotate angle v)+ = direction (transform t1 (rotate angle v)) - direction v - angle+ }+ { rot2 = rotateAbout l' angle2+ = ???+ }++-}++-- This is how we handle freezing properly with ScaleInv wrappers.+-- Normal transformations are applied ignoring scaling; "frozen"+-- transformations (i.e. transformations applied after a freeze) are+-- applied directly to the underlying object, scales and all. We must+-- take care to transform the reference point and direction vector+-- appropriately.+instance (V t ~ R2, Transformable t) => IsPrim (ScaleInv t) where+ transformWithFreeze t1 t2 s = ScaleInv t'' d'' origin''+ where+ -- first, apply t2 normally, i.e. ignoring scaling+ s'@(ScaleInv t' _ _) = transform t2 s++ -- now apply t1 to get the new direction and origin+ (ScaleInv _ d'' origin'') = transform t1 s'++ -- but apply t1 directly to the underlying thing, scales and all.+ t'' = transform t1 t'++instance (Renderable t b, V t ~ R2) => Renderable (ScaleInv t) b where+ render b = render b . view scaleInvObj++-- | Create a diagram from a single scale-invariant primitive. The+-- vector argument specifies the direction in which the primitive is+-- \"pointing\" (for the purpose of keeping it rotated correctly+-- under non-uniform scaling). The primitive is assumed to be+-- \"located\" at the origin (for the purpose of translating it+-- correctly under scaling).+--+-- Note that the resulting diagram will have an /empty/ envelope,+-- trace, and query. The reason is that the envelope, trace, and+-- query cannot be cached---applying a transformation would cause+-- the cached envelope, etc. to get \"out of sync\" with the+-- scale-invariant object. The intention, at any rate, is that+-- scale-invariant things will be used only as \"decorations\" (/e.g./+-- arrowheads) which should not affect the envelope, trace, and+-- query.+scaleInvPrim :: (Transformable t, Renderable t b, V t ~ R2, Monoid m)+ => t -> R2 -> QDiagram b R2 m+scaleInvPrim t d = mkQD (Prim $ scaleInv t d) mempty mempty mempty mempty
src/Diagrams/TwoD/Types.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -----------------------------------------------------------------------------@@ -21,39 +21,44 @@ module Diagrams.TwoD.Types ( -- * 2D Euclidean space- R2, r2, unr2- , P2, p2, unp2+ R2(..), r2, unr2, mkR2, r2Iso+ , P2, p2, mkP2, unp2, p2Iso , T2 -- * Angles , Angle(..)- , Turn(..), CircleFrac, Rad(..), Deg(..)- , fullCircle, convertAngle++ , Turn(..), asTurn, CircleFrac+ , Rad(..), asRad+ , Deg(..), asDeg+ , fullTurn, fullCircle, convertAngle, angleRatio ) where +import Control.Lens (Iso', Wrapped, iso, makeWrapped, op,+ wrapped, _1, _2)+ import Diagrams.Coordinates import Diagrams.Core import Diagrams.Util (tau) -import Control.Newtype-+import Data.AffineSpace.Point import Data.Basis+import Data.MemoTrie (HasTrie (..)) import Data.NumInstances.Tuple () import Data.VectorSpace import Data.Typeable- ------------------------------------------------------------ -- 2D Euclidean space -- | The two-dimensional Euclidean vector space R^2. This type is -- intentionally abstract. ----- * To construct a vector, use 'r2', or '&' (from "Diagrams.Coordinates"):+-- * To construct a vector, use 'r2', or '^&' (from "Diagrams.Coordinates"): -- -- @ -- r2 (3,4) :: R2--- 3 & 4 :: R2+-- 3 ^& 4 :: R2 -- @ -- -- Note that "Diagrams.Coordinates" is not re-exported by@@ -74,71 +79,120 @@ -- foo (coords -> x :& y) = ... -- @ -newtype R2 = R2 { unR2 :: (Double, Double) }- deriving (AdditiveGroup, Eq, Ord, Typeable, Num, Fractional)+data R2 = R2 {-# UNPACK #-} !Double+ {-# UNPACK #-} !Double+ deriving (Eq, Ord, Typeable) +instance AdditiveGroup R2 where+ zeroV = R2 0 0+ R2 x1 y1 ^+^ R2 x2 y2 = R2 (x1 + x2) (y1 + y2)+ negateV (R2 x y) = R2 (-x) (-y)++instance Num R2 where+ (+) = (^+^)+ R2 x1 y1 * R2 x2 y2 = R2 (x1 * x2) (y1 * y2) -- this is sort of bogus+ (-) = (^-^)+ negate = negateV+ abs (R2 x y) = R2 (abs x) (abs y)+ signum (R2 x y) = R2 (signum x) (signum y)+ fromInteger i = R2 i' i'+ where i' = fromInteger i++instance Fractional R2 where+ R2 x1 y1 / R2 x2 y2 = R2 (x1/x2) (y1/y2)+ recip (R2 x y) = R2 (recip x) (recip y)+ fromRational r = R2 r' r'+ where r' = fromRational r+ instance Show R2 where- showsPrec p (R2 (x,y)) = showParen (p >= 7) $- showCoord x . showString " & " . showCoord y+ showsPrec p (R2 x y) = showParen (p >= 7) $+ showCoord x . showString " ^& " . showCoord y where- showCoord x | x < 0 = showParen True (shows x)- | otherwise = shows x+ showCoord c | c < 0 = showParen True (shows c)+ | otherwise = shows c instance Read R2 where readsPrec d r = readParen (d > app_prec)- (\r -> [ (R2 (x,y), r''')- | (x,r') <- readsPrec (amp_prec + 1) r- , ("&",r'') <- lex r'- , (y,r''') <- readsPrec (amp_prec + 1) r''- ])+ (\rr -> [ (R2 x y, r''')+ | (x,r') <- readsPrec (amp_prec + 1) rr+ , ("^&",r'') <- lex r'+ , (y,r''') <- readsPrec (amp_prec + 1) r''+ ]) r where app_prec = 10 amp_prec = 7 -instance Newtype R2 (Double, Double) where- pack = R2- unpack = unR2- -- | Construct a 2D vector from a pair of components. See also '&'. r2 :: (Double, Double) -> R2-r2 = pack+r2 (x,y) = R2 x y -- | Convert a 2D vector back into a pair of components. See also 'coords'. unr2 :: R2 -> (Double, Double)-unr2 = unpack+unr2 (R2 x y) = (x,y) +-- | Curried form of `r2`.+mkR2 :: Double -> Double -> R2+mkR2 = curry r2++-- | Lens wrapped isomorphisms for R2.+instance Wrapped (Double, Double) (Double, Double) R2 R2 where+ wrapped = iso r2 unr2+ {-# INLINE wrapped #-}+ type instance V R2 = R2 instance VectorSpace R2 where type Scalar R2 = Double- (*^) = over R2 . (*^)+ s *^ R2 x y = R2 (s*x) (s*y) +data R2Basis = XB | YB deriving (Eq, Ord, Enum)++instance HasTrie R2Basis where+ data R2Basis :->: x = R2Trie x x+ trie f = R2Trie (f XB) (f YB)+ untrie (R2Trie x _y) XB = x+ untrie (R2Trie _x y) YB = y+ enumerate (R2Trie x y) = [(XB,x),(YB,y)]+ instance HasBasis R2 where- type Basis R2 = Either () () -- = Basis (Double, Double)- basisValue = R2 . basisValue- decompose = decompose . unR2- decompose' = decompose' . unR2+ type Basis R2 = R2Basis+ basisValue XB = R2 1 0+ basisValue YB = R2 0 1 + decompose (R2 x y) = [(XB, x), (YB, y)]++ decompose' (R2 x _) (XB) = x+ decompose' (R2 _ y) (YB) = y+ instance InnerSpace R2 where- (unR2 -> vec1) <.> (unR2 -> vec2) = vec1 <.> vec2+ (R2 x1 y1) <.> (R2 x2 y2) = x1*x2 + y1*y2 instance Coordinates R2 where type FinalCoord R2 = Double type PrevDim R2 = Double type Decomposition R2 = Double :& Double - x & y = r2 (x,y)- coords (unR2 -> (x,y)) = x :& y+ x ^& y = R2 x y+ coords (R2 x y) = x :& y +r2Iso :: Iso' R2 (Double, Double)+r2Iso = iso unr2 r2++instance HasX R2 where+ _x = r2Iso . _1++instance HasY R2 where+ _y = r2Iso . _2+ -- | Points in R^2. This type is intentionally abstract. ----- * To construct a point, use 'p2', or '&' (see+-- * To construct a point, use 'p2', or '^&' (see -- "Diagrams.Coordinates"): -- -- @ -- p2 (3,4) :: P2--- 3 & 4 :: P2+-- 3 ^& 4 :: P2 -- @ -- -- * To construct a point from a vector @v@, use @'origin' 'Data.AffineSpace..+^' v@.@@ -156,39 +210,93 @@ -- @ type P2 = Point R2 --- | Construct a 2D point from a pair of coordinates. See also '&'.+-- | Construct a 2D point from a pair of coordinates. See also '^&'. p2 :: (Double, Double) -> P2-p2 = pack . pack+p2 = P . r2 -- | Convert a 2D point back into a pair of coordinates. See also 'coords'. unp2 :: P2 -> (Double, Double)-unp2 = unpack . unpack+unp2 (P v) = unr2 v +-- | Curried form of `p2`.+mkP2 :: Double -> Double -> P2+mkP2 = curry p2+ -- | Transformations in R^2. type T2 = Transformation R2 instance Transformable R2 where transform = apply +p2Iso :: Iso' P2 (Double, Double)+p2Iso = iso unp2 p2++instance HasX P2 where+ _x = p2Iso . _1++instance HasY P2 where+ _y = p2Iso . _2 ------------------------------------------------------------ -- Angles -- | Newtype wrapper used to represent angles as fractions of a -- circle. For example, 1\/3 turn = tau\/3 radians = 120 degrees.-newtype Turn = Turn { getTurn :: Double }- deriving (Read, Show, Eq, Ord, Enum, Floating, Fractional, Num, Real, RealFloat, RealFrac)+newtype Turn = Turn Double+ deriving (Read, Show, Eq, Ord, Enum, Fractional, Num, Real, RealFrac, AdditiveGroup) +makeWrapped ''Turn++instance VectorSpace Turn where+ type Scalar Turn = Double+ s *^ Turn t = Turn (s*t)++-- | The identity function with a restricted type, for conveniently+-- declaring that some value should have type 'Turn'. For example,+-- @rotation . asTurn . fromRational@ constructs a rotation from a+-- rational value considered as a @Turn@. Without @asTurn@, the angle+-- type would be ambiguous.+asTurn :: Turn -> Turn+asTurn = id+ -- | Deprecated synonym for 'Turn', retained for backwards compatibility. type CircleFrac = Turn -- | Newtype wrapper for representing angles in radians.-newtype Rad = Rad { getRad :: Double }- deriving (Read, Show, Eq, Ord, Enum, Floating, Fractional, Num, Real, RealFloat, RealFrac)+newtype Rad = Rad Double+ deriving (Read, Show, Eq, Ord, Enum, Floating, Fractional, Num, Real, RealFloat, RealFrac, AdditiveGroup) +makeWrapped ''Rad++instance VectorSpace Rad where+ type Scalar Rad = Double+ s *^ Rad r = Rad (s*r)++-- | The identity function with a restricted type, for conveniently+-- declaring that some value should have type 'Rad'. For example,+-- @rotation . asRad . fromRational@ constructs a rotation from a+-- rational value considered as a value in radians. Without @asRad@,+-- the angle type would be ambiguous.+asRad :: Rad -> Rad+asRad = id+ -- | Newtype wrapper for representing angles in degrees.-newtype Deg = Deg { getDeg :: Double }- deriving (Read, Show, Eq, Ord, Enum, Floating, Fractional, Num, Real, RealFloat, RealFrac)+newtype Deg = Deg Double+ deriving (Read, Show, Eq, Ord, Enum, Fractional, Num, Real, RealFrac, AdditiveGroup) +makeWrapped ''Deg++instance VectorSpace Deg where+ type Scalar Deg = Double+ s *^ Deg d = Deg (s*d)++-- | The identity function with a restricted type, for conveniently+-- declaring that some value should have type 'Deg'. For example,+-- @rotation . asDeg . fromIntegral@ constructs a rotation from an+-- integral value considered as a value in degrees. Without @asDeg@,+-- the angle type would be ambiguous.+asDeg :: Deg -> Deg+asDeg = id+ -- | Type class for types that measure angles. class Num a => Angle a where -- | Convert to a turn, /i.e./ a fraction of a circle.@@ -203,13 +311,13 @@ -- | tau radians = 1 full turn. instance Angle Rad where- toTurn = Turn . (/tau) . getRad- fromTurn = Rad . (*tau) . getTurn+ toTurn = Turn . (/tau) . op Rad+ fromTurn = Rad . (*tau) . op Turn -- | 360 degrees = 1 full turn. instance Angle Deg where- toTurn = Turn . (/360) . getDeg- fromTurn = Deg . (*360) . getTurn+ toTurn = Turn . (/360) . op Deg+ fromTurn = Deg . (*360) . op Turn -- | An angle representing one full turn. fullTurn :: Angle a => a@@ -222,3 +330,7 @@ -- | Convert between two angle representations. convertAngle :: (Angle a, Angle b) => a -> b convertAngle = fromTurn . toTurn++-- | Calculate ratio between two angles+angleRatio :: Angle a => a -> a -> Double+angleRatio a b = op Turn (toTurn a) / op Turn (toTurn b)
src/Diagrams/TwoD/Vector.hs view
@@ -16,32 +16,31 @@ unitX, unitY, unit_X, unit_Y -- * Converting between vectors and angles- , direction, fromDirection, e+ , direction, angleBetween, fromDirection, e -- * 2D vector utilities , perp, leftTurn ) where import Data.VectorSpace ((<.>))-import Diagrams.Coordinates import Diagrams.TwoD.Types-import Diagrams.Util (( # ))+import Diagrams.Coordinates -- | The unit vector in the positive X direction. unitX :: R2-unitX = 1 & 0+unitX = 1 ^& 0 -- | The unit vector in the positive Y direction. unitY :: R2-unitY = 0 & 1+unitY = 0 ^& 1 -- | The unit vector in the negative X direction. unit_X :: R2-unit_X = (-1) & 0+unit_X = (-1) ^& 0 -- | The unit vector in the negative Y direction. unit_Y :: R2-unit_Y = 0 & (-1)+unit_Y = 0 ^& (-1) -- | Compute the direction of a vector, measured counterclockwise from -- the positive x-axis as a fraction of a full turn. The zero@@ -49,9 +48,18 @@ direction :: Angle a => R2 -> a direction (coords -> x :& y) = convertAngle . Rad $ atan2 y x +-- | Compute the counterclockwise angle from the first vector to the second.+angleBetween :: (Angle a, Num a, Ord a) => R2 -> R2 -> a+angleBetween v1 v2+ | d2 > d1 = d2 - d1+ | otherwise = fullTurn + d2 - d1+ where+ d1 = direction v1+ d2 = direction v2+ -- | Convert an angle into a unit vector pointing in that direction. fromDirection :: Angle a => a -> R2-fromDirection a = cos a' & sin a'+fromDirection a = cos a' ^& sin a' where Rad a' = convertAngle a -- | A convenient synonym for 'fromDirection'.@@ -61,7 +69,7 @@ -- | @perp v@ is perpendicular to and has the same magnitude as @v@. -- In particular @perp v == rotateBy (1/4) v@. perp :: R2 -> R2-perp (coords -> x :& y) = (-y) & x+perp (coords -> x :& y) = (-y) ^& x -- | @leftTurn v1 v2@ tests whether the direction of @v2@ is a left -- turn from @v1@ (that is, if the direction of @v2@ can be obtained
src/Diagrams/Util.hs view
@@ -21,7 +21,6 @@ , tau -- * Internal utilities- , Proxy(..) , foldB ) where@@ -86,10 +85,6 @@ -- digits or so), try <http://youtu.be/3174T-3-59Q>. tau :: Floating a => a tau = 2*pi---- | A value of @Proxy a@ carries no information; it's used only to--- fix the type @a@.-data Proxy a = Proxy -- | Given an associative binary operation and a default value to use -- in the case of an empty list, perform a /balanced/ fold over a