diagrams-core 0.5.0.1 → 1.5.1.2
raw patch · 44 files changed
Files
- CHANGELOG.md +770/−0
- CHANGES +0/−78
- LICENSE +15/−3
- README +0/−9
- README.markdown +6/−0
- diagrams-core.cabal +53/−30
- diagrams/src_Diagrams_Core_Trace_maxRayTracePEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_maxRayTraceVEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_maxTracePEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_maxTraceVEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_rayTracePEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_rayTraceVEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_traceEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_tracePEx.svg +1/−0
- diagrams/src_Diagrams_Core_Trace_traceVEx.svg +1/−0
- src/Diagrams/Core.hs +270/−0
- src/Diagrams/Core/Compile.hs +201/−0
- src/Diagrams/Core/Envelope.hs +365/−0
- src/Diagrams/Core/HasOrigin.hs +107/−0
- src/Diagrams/Core/Juxtapose.hs +80/−0
- src/Diagrams/Core/Measure.hs +141/−0
- src/Diagrams/Core/Names.hs +210/−0
- src/Diagrams/Core/Points.hs +56/−0
- src/Diagrams/Core/Query.hs +99/−0
- src/Diagrams/Core/Style.hs +375/−0
- src/Diagrams/Core/Trace.hs +432/−0
- src/Diagrams/Core/Transform.hs +427/−0
- src/Diagrams/Core/Types.hs +1010/−0
- src/Diagrams/Core/V.hs +87/−0
- src/Graphics/Rendering/Diagrams.hs +0/−153
- src/Graphics/Rendering/Diagrams/Core.hs +0/−632
- src/Graphics/Rendering/Diagrams/Envelope.hs +0/−254
- src/Graphics/Rendering/Diagrams/HasOrigin.hs +0/−94
- src/Graphics/Rendering/Diagrams/Juxtapose.hs +0/−63
- src/Graphics/Rendering/Diagrams/MList.hs +0/−180
- src/Graphics/Rendering/Diagrams/Monoids.hs +0/−467
- src/Graphics/Rendering/Diagrams/Names.hs +0/−231
- src/Graphics/Rendering/Diagrams/Points.hs +0/−28
- src/Graphics/Rendering/Diagrams/Query.hs +0/−50
- src/Graphics/Rendering/Diagrams/Style.hs +0/−239
- src/Graphics/Rendering/Diagrams/Transform.hs +0/−278
- src/Graphics/Rendering/Diagrams/UDTree.hs +0/−161
- src/Graphics/Rendering/Diagrams/Util.hs +0/−27
- src/Graphics/Rendering/Diagrams/V.hs +0/−42
+ CHANGELOG.md view
@@ -0,0 +1,770 @@+## [v1.5.1.2](https://github.com/diagrams/diagrams-core/tree/v1.5.1.2) (2026-04-18)++- Allow `base-4.22`, `containers-0.8`, and test on GHC 9.14+- Fix some pattern match warnings+- Remove `semigroups` dependency++## [v1.5.1.1-r4](https://github.com/diagrams/diagrams-core/tree/v1.5.1.1-r4) (2025-05-16)++- Allow `monoid-extras-0.7`++## [v1.5.1.1-r3](https://github.com/diagrams/diagrams-core/tree/v1.5.1.1-r3) (2025-01-30)++- Allow `base-4.21` (GHC 9.12)++## [v1.5.1.1-r2](https://github.com/diagrams/diagrams-core/tree/v1.5.1.1-r2) (2024-05-20)++- Allow:+ - `base-4.20` (GHC 9.10)+ - `lens-5.3`+ - `containers-0.7`+- Test on GHC 9.10++## [v1.5.1.1-r1](https://github.com/diagrams/diagrams-core/tree/v1.5.1.1-r1) (2024-04-20)++* Allow `linear-1.23`++## [v1.5.1.1](https://github.com/diagrams/diagrams-core/tree/v1.5.1.1) (2023-11-15)++* Allow `base-4.19` and test on GHC 9.8+* Fix more warnings++## [v1.5.1](https://github.com/diagrams/diagrams-core/tree/v1.5.1) (2023-05-11)++* Allow `base-4.18` and test on GHC 9.6 (thanks to @sergv)+* Fix some warnings (thanks to @sergv)+* Fix some documentation typos (thanks to @mchav)++## [v1.5.0.1-r1](https://github.com/diagrams/diagrams-core/tree/v1.5.0.1-r1) (2022-11-30)++* Allow `linear-1.22`++## [v1.5.0.1](https://github.com/diagrams/diagrams-core/tree/v1.5.0.1) (2022-08-27)++* Test with up to `base-4.17` and GHC 9.4+* Allow `lens-5.2`+* Fix documentation for `atLeast` and `atMost` (thanks to Igor Moreno)++## [v1.5.0](https://github.com/diagrams/diagrams-core/tree/v1.5.0) (2021-05-13)++* Updates for GHC 8.10 and 9.0+* Drop support for GHC < 8.4+* Remove deprecated `Option` type in favor of `Maybe`. This is a+ breaking API change.++## [v1.4.2-r1](https://github.com/diagrams/diagrams-core/tree/v1.4.2-r1) (2020-02-10)++* Allow `lens-4.19` and `linear-1.21`++## [v1.4.2](https://github.com/diagrams/diagrams-core/tree/v1.4.2) (2019-10-19)++* New `KeyVal` constructor for `Annotation` ([PR](https://github.com/diagrams/diagrams-core/pull/104))+* Updates for GHC 8.8+* Drop support for GHC 7.6 and 7.8++## [v1.4.1.1](https://github.com/diagrams/diagrams-core/tree/v1.4.1.1) (2018-06-17)++* Add some `ConstraintKinds` pragmas to allow compilation on GHC 7.8 and 7.6++## [v1.4.1](https://github.com/diagrams/diagrams-core/tree/v1.4.1) (2018-04-10)++* Allow `base-4.11`+* Allow `lens-4.16`+* Add `Semigroup` instance to build on GHC 8.4++## v1.4.0.1++* Allow base-4.10++## [v1.4](https://github.com/diagrams/diagrams-core/tree/v1.4) (2016-10-26)++* **New features**++ - New `eachName` traversal, for traversing over parts of a `Name`+ that match a given type++ - More documentation explaining `HasOrigin` and `Transformable`+ instances for `Envelope`++* **Dependency/version changes**++ - Allow `lens-4.15`+ - Many other upper bounds bumped; see minor release changelogs below.++* **New instances**++ - `Transformable` instance for `Measured`++ - A bunch more instances for `Query` (`Distributive`,+ `Representable`, `Profunctor`, `Coseive`, `Closed`, `Costrong`,+ `Corepresentable`)++* **API changes**++ - Move some `Query`-related functions to `diagrams-lib` (`sample`,+ `value`, `resetValue`, `clearValue`)++ - Remove some redundant constraints in type signatures (should not+ actually affect API)++## [v1.3.0.8](https://github.com/diagrams/diagrams-core/tree/v1.3.0.8) (2016-06-05)++- allow `base-4.9`+- build warning-free on GHC 8.0.1++## [v1.3.0.7](https://github.com/diagrams/diagrams-core/tree/v1.3.0.7) (2016-05-01)++- allow `lens-4.14`++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3.0.6...v1.3.0.7)++## [v1.3.0.6](https://github.com/diagrams/diagrams-core/tree/v1.3.0.6) (2016-02-19)++ - allow `unordered-containers-0.2.*`++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3.0.5...v1.3.0.6)++## [v1.3.0.5](https://github.com/diagrams/diagrams-core/tree/v1.3.0.5) (2016-01-14)++ - allow `unordered-containers-0.2.6`++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3.0.4...v1.3.0.5)++## [v1.3.0.4](https://github.com/diagrams/diagrams-core/tree/v1.3.0.4) (2015-11-10)++ - allow `semigroups-0.18`++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3.0.3...v1.3.0.4)++## [v1.3.0.3](https://github.com/diagrams/diagrams-core/tree/v1.3.0.3) (2015-09-17)++ - allow `lens-4.13`+ - allow `linear-1.20`+ - allow `semigroups-0.17`++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3.0.2...v1.3.0.3)++## [v1.3.0.2](https://github.com/diagrams/diagrams-core/tree/v1.3.0.2) (2015-07-19)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3.0.1...v1.3.0.2)++## [v1.3.0.1](https://github.com/diagrams/diagrams-core/tree/v1.3.0.1) (2015-05-26)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.3...v1.3.0.1)++## [v1.3](https://github.com/diagrams/diagrams-core/tree/v1.3) (2015-04-19)++* **New features**++ - Update for ghc-7.10.++ - Switch from `vector-space` to `linear` for linear algebra.++ - `OpacityGroup` annotation for setting the opacity of diagrams as+ a group. Opacity groups can be applied with the `opacityGroup` or+ `groupOpacity` functions.++ - Added `atAttr`, `atMAttr` and `atTAttr` lenses onto the attributes+ of styles.++ - `InSpace` and `SameSpace` synonyms.++ - `size` function for computing the range of an enveloped object in+ the basis vectors.++ - "Grouping" for transparent things [\#21](https://github.com/diagrams/diagrams-core/issues/21)++* **Dependency/version changes**++ - Allow `base-4.8`+ - Allow `lens-4.9`++* **New instances**++ - `Show` instances for `Attribute` and `Style`.+ - `Each`, `Ixed` and `At` instances for and `Style`.++* **API changes**++ - `Measure` has a new internal representation. `Local`, `Global`,+ `Normalized`, and `Output` have been renamed to `local`, `global`,+ `normalized` and `output` respectivly. `Measure` is now defined in+ `Diagrams.Core.Measure`.++ - `GTAttribute` has been removed. `MAttribute` now holds measured+ attributes and no longer requires a `Data` instance.++ - `V` is now a `* -> *` kind type family.++ - New type family `N` for the number type of an object, `Scalar`+ type family no longer exists.++ - `(|>)` has moved to `(.>>)` to make room for lens's snoc operator.++ - `Style`'s internal representation now uses a hashmap of the+ `TypeRep`.++**Merged pull requests:**++- Pre 1.3 [\#82](https://github.com/diagrams/diagrams-core/pull/82) ([cchalmers](https://github.com/cchalmers))++- update for GHC-7.10, -Wall [\#81](https://github.com/diagrams/diagrams-core/pull/81) ([bergey](https://github.com/bergey))++- Style lenses [\#80](https://github.com/diagrams/diagrams-core/pull/80) ([cchalmers](https://github.com/cchalmers))++- Add isReflection [\#79](https://github.com/diagrams/diagrams-core/pull/79) ([byorgey](https://github.com/byorgey))++- Linear update [\#77](https://github.com/diagrams/diagrams-core/pull/77) ([cchalmers](https://github.com/cchalmers))++- Bump lens upper version bounds [\#74](https://github.com/diagrams/diagrams-core/pull/74) ([RyanGlScott](https://github.com/RyanGlScott))++- Add Diagram B synonym for Diagram b v n [\#73](https://github.com/diagrams/diagrams-core/pull/73) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++- New stuff [\#72](https://github.com/diagrams/diagrams-core/pull/72) ([cchalmers](https://github.com/cchalmers))++- Linear [\#71](https://github.com/diagrams/diagrams-core/pull/71) ([cchalmers](https://github.com/cchalmers))++- Bump linear upper version bounds [\#75](https://github.com/diagrams/diagrams-core/pull/75) ([RyanGlScott](https://github.com/RyanGlScott))++- Change Measure back to not using Scalar v [\#65](https://github.com/diagrams/diagrams-core/pull/65) ([Mathnerd314](https://github.com/Mathnerd314))++- Remove gratuitous Data constraints [\#69](https://github.com/diagrams/diagrams-core/pull/69) ([Mathnerd314](https://github.com/Mathnerd314))++## [v1.2.0.6](https://github.com/diagrams/diagrams-core/tree/v1.2.0.6) (2015-04-03)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.2.0.5...v1.2.0.6)++**Closed issues:**++- Please add support for recent versions of vector-space [\#78](https://github.com/diagrams/diagrams-core/issues/78)++## [v1.2.0.5](https://github.com/diagrams/diagrams-core/tree/v1.2.0.5) (2015-01-13)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.2.0.4...v1.2.0.5)++## [v1.2.0.4](https://github.com/diagrams/diagrams-core/tree/v1.2.0.4) (2014-12-04)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.2.0.3...v1.2.0.4)++## [v1.2.0.3](https://github.com/diagrams/diagrams-core/tree/v1.2.0.3) (2014-11-17)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.2.0.2...v1.2.0.3)++## [v1.2.0.2](https://github.com/diagrams/diagrams-core/tree/v1.2.0.2) (2014-08-22)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.2.0.1...v1.2.0.2)++**Closed issues:**++- Warn against GND for IsName [\#67](https://github.com/diagrams/diagrams-core/issues/67)++## [v1.2.0.1](https://github.com/diagrams/diagrams-core/tree/v1.2.0.1) (2014-06-04)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.2...v1.2.0.1)++**Merged pull requests:**++- Propogate transformations into the terms of Measure [\#66](https://github.com/diagrams/diagrams-core/pull/66) ([bergey](https://github.com/bergey))++## [v1.2](https://github.com/diagrams/diagrams-core/tree/v1.2) (2014-06-02)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.1...v1.2)++* **New features**++ - New function `matrixHomRep` to convert a transformation to a+ homogeneous matrix representation.++ - New function `dropTransl` to drop the translation component+ from a transformation.++ - A mini-DSL for Measures.++ - New `extent` function, used in `diameter`.++ - New `dimension` function to return the dimension of a vector space.++ - New `_relative` iso between points and vectors.++ - `avgScale` function (for computing the average scaling factor of+ a transformation) has been moved from `diagrams-lib` to+ `diagrams-core` and generalized to work over any vector space.++* **Dependency/version changes**++ - Allow `semigroups-0.15`+ - Allow `lens-4.2`++* **API changes**++ - Major refactoring which removes `freeze` (and hence `Split` transforms,+ etc.) and adds units of `Measure`.++ - Refactoring and simplification of the `Backend` class.++ - Remove `Multibackend`.++ - Remove `nullPrim`, `IsPrim` and simplify `RPrim` so that it does not+ carry a transformation.++ - Update `adjustDia` to return a transformation, not just a scale factor.+ Add `renderDiaT` which returns a transformation (for use by end+ users, e.g. to convert output coordinates back into local coordinates).+ +**Implemented enhancements:**++- Extracting things from Prim wrappers [\#42](https://github.com/diagrams/diagrams-core/issues/42)++**Closed issues:**++- Incomplete comment on Backend class [\#64](https://github.com/diagrams/diagrams-core/issues/64)++- Please add support for Lens 4.x [\#56](https://github.com/diagrams/diagrams-core/issues/56)++**Merged pull requests:**++- A mini-DSL for Measures. [\#61](https://github.com/diagrams/diagrams-core/pull/61) ([byorgey](https://github.com/byorgey))++- Clean-slate redesign/simplification of `Backend` class [\#60](https://github.com/diagrams/diagrams-core/pull/60) ([byorgey](https://github.com/byorgey))++- Rework units [\#59](https://github.com/diagrams/diagrams-core/pull/59) ([byorgey](https://github.com/byorgey))++- Avg scale [\#58](https://github.com/diagrams/diagrams-core/pull/58) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++- Preliminary implementation of Measure [\#55](https://github.com/diagrams/diagrams-core/pull/55) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++- No mco [\#62](https://github.com/diagrams/diagrams-core/pull/62) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++## [v1.1](https://github.com/diagrams/diagrams-core/tree/v1.1) (2014-03-09)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.0.0.1...v1.1)++* **New features**++ - New `basis` function+ - New `determinant` function for computing the determinant of a+ `Transformation`+ - Add `Typeable` constraint on `Prim`s, making it possible to+ extract things back out of a `Prim` wrapper using `cast`+ - Raw `Trace`s now return a *sorted list* of intersections,+ instead of only the smallest. This is used to implement a new+ family of functions `rayTraceV`, `rayTraceP`, `maxRayTraceV`,+ `maxRayTraceP`, which work similarly to the parallel versions+ without `Ray`, but return the first intersection in the+ *positive* direction from the given point, rather than the+ smallest in absolute terms.+ - New `Annotation` type and corresponding `applyAnnotation`+ function, for attaching uninterpreted annotations at specific+ points in a diagram tree. Currently this is used for+ hyperlinks; more annotation types will be added in the future.++* **Dependency/version changes**++ - Require `lens-4.0`+ - Allow `vector-space-points-0.2`++* **Bug fixes**++ - Looking up a subdiagram by name now results in a diagram which+ still has that name (#43)+ +**Closed issues:**++- Named subdiagrams lose their names after being looked up [\#43](https://github.com/diagrams/diagrams-core/issues/43)++**Merged pull requests:**++- Hyperlinks [\#57](https://github.com/diagrams/diagrams-core/pull/57) ([tdox](https://github.com/tdox))++- Added `basis`, simplified `onBasis` [\#54](https://github.com/diagrams/diagrams-core/pull/54) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++- Determinants [\#53](https://github.com/diagrams/diagrams-core/pull/53) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++- Introduce Typeable constraint on Prims \(see \#42\) [\#52](https://github.com/diagrams/diagrams-core/pull/52) ([byorgey](https://github.com/byorgey))++- Update Wrapped instances for lens-4.0 [\#51](https://github.com/diagrams/diagrams-core/pull/51) ([bergey](https://github.com/bergey))++- return list of traces [\#48](https://github.com/diagrams/diagrams-core/pull/48) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++- Projections rebase [\#50](https://github.com/diagrams/diagrams-core/pull/50) ([bergey](https://github.com/bergey))++## [v1.0.0.1](https://github.com/diagrams/diagrams-core/tree/v1.0.0.1) (2013-11-28)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v1.0...v1.0.0.1)++## [v1.0](https://github.com/diagrams/diagrams-core/tree/v1.0) (2013-11-25)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v0.7.0.1...v1.0)++* **New features**++ * Delayed subtrees: instead of a primitive, one can now also have+ a delayed subtree at a leaf, containing a continuation which+ generates a `QDiagram` when given the accumulated d-annotation+ at that point in the tree. Useful for things which need to know+ the final transformation applied to them before deciding what+ diagram to generate. The prototypical use case is arrows: see+ https://github.com/diagrams/diagrams-lib/issues/112 . However,+ this may be useful for other things as well: for example,+ diagrams which scale normally until hitting some maximum or+ minimum size, at which point they refuse to scale any further+ (or more generally diagrams which scale as some non-linear+ function of the transformation applied to them).++ The only downside is that the u-annotation must be fixed ahead+ of time---doing otherwise requires a more general solution for+ constraint solving.++ * New function `lookupName` for doing a simple lookup of a named+ subdiagram++ * New module `Diagrams.Core.Compile`, containing a framework for+ compiling `QDiagrams` into a simpler tree type `RTree`, which+ may be used by backends for rendering.++* **New instances**++ * `Qualifiable` instances for `(,)`, `(,,)`, `[]`, `Set`, `Map k`,+ and `(->) e`.++ * `(->) e` instance for `Juxtaposable` (thanks to Carlos Scheidegger)++* **API changes**++ * Export `pointDiagram` function, which creates an otherwise empty+ diagram with a point (not empty) envelope++ * A bunch of stuff now uses machinery from the `lens` library.+ * `envelope`, `trace`, and `subMap` are now `Lens'`es+ * `Wrapped` instances for `Trace`, `TransInv`, `QDiagram`,+ `SubMap`, `Envelope`, `Style`, `Query`, and `Name` (replaces+ `Newtype` instances)+ * `Iso`s for `Query`, `Envelope`, `QDiagram`, `SubMap`, `TransInv`+ +**Implemented enhancements:**++- Tree structure in Backends [\#19](https://github.com/diagrams/diagrams-core/issues/19)++**Merged pull requests:**++- Delayed subtrees [\#47](https://github.com/diagrams/diagrams-core/pull/47) ([byorgey](https://github.com/byorgey))++- Trees for backends [\#46](https://github.com/diagrams/diagrams-core/pull/46) ([byorgey](https://github.com/byorgey))++- add b-\>a instance for Juxtaposable [\#45](https://github.com/diagrams/diagrams-core/pull/45) ([cscheid](https://github.com/cscheid))++- Lens [\#44](https://github.com/diagrams/diagrams-core/pull/44) ([jeffreyrosenbluth](https://github.com/jeffreyrosenbluth))++## [v0.7.0.1](https://github.com/diagrams/diagrams-core/tree/v0.7.0.1) (2013-09-27)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v0.7...v0.7.0.1)++**Merged pull requests:**++- Add lookupName function. [\#41](https://github.com/diagrams/diagrams-core/pull/41) ([cmears](https://github.com/cmears))++## [v0.7](https://github.com/diagrams/diagrams-core/tree/v0.7) (2013-08-09)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v0.6.0.2...v0.7)++* **New features**++ - new function `onBasis`, to extract the matrix equivalent of a `Transformation`+ - `SubMap`s are now `Deletable`+ - new function `localize` for hiding/deleting names from scope+ - new `IsPrim` class, containing `transformWithFreeze` function.+ This is primarily intended to support scale-invariant primitives+ (*e.g.* arrowheads) but may be useful for other stuff as well.+ The default implementation of `renderDia` now uses+ `transformWithFreeze`.+ - optimized `Transformable` instance for `TransInv`++* **New instances**++ - `Eq`, `Ord`, `Enveloped`, `Traced`, and `Qualifiable` instances+ for `TransInv`++ - `Transformable` instance for functions, which acts by conjugation++* **API changes**++ - `named` and `namePoint` have moved to the `diagrams-lib` package.++* **Dependency/version changes**++ - allow `base-4.7`+ - upgrade to `monoid-extras-0.3`+ +**Implemented enhancements:**++- Function to extract matrix coefficients from a Transformation [\#22](https://github.com/diagrams/diagrams-core/issues/22)++**Closed issues:**++- Support for monoid-extras-0.3.0.0 [\#38](https://github.com/diagrams/diagrams-core/issues/38)++**Merged pull requests:**++- New IsPrim class for supporting ScaleInv [\#37](https://github.com/diagrams/diagrams-core/pull/37) ([byorgey](https://github.com/byorgey))++- onBasis gets the matrix equivalent of the Transformation [\#36](https://github.com/diagrams/diagrams-core/pull/36) ([bergey](https://github.com/bergey))++## [v0.6.0.2](https://github.com/diagrams/diagrams-core/tree/v0.6.0.2) (2013-03-06)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v0.6.0.1...v0.6.0.2)++**Fixed bugs:**++- radius is wrong [\#35](https://github.com/diagrams/diagrams-core/issues/35)++**Merged pull requests:**++- make SubMaps deletable, and add a new function 'localize' for hiding/deleting names [\#34](https://github.com/diagrams/diagrams-core/pull/34) ([byorgey](https://github.com/byorgey))++## [v0.6.0.1](https://github.com/diagrams/diagrams-core/tree/v0.6.0.1) (2013-01-07)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v0.6...v0.6.0.1)++**Fixed bugs:**++- "type instance V \(Point v\) = v" is not visible without explicit import. [\#17](https://github.com/diagrams/diagrams-core/issues/17)++**Merged pull requests:**++- Transformable instance for functions \(by conjugation\) [\#32](https://github.com/diagrams/diagrams-core/pull/32) ([conal](https://github.com/conal))++## [v0.6](https://github.com/diagrams/diagrams-core/tree/v0.6) (2012-12-12)++[Full Changelog](https://github.com/diagrams/diagrams-core/compare/v0.5...v0.6)++* **New features**++ - Proper support for subdiagrams: previous versions of+ diagrams-core had a mechanism for associating names with a pair+ of a location and an envelope. Now, names are associated with+ actual subdiagrams (including their location and envelope, along+ with all the other information stored by a diagram).++ See+ [`Diagrams.Core.Types`](https://github.com/diagrams/diagrams-core/blob/27b275f45cad514caefcd3035e4e261f1b4adf6f/src/Diagrams/Core/Types.hs#L493).++ - Traces: in addition to an envelope, each diagram now stores a+ "trace", which is like an embedded raytracer: given any ray+ (represented by a base point and a vector), the trace computes+ the closest point of intersection with the diagram along the+ ray. This is useful for determining points on the boundary of a+ diagram, *e.g.* when drawing arrows between diagrams.++ See [`Diagrams.Core.Trace`](https://github.com/diagrams/diagrams-core/blob/2f8727fdfa60cdf46456a23f358c8a771b2cd90d/src/Diagrams/Core/Trace.hs).++* **API changes**++ - The modules have all been renamed to be more consistent with the+ module naming scheme in the rest of the diagrams universe. In+ particular:++ `Graphics.Rendering.Diagrams` --> `Diagrams.Core`+ `Grahpics.Rendering.Diagrams.Core` --> `Diagrams.Core.Types`+ `Graphics.Rendering.Diagrams.*` --> `Diagrams.Core.*`++ - `Graphics.Rendering.Diagrams.UDTree` has been split out into a+ separate+ [`dual-tree`](http://hackage.haskell.org/package/dual%2Dtree)+ package (which has also been substantially rewritten).++ - `Graphics.Rendering.Diagrams.{Monoids,MList}` have been split+ out into a separate [`monoid-extras`](http://hackage.haskell.org/package/monoid%2Dextras) package.++ - The `names` function now returns a list of names and their+ associated locations, instead of the associated subdiagrams. In+ particular the output is suitable to be rendered to a `String`+ using `show`.++ - The new `subMap` function fills a similar role that `names` used+ to play, returning the entire mapping from names to subdiagrams.++ - New functions `envelope[VP]May`++ `envelopeV` and `envelopeP` return the zero vector and origin,+ respectively, when called on an empty envelope. However,+ sometimes it's useful to actually know whether the envelope was+ empty or not (the zero vector and the origin are legitimate+ outputs from non-empty envelopes). The new functions have their+ return type wrapped in `Maybe` for this purpose.++ - New functions `envelopeS` and `envelopeSMay`++ Like `envelope[VP](May)`, but returning a scalar multiple of+ the input vector.++ - The `Graphics.Rendering.Diagrams.Util` module has been removed,+ along with the `withLength` function. Calls to `withLength` can+ be replaced using++ `withLength s v = s *^ normalized v`++ - Add needed constraints `(InnerSpace v, OrderedField (Scalar v),+ Monoid' m)` to the type of the `renderDias` method in the+ `MultiBackend` class.++ - Generalized `Transformable` instances for pairs and tuples++ Previously, the components of the tuples were required to have+ the same type; but everything still works as long as they all+ share the same vector space. This is actually useful in+ practice: say, if we wanted to pair a diagram with a path and+ then apply the same transformation to both.++* **Improvements**++ - More efficient implementation of `diameter`++* **Dependency/version changes**++ - Tested with GHC 7.6.1+ - allow `base-4.6`+ - allow `containers-0.5.*`+ - allow `MemoTrie-0.6.1`++* **Bug fixes**++ - juxtaposeDefault now correctly handles empty envelopes (#37)++ `juxtaposeDefault` is now the identity on the second object if+ either one has an empty envelope. In particular this means that+ `mempty` is now an identity element for `beside` and friends.+ +**Implemented enhancements:**++- Turn R2 into D2 \(Generalize R2 to any numeric type\) [\#20](https://github.com/diagrams/diagrams-core/issues/20)++- Terminology: rename "bounding function" -\> "envelope"; "boundary function" -\> "boundary" [\#16](https://github.com/diagrams/diagrams-core/issues/16)++- Refactor: rename AnnDiagram to QDiagram [\#15](https://github.com/diagrams/diagrams-core/issues/15)++- Combine \(point, bounds\) pairs stored in NameMap into a single "located bounding function" data structure [\#14](https://github.com/diagrams/diagrams-core/issues/14)++- Remember more structure when building diagrams [\#12](https://github.com/diagrams/diagrams-core/issues/12)++- Diagram-building service library + executable [\#7](https://github.com/diagrams/diagrams-core/issues/7)++**Fixed bugs:**++- setBounds is incorrect -- throws away bounds of subsequent diagrams too [\#13](https://github.com/diagrams/diagrams-core/issues/13)++- Start developing test suites [\#10](https://github.com/diagrams/diagrams-core/issues/10)++- Freezing does not appear to work with the SVG backend [\#9](https://github.com/diagrams/diagrams-core/issues/9)++- Silent failure on other image types than .png [\#6](https://github.com/diagrams/diagrams-core/issues/6)++- Tutorial contains links to old version of package [\#5](https://github.com/diagrams/diagrams-core/issues/5)++- space is not left for empty diagram when using e.g. hcat' with {sep = ... } [\#3](https://github.com/diagrams/diagrams-core/issues/3)++- Ellipse rotated incorrectly in test file with ellipse next to a square [\#2](https://github.com/diagrams/diagrams-core/issues/2)++**Closed issues:**++- Rename core modules to remove Graphics.Rendering prefix. [\#28](https://github.com/diagrams/diagrams-core/issues/28)++- Improve haddock documentation [\#11](https://github.com/diagrams/diagrams-core/issues/11)++- Improve description of Envelope in Haddock documentation [\#1](https://github.com/diagrams/diagrams-core/issues/1)++**Merged pull requests:**++- Add envelopeS / envelopeSMay for querying scalar displacements from envelopes [\#31](https://github.com/diagrams/diagrams-core/pull/31) ([mgsloan](https://github.com/mgsloan))++- Better definition for diameter [\#30](https://github.com/diagrams/diagrams-core/pull/30) ([mgsloan](https://github.com/mgsloan))++- Added needed constraints for MultiBackend. [\#29](https://github.com/diagrams/diagrams-core/pull/29) ([fryguybob](https://github.com/fryguybob))++- Rename `names` to `subMap`, and add new function `names` [\#26](https://github.com/diagrams/diagrams-core/pull/26) ([byorgey](https://github.com/byorgey))++- Fixes to work with rewritten dual-tree [\#25](https://github.com/diagrams/diagrams-core/pull/25) ([byorgey](https://github.com/byorgey))++- Fix for juxtaposeDefault to correctly handle empty envelopes [\#24](https://github.com/diagrams/diagrams-core/pull/24) ([byorgey](https://github.com/byorgey))++- dep bumps - fixes for GHC7.6 [\#23](https://github.com/diagrams/diagrams-core/pull/23) ([mgsloan](https://github.com/mgsloan))++## [v0.5](https://github.com/diagrams/diagrams-core/tree/v0.5) (2012-03-09)++* New features:+ - New `Juxtaposable` class+ - New `NullBackend` and `D` types, for conveniently giving a+ monomorphic type to diagrams when we don't care which one it is.+ - [\#27](http://code.google.com/p/diagrams/issues/detail?id=27): Change type of `adjustDia` to return a new options record+ (with an explicitly filled-in size)++* New instances:+ - `Enveloped`, `HasOrigin`, `Juxtaposable`, `HasStyle`, and `Transformable`+ instances for `Set`s and tuples+ - `V Double = Double`+ - `Juxtaposable` and `Boundable` instances for `Map`++* API changes+ - `AnnDiagram` renamed to `QDiagram`+ - [\#61](http://code.google.com/p/diagrams/issues/detail?id=61): terminology change from "bounds" to "envelope"+ + `boundary` -> `envelopeP`+ + "bounding region" -> "envelope"+ + `Bounds` -> `Envelope`+ + `Boundable` -> `Enveloped`+ + `getBounds` -> `getEnvelope`+ + *etc.*+ - Split out definition of `Point` into separate package+ ([`vector-space-points`](http://hackage.haskell.org/package/vector%2Dspace%2Dpoints))+ - The `Point` constructor `P` is no longer exported from+ `Graphics.Rendering.Diagrams`. See the `Diagrams.TwoD.Types` module+ from `diagrams-lib` for new tools for working with abstract 2D+ points. If you really need the `P` constructor, import+ `Graphics.Rendering.Diagrams.Points`.+ - Name-related functions now return "located bounding functions"+ instead of pairs of points and bounds, to allow for future+ expansion.++* Dependency/version changes:+ - `vector-space` 0.8 is now required.+ - Bump base upper bound to allow 4.5; now tested with GHC 7.4.1.++* Bug fixes:+ - Bug fix related to empty envelopes++0.4: 23 October 2011+--------------------++* improved documentation+* a few new instances (Newtype Point, Boundable Point)+* new functions (value, clearValue, resetValue) for working with+ alternate query monoids++0.3: 18 June 2011+-----------------++* big overhaul of name maps:+ - allow arbitrary types as atomic names+ - carry along bounding functions as well as names in NameMaps+ - additional functions for querying information associated with names+* fix for issue #34 (fix behavior of setBounds)+* Transformable and HasOrigin instances for Transformations++0.2: 3 June 2011+----------------++* bounding regions can now be overridden+* new namePoint function for more flexibly assigning names to arbitrary points+* add HasStyle, Boundable, and HasOrigin instances for lists+* add a "trivial backend"+* transformable attributes++0.1.1: 18 May 2011+------------------++* link to new website++0.1: 17 May 2011+----------------++* initial preview release++\* *This Change Log was automatically generated by (and hand edited) [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
− CHANGES
@@ -1,78 +0,0 @@-* 0.5.0.1: 11 May 2012-- - Update MemoTrie upper bound to allow MemoTrie-0.5--* 0.5: 9 March 2012-- * New features:-- - New 'Juxtaposable' class-- - New NullBackend and D types, for conveniently giving a- monomorphic type to diagrams when we don't care which one it is.-- - #27: Change type of adjustDia to return a new options record- (with an explicitly filled-in size)-- * New instances:- - Enveloped, HasOrigin, Juxtaposable, HasStyle, and Transformable- instances for Sets and tuples- - V Double = Double- - Juxtaposable and Boundable instances for Map-- * API changes-- - AnnDiagram -> QDiagram-- - #61: terminology change from "bounds" to "envelope"- + boundary -> envelopeP- + "bounding region" -> "envelope"- + Bounds -> Envelope- + Boundable -> Enveloped- + getBounds -> getEnvelope- + etc.-- - Split out definition of Point into separate package- (vector-space-points)-- - The Point constructor P is no longer exported from- Graphics.Rendering.Diagrams. See the Diagrams.TwoD.Types module- from diagrams-lib for new tools for working with abstract 2D- points. If you really need the P constructor, import- Graphics.Rendering.Diagrams.Points.-- - Name-related functions now return "located bounding functions"- instead of pairs of points and bounds, to allow for future- expansion.-- * Dependency/version changes:- - vector-space 0.8 is now required.- - Bump base upper bound to allow 4.5; now tested with GHC 7.4.1.-- * Bug fixes:- - Bug fix related to empty envelopes--0.4: 23 October 2011- * improved documentation- * a few new instances (Newtype Point, Boundable Point)- * new functions (value, clearValue, resetValue) for working with- alternate query monoids0.1: 17 May 2011- * initial preview release--0.3: 18 June 2011- * big overhaul of name maps:- - allow arbitrary types as atomic names- - carry along bounding functions as well as names in NameMaps- - additional functions for querying information associated with names- * fix for issue #34 (fix behavior of setBounds)- * Transformable and HasOrigin instances for Transformations--0.2: 3 June 2011- * bounding regions can now be overridden- * new namePoint function for more flexibly assigning names to arbitrary points- * add HasStyle, Boundable, and HasOrigin instances for lists- * add a "trivial backend"- * transformable attributes--0.1.1: 18 May 2011- * link to new website
LICENSE view
@@ -1,10 +1,22 @@-Copyright (c) 2011-2012 diagrams-core team:- +Copyright (c) 2011-2015 diagrams-core team:++ Daniel Bergey <bergey@alum.mit.edu>+ Christopher Chalmers <c.chalmers@me.com>+ Tad Doxsee <doxsee@pacbell.net>+ Conal Elliott <conal@conal.net>+ Ben Gamari <bgamari.foss@gmail.com>+ Allan Gardner <allanegardner@gmail.com> Sam Griffin <sam.griffin@gmail.com>+ Niklas Haas <git@nand.wakku.to>+ Chris Mears <chris@cmears.id.au>+ Jeffrey Rosenbluth <Jeffrey.Rosenbluth@gmail.com>+ Carlos Scheidegger <cscheid@research.att.com>+ Ryan Scott <ryan.gl.scott@ku.edu> Vilhelm Sjöberg <vilhelm.sjoberg@gmail.com>+ Michael Sloan <mgsloan@gmail.com> Scott Walck <walck@lvc.edu> Ryan Yates <fryguybob@gmail.com>- Brent Yorgey <byorgey@cis.upenn.edu>+ Brent Yorgey <byorgey@gmail.com> All rights reserved.
− README
@@ -1,9 +0,0 @@-The core modules underlying diagrams, a Haskell embedded-domain-specific language for compositional, declarative drawing. See-- http://projects.haskell.org/diagrams/--for more information about the project, including installation-instructions, tutorials, a user manual, a gallery of example images,-and links to the mailing list, IRC channel, developer wiki and bug-tracker.
+ README.markdown view
@@ -0,0 +1,6 @@+[](https://github.com/diagrams/diagrams-core/actions/workflows/haskell-ci.yml)++The core modules defining the basic data structures and algorithms for+[diagrams](http://projects.haskell.org/diagrams), a Haskell embedded+domain-specific language for compositional, declarative drawing.+
diagrams-core.cabal view
@@ -1,46 +1,69 @@ Name: diagrams-core-Version: 0.5.0.1+Version: 1.5.1.2 Synopsis: Core libraries for diagrams EDSL Description: The core modules underlying diagrams, an embedded domain-specific language for compositional, declarative drawing.-Homepage: http://projects.haskell.org/diagrams+Homepage: https://diagrams.github.io License: BSD3 License-file: LICENSE Author: Brent Yorgey Maintainer: diagrams-discuss@googlegroups.com+Bug-reports: https://github.com/diagrams/diagrams-core/issues Category: Graphics Build-type: Simple-Cabal-version: >=1.6-Extra-source-files: CHANGES, README-Tested-with: GHC == 6.12.3, GHC == 7.0.4, GHC == 7.2.1, GHC == 7.4.1+Cabal-version: 1.18+Extra-source-files: diagrams/*.svg+extra-doc-files: diagrams/*.svg, CHANGELOG.md, README.markdown+Tested-with: GHC ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.8 || ==9.6.6 || ==9.8.2 || ==9.10.1 || ==9.12.1 || ==9.14.1 Source-repository head- type: darcs- location: http://patch-tag.com/r/byorgey/diagrams-core+ type: git+ location: https://github.com/diagrams/diagrams-core.git Library- Exposed-modules: Graphics.Rendering.Diagrams,- Graphics.Rendering.Diagrams.Monoids,- Graphics.Rendering.Diagrams.MList,- Graphics.Rendering.Diagrams.UDTree,- Graphics.Rendering.Diagrams.V,- Graphics.Rendering.Diagrams.Query,- Graphics.Rendering.Diagrams.Transform,- Graphics.Rendering.Diagrams.Envelope,- Graphics.Rendering.Diagrams.HasOrigin,- Graphics.Rendering.Diagrams.Juxtapose,- Graphics.Rendering.Diagrams.Points,- Graphics.Rendering.Diagrams.Names,- Graphics.Rendering.Diagrams.Style,- Graphics.Rendering.Diagrams.Util,- Graphics.Rendering.Diagrams.Core-- Build-depends: base >= 4.2 && < 4.6,- containers >= 0.3 && < 0.5,- semigroups >= 0.3.4 && < 0.9,- vector-space >= 0.8 && < 0.9,- vector-space-points >= 0.1 && < 0.2,- MemoTrie >= 0.4.7 && < 0.6,- newtype >= 0.2 && < 0.3+ Exposed-modules: Diagrams.Core,+ Diagrams.Core.Compile,+ Diagrams.Core.Envelope,+ Diagrams.Core.HasOrigin,+ Diagrams.Core.Juxtapose,+ Diagrams.Core.Names,+ Diagrams.Core.Points,+ Diagrams.Core.Query+ Diagrams.Core.Style,+ Diagrams.Core.Measure,+ Diagrams.Core.Trace,+ Diagrams.Core.Transform,+ Diagrams.Core.Types,+ Diagrams.Core.V + Build-depends: base >= 4.11 && < 4.23,+ containers >= 0.4.2 && < 0.9,+ unordered-containers >= 0.2 && < 0.3,+ monoid-extras >= 0.6 && < 0.8,+ dual-tree >= 0.2 && < 0.3,+ lens >= 4.0 && < 5.4,+ linear >= 1.11.3 && < 1.24,+ adjunctions >= 4.0 && < 5.0,+ distributive >=0.2.2 && < 1.0,+ profunctors >= 5.0 && < 6.0,+ mtl >= 2.2 && < 2.4 hs-source-dirs: src++ Other-extensions: DeriveDataTypeable+ EmptyDataDecls+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ GADTs+ GeneralizedNewtypeDeriving+ MultiParamTypeClasses+ OverlappingInstances+ ScopedTypeVariables+ StandaloneDeriving+ TupleSections+ TypeFamilies+ TypeOperators+ TypeSynonymInstances+ UndecidableInstances++ Default-language: Haskell2010
+ diagrams/src_Diagrams_Core_Trace_maxRayTracePEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="251.1920" stroke-opacity="1" viewBox="0 0 600 251" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.9072,225.9724 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.8871,50.3137 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.3777,50.3137 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.4341,25.2196 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.6533,36.5209 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 226.0979,202.1330 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 276.2861,141.9072 l 54.2033,-90.3388 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 278.7955,141.9072 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 276.2861,141.9072 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 291.3425,116.8130 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 284.5617,128.1144 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 332.9987,51.5684 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.6537,161.9824 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 57.8419,237.2647 l 100.3764,-167.2940 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.3513,237.2647 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.8419,237.2647 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 72.8984,212.1706 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.1176,223.4720 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 160.7277,69.9707 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_maxRayTraceVEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="251.1920" stroke-opacity="1" viewBox="0 0 600 251" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.9072,225.9724 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.8871,50.3137 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.3777,50.3137 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.4341,25.2196 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.6533,36.5209 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 226.0979,202.1330 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 276.2861,141.9072 l 54.2033,-90.3388 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 278.7955,141.9072 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 276.2861,141.9072 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 291.3425,116.8130 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 284.5617,128.1144 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 276.2861,141.9072 l 47.2124,-78.6874 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 330.4893,51.5684 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 323.7085,62.8697 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 332.9987,51.5684 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.6537,161.9824 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 57.8419,237.2647 l 100.3764,-167.2940 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.3513,237.2647 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.8419,237.2647 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 72.8984,212.1706 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.1176,223.4720 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.8419,237.2647 l 93.3856,-155.6426 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 158.2183,69.9707 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 151.4375,81.2721 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 160.7277,69.9707 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_maxTracePEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="251.1920" stroke-opacity="1" viewBox="0 0 600 251" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.9072,225.9724 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 567.3777,50.3137 l -15.0565,25.0941 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.8871,50.3137 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.3777,50.3137 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.4341,25.2196 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.6533,36.5209 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 554.8306,75.4078 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 226.0979,202.1330 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 276.2861,141.9072 l 54.2033,-90.3388 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 278.7955,141.9072 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 276.2861,141.9072 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 291.3425,116.8130 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 284.5617,128.1144 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 332.9987,51.5684 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.6537,161.9824 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 57.8419,237.2647 l 100.3764,-167.2940 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.3513,237.2647 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.8419,237.2647 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 72.8984,212.1706 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.1176,223.4720 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 160.7277,69.9707 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_maxTraceVEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="251.1920" stroke-opacity="1" viewBox="0 0 600 251" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.9072,225.9724 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 567.3777,50.3137 l -15.0565,25.0941 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.8871,50.3137 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.3777,50.3137 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.4341,25.2196 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.6533,36.5209 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.3777,50.3137 l -8.0656,13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 552.3212,75.4078 l 12.6062,-10.9724 l -5.8254,-0.3289 l -3.0316,-4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 559.1020,64.1064 l 0.2100,-0.3500 l 0.6658,0.3995 l -0.8758,-0.0494 l 0.2100,-0.3500 l -0.6658,-0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 554.8306,75.4078 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 226.0979,202.1330 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 276.2861,141.9072 l 54.2033,-90.3388 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 278.7955,141.9072 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 276.2861,141.9072 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 291.3425,116.8130 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 284.5617,128.1144 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 276.2861,141.9072 l 47.2124,-78.6874 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 330.4893,51.5684 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 323.7085,62.8697 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 332.9987,51.5684 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.6537,161.9824 h 150.5646 v -150.5646 h -100.3764 v 50.1882 h 50.1882 v 50.1882 h -100.3764 v 50.1882 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.018820577164367,5.018820577164367"><path d="M 57.8419,237.2647 l 100.3764,-167.2940 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.3513,237.2647 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.8419,237.2647 l 8.0656,-13.4427 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 72.8984,212.1706 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.1176,223.4720 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5528821304000942" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.8419,237.2647 l 93.3856,-155.6426 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 158.2183,69.9707 l -12.6062,10.9724 l 5.8254,0.3289 l 3.0316,4.9853 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 151.4375,81.2721 l -0.2100,0.3500 l -0.6658,-0.3995 l 0.8758,0.0494 l -0.2100,0.3500 l 0.6658,0.3995 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 160.7277,69.9707 c 0.0000,-1.3859 -1.1235,-2.5094 -2.5094 -2.5094c -1.3859,-0.0000 -2.5094,1.1235 -2.5094 2.5094c -0.0000,1.3859 1.1235,2.5094 2.5094 2.5094c 1.3859,0.0000 2.5094,-1.1235 2.5094 -2.5094Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_rayTracePEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="252.3529" stroke-opacity="1" viewBox="0 0 600 252" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.1765,227.0168 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.7479,50.5462 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.2269,50.5462 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.3529,25.3361 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.5565,36.6636 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 224.3697,201.8067 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 274.7899,141.3025 l 24.2017,-40.3361 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 277.3109,141.3025 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 274.7899,141.3025 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 289.9160,116.0924 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 283.1195,127.4199 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 301.5126,100.9664 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.5630,162.7311 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 57.9832,238.3613 l 45.3782,-75.6303 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.5042,238.3613 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.9832,238.3613 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 73.1092,213.1513 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.3128,224.4787 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 105.8824,162.7311 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_rayTraceVEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="252.3529" stroke-opacity="1" viewBox="0 0 600 252" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.1765,227.0168 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.7479,50.5462 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.2269,50.5462 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.3529,25.3361 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.5565,36.6636 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 224.3697,201.8067 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 274.7899,141.3025 l 24.2017,-40.3361 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 277.3109,141.3025 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 274.7899,141.3025 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 289.9160,116.0924 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 283.1195,127.4199 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 274.7899,141.3025 l 17.1947,-28.6579 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 298.9916,100.9664 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 292.1951,112.2938 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 301.5126,100.9664 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.5630,162.7311 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 57.9832,238.3613 l 45.3782,-75.6303 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.5042,238.3613 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.9832,238.3613 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 73.1092,213.1513 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.3128,224.4787 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.9832,238.3613 l 38.3712,-63.9520 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 103.3613,162.7311 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 96.5649,174.0585 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 105.8824,162.7311 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_traceEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="206.6667" stroke-opacity="1" viewBox="0 0 200 207" font-size="1" width="200.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="0.8132240363721016" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 9.0909,194.2424 h 181.8182 v -181.8182 h -121.2121 v 60.6061 h 60.6061 v 60.6061 h -121.2121 v 60.6061 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="0.8132240363721016" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="6.0606060606060606,6.0606060606060606"><path d="M 69.6970,121.5152 l -43.6364,72.7273 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="0.8132240363721016" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="6.0606060606060606,6.0606060606060606"><path d="M 69.6970,121.5152 l 65.4545,-109.0909 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 72.7273,121.5152 c 0.0000,-1.6736 -1.3567,-3.0303 -3.0303 -3.0303c -1.6736,-0.0000 -3.0303,1.3567 -3.0303 3.0303c -0.0000,1.6736 1.3567,3.0303 3.0303 3.0303c 1.6736,0.0000 3.0303,-1.3567 3.0303 -3.0303Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="0.8132240363721016" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 69.6970,121.5152 l 14.5208,-24.2014 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 87.8788,91.2121 l -6.6017,5.7461 l 3.0507,0.1722 l 1.5876,2.6107 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 84.3278,97.1305 l -0.1100,0.1833 l -0.3487,-0.2092 l 0.4586,0.0259 l -0.1100,0.1833 l 0.3487,0.2092 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 138.1818,12.4242 c 0.0000,-1.6736 -1.3567,-3.0303 -3.0303 -3.0303c -1.6736,-0.0000 -3.0303,1.3567 -3.0303 3.0303c -0.0000,1.6736 1.3567,3.0303 3.0303 3.0303c 1.6736,0.0000 3.0303,-1.3567 3.0303 -3.0303Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 101.8182,73.0303 c 0.0000,-1.6736 -1.3567,-3.0303 -3.0303 -3.0303c -1.6736,-0.0000 -3.0303,1.3567 -3.0303 3.0303c -0.0000,1.6736 1.3567,3.0303 3.0303 3.0303c 1.6736,0.0000 3.0303,-1.3567 3.0303 -3.0303Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 65.4545,133.6364 c 0.0000,-1.6736 -1.3567,-3.0303 -3.0303 -3.0303c -1.6736,-0.0000 -3.0303,1.3567 -3.0303 3.0303c -0.0000,1.6736 1.3567,3.0303 3.0303 3.0303c 1.6736,0.0000 3.0303,-1.3567 3.0303 -3.0303Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 29.0909,194.2424 c 0.0000,-1.6736 -1.3567,-3.0303 -3.0303 -3.0303c -1.6736,-0.0000 -3.0303,1.3567 -3.0303 3.0303c -0.0000,1.6736 1.3567,3.0303 3.0303 3.0303c 1.6736,0.0000 3.0303,-1.3567 3.0303 -3.0303Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_tracePEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="252.3529" stroke-opacity="1" viewBox="0 0 600 252" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.1765,225.7563 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 567.2269,49.2857 l -105.8824,176.4706 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.7479,49.2857 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.2269,49.2857 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.3529,24.0756 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.5565,35.4031 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 463.8655,225.7563 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 224.3697,200.5462 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 274.7899,140.0420 l -36.3025,60.5042 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 277.3109,140.0420 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 274.7899,140.0420 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 289.9160,114.8319 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 283.1195,126.1594 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 241.0084,200.5462 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.5630,162.7311 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 57.9832,238.3613 l 45.3782,-75.6303 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.5042,238.3613 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.9832,238.3613 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 73.1092,213.1513 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.3128,224.4787 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 105.8824,162.7311 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g></svg>
+ diagrams/src_Diagrams_Core_Trace_traceVEx.svg view
@@ -0,0 +1,1 @@+<svg xmlns="http://www.w3.org/2000/svg" height="252.3529" stroke-opacity="1" viewBox="0 0 600 252" font-size="1" width="600.0000" xmlns:xlink="http://www.w3.org/1999/xlink" stroke="rgb(0,0,0)" version="1.1"><defs></defs><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 441.1765,225.7563 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 567.2269,49.2857 l -105.8824,176.4706 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 569.7479,49.2857 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.2269,49.2857 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 582.3529,24.0756 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 575.5565,35.4031 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 567.2269,49.2857 l -98.8754,164.7923 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 461.3445,225.7563 l 12.6353,-10.9978 l -5.8389,-0.3297 l -3.0386,-4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 468.1410,214.4289 l 0.2105,-0.3508 l 0.6673,0.4004 l -0.8778,-0.0496 l 0.2105,-0.3508 l -0.6673,-0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 463.8655,225.7563 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 224.3697,200.5462 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 274.7899,140.0420 l -36.3025,60.5042 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 277.3109,140.0420 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 274.7899,140.0420 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 289.9160,114.8319 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 283.1195,126.1594 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 274.7899,140.0420 l -29.2956,48.8259 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 238.4874,200.5462 l 12.6353,-10.9978 l -5.8389,-0.3297 l -3.0386,-4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 245.2839,189.2188 l 0.2105,-0.3508 l 0.6673,0.4004 l -0.8778,-0.0496 l 0.2105,-0.3508 l -0.6673,-0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 241.0084,200.5462 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 7.5630,162.7311 h 151.2605 v -151.2605 h -100.8403 v 50.4202 h 50.4202 v 50.4202 h -100.8403 v 50.4202 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-dashoffset="0.0" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-dasharray="5.042016806722689,5.042016806722689"><path d="M 57.9832,238.3613 l 45.3782,-75.6303 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 60.5042,238.3613 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,0,255)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.9832,238.3613 l 8.1191,-13.5318 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 73.1092,213.1513 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,255)" stroke-width="0.0" fill="rgb(0,0,255)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 66.3128,224.4787 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="0.0" stroke="rgb(0,128,0)" stroke-width="1.5564665866295098" fill="rgb(0,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 57.9832,238.3613 l 38.3712,-63.9520 "/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 103.3613,162.7311 l -12.6353,10.9978 l 5.8389,0.3297 l 3.0386,4.9968 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,128,0)" stroke-width="0.0" fill="rgb(0,128,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 96.5649,174.0585 l -0.2105,0.3508 l -0.6673,-0.4004 l 0.8778,0.0496 l -0.2105,0.3508 l 0.6673,0.4004 Z"/></g><g stroke-linejoin="miter" stroke-opacity="1.0" fill-opacity="1.0" stroke="rgb(0,0,0)" stroke-width="0.0" fill="rgb(255,0,0)" stroke-linecap="butt" stroke-miterlimit="10.0"><path d="M 105.8824,162.7311 c 0.0000,-1.3923 -1.1287,-2.5210 -2.5210 -2.5210c -1.3923,-0.0000 -2.5210,1.1287 -2.5210 2.5210c -0.0000,1.3923 1.1287,2.5210 2.5210 2.5210c 1.3923,0.0000 2.5210,-1.1287 2.5210 -2.5210Z"/></g></svg>
+ src/Diagrams/Core.hs view
@@ -0,0 +1,270 @@+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- The core library of primitives forming the basis of an embedded+-- domain-specific language for describing and rendering diagrams.+-- Normal users of the diagrams library should almost never need to+-- import anything from this package directly; instead, import modules+-- (especially @Diagrams.Prelude@) from the diagrams-lib package,+-- which re-exports most things of value to users.+--+-- For most library code needing access to core internals, it should+-- be sufficient to import this module, which simply re-exports useful+-- functionality from other modules in the core library. Library+-- writers needing finer-grained access or functionality may+-- occasionally find it useful to directly import one of the+-- constituent core modules.+--+-- The diagrams library relies heavily on custom types and classes. Many+-- of the relevant definitions are in the "Diagrams.Core.Types" module.+-- Indeed the definition of the diagram type @QDiagram@ is contained in:+-- 'Diagrams.Core.Types.QDiagram'.+--+-- The best place to start when learning+-- about diagrams\' types is the user manual:+-- <https://diagrams.github.io/doc/manual.html#type-reference>+-- The following list shows which types are contained in each module of+-- "Diagrams.Core".+--+-- * "Diagrams.Core.Types"+--+-- * @'Annotation'@,+-- * @'UpAnnots' b v n m@, @'DownAnnots' v n@,+-- * @'QDiaLeaf' b v n m@, @'Measure' n@,+-- * @'Subdiagram' b v n m@, @'SubMap' b v n m@,+-- * @'Prim' b v n@, @'Backend' b v n@,+-- * @'DNode' b v n a@, @'DTree' b v n a@,+-- * @'RNode' b v n a@, @'RTree' b v n a@,+-- * @'NullBackend'@, @'Renderable' t b@,+-- * @'D' v n@.+--+-- * "Diagrams.Core.Envelope"+--+-- * @'Envelope' v n@, @'Enveloped' a@,+-- * @'OrderedField' s@.+--+-- * "Diagrams.Core.Juxtapose"+--+-- * @'Juxtaposable' a@.+--+-- * "Diagrams.Core.Names"+--+-- * @'AName'@, @'Name'@, @'IsName' a@,+-- * @'Qualifiable' q@.+--+-- * "Diagrams.Core.HasOrigin"+--+-- * @'HasOrigin' t@.+--+-- * "Diagrams.Core.Query"+--+-- * @'Query' v n m@.+--+-- * "Diagrams.Core.Style"+--+-- * @'AttributeClass' a@, @'Attribute' v n@,+-- * @'Style' v n@, @'HasStyle'@.+--+-- * "Diagrams.Core.Trace"+--+-- * @'SortedList' a@,+-- * @'Trace' v n@, @'Traced' a@.+--+-- * "Diagrams.Core.Transform"+--+-- * @u ':-:' v@, @'HasLinearMap'@, @'HasBasis'@+-- * @'Transformation' v n@, @'Transformable' t@,+-- * @'TransInv' t@.+--+-- * "Diagrams.Core.V"+--+-- * @'V' a@,+-- * @'N' a@,+-- * @'Vn' a@,+-- * @'InSpace' v n a@,+-- * @'SameSpace' a b@.+-----------------------------------------------------------------------------++module Diagrams.Core+ ( -- * Associated vector spaces++ V, N, Vn, InSpace, SameSpace++ -- * Points++ , Point, origin, (*.)+ , relative++ -- * Transformations++ -- ** Utilities+ , basis+ , dimension+ , determinant+ , isReflection++ -- ** Invertible linear transformations+ , (:-:), (<->), linv, lapp++ -- ** General transformations+ , Transformation+ , inv, transp, transl+ , dropTransl+ , apply+ , papply+ , fromLinear++ -- ** Some specific transformations+ , translation, translate, moveTo, place+ , scaling, scale+ , avgScale++ -- ** The Transformable class++ , Transformable(..)++ -- ** Translational invariance++ , TransInv(TransInv)+ , eye++ -- * Names++ , AName+ , Name, IsName(..)+ , Qualifiable(..), (.>)+ , eachName++ -- ** Subdiagram maps++ , SubMap(..)+ , fromNames+ , rememberAs++ , lookupSub++ -- * Attributes and styles++ , AttributeClass+ , Attribute (..)++ , Style, HasStyle(..)+ , getAttr+ , atAttr, atMAttr, atTAttr+ , applyAttr, applyMAttr, applyTAttr++ -- * Envelopes++ , Envelope(..)+ , appEnvelope, onEnvelope, mkEnvelope+ , Enveloped(..)+ , envelopeVMay, envelopeV, envelopePMay, envelopeP+ , diameter, radius, size++ -- * Traces++ , Trace(Trace)+ , SortedList, mkSortedList, getSortedList+ , appTrace, mkTrace+ , Traced(..)+ , traceV, traceP+ , maxTraceV, maxTraceP+ , rayTraceV, rayTraceP+ , maxRayTraceV, maxRayTraceP++ -- * Things with local origins++ , HasOrigin(..), moveOriginBy++ -- * Juxtaposable things++ , Juxtaposable(..), juxtaposeDefault++ -- * Queries++ , Query(..)++ -- * Primitives++ , Prim(..)++ -- * Diagrams++ , QDiagram, Diagram, mkQD, pointDiagram+ , envelope, trace, subMap, names, query++ , nameSub+ , withName+ , withNameAll+ , withNames+ , localize++ , href+ , opacityGroup+ , groupOpacity++ , setEnvelope, setTrace++ , atop++ -- ** Subdiagrams++ , Subdiagram(..), mkSubdiagram+ , getSub, rawSub+ , location+ , subPoint++ -- ** Measurements++ , Measured+ , Measure+ , fromMeasured+ , output+ , local+ , global+ , normalized+ , scaleLocal+ , atLeast+ , atMost++ -- * Backends++ , Backend(..)+ , Renderable(..)++ , renderDia+ , renderDiaT++ -- ** The null backend++ , NullBackend, D++ -- * Convenience classes++ , HasLinearMap+ , HasBasis+ , OrderedField+ , TypeableFloat+ , Monoid'++ ) where++import Diagrams.Core.Compile+import Diagrams.Core.Envelope+import Diagrams.Core.HasOrigin+import Diagrams.Core.Juxtapose+import Diagrams.Core.Measure+import Diagrams.Core.Names+import Diagrams.Core.Points+import Diagrams.Core.Query+import Diagrams.Core.Style+import Diagrams.Core.Trace+import Diagrams.Core.Transform+import Diagrams.Core.Types+import Diagrams.Core.V++import Data.Monoid.WithSemigroup (Monoid')
+ src/Diagrams/Core/Compile.hs view
@@ -0,0 +1,201 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Compile+-- Copyright : (c) 2013-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- This module provides tools for compiling @QDiagrams@ into a more+-- convenient and optimized tree form, suitable for use by backends.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Compile+ ( -- * Tools for backends+ RNode(..)+ , RTree+ , toRTree++ -- * Backend API++ , renderDia+ , renderDiaT++ -- * Internals++ , toDTree+ , fromDTree+ )+ where++import qualified Data.List.NonEmpty as NEL+import Data.Maybe (fromMaybe)+import Data.Monoid.Coproduct+import Data.Monoid.MList+import Data.Monoid.WithSemigroup (Monoid')+import Data.Semigroup+import Data.Tree+import Data.Tree.DUAL+import Data.Typeable++import Diagrams.Core.Envelope (OrderedField, diameter)+import Diagrams.Core.Style+import Diagrams.Core.Transform+import Diagrams.Core.Types++import Linear.Metric hiding (qd)++-- Typeable1 is a depreciated synonym in ghc > 707+#if __GLASGOW_HASKELL__ >= 707+#define Typeable1 Typeable+#endif++emptyDTree :: Tree (DNode b v n a)+emptyDTree = Node DEmpty []++uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r+uncurry3 f (x, y, z) = f x y z++-- | Convert a @QDiagram@ into a raw tree.+toDTree :: (HasLinearMap v, Floating n, Typeable n)+ => n -> n -> QDiagram b v n m -> Maybe (DTree b v n Annotation)+toDTree g n (QD qd)+ = foldDUAL++ -- Prims at the leaves. We ignore the accumulated d-annotations+ -- for prims (since we instead distribute them incrementally+ -- throughout the tree as they occur), or pass them to the+ -- continuation in the case of a delayed node.+ (\d -> withQDiaLeaf++ -- Prim: make a leaf node+ (\p -> Node (DPrim p) [])++ -- Delayed tree: pass the accumulated d-annotations to+ -- the continuation, convert the result to a DTree, and+ -- splice it in, adding a DDelay node to mark the point+ -- of the splice.+ (Node DDelay . (:[]) . fromMaybe emptyDTree . toDTree g n . ($ (d, g, n)) . uncurry3)+ )++ -- u-only leaves --> empty DTree. We don't care about the+ -- u-annotations.+ emptyDTree++ -- a non-empty list of child trees.+ (\ts -> case NEL.toList ts of+ [t] -> t+ ts' -> Node DEmpty ts'+ )++ -- Internal d-annotations. We untangle the interleaved+ -- transformations and style, and carefully place the style+ -- /above/ the transform in the tree (since by calling+ -- 'untangle' we have already performed the action of the+ -- transform on the style).+ (\d t -> case get d of+ Nothing -> t+ Just d' ->+ let (tr,sty) = untangle d'+ in Node (DStyle sty) [Node (DTransform tr) [t]]+ )++ -- Internal a-annotations.+ (\a t -> Node (DAnnot a) [t])+ qd++-- | Convert a @DTree@ to an @RTree@ which can be used directly by backends.+-- A @DTree@ includes nodes of type @DTransform (Transformation v)@;+-- in the @RTree@ transform is pushed down until it reaches a primitive node.+fromDTree :: forall b v n. (Floating n, HasLinearMap v)+ => DTree b v n Annotation -> RTree b v n Annotation+fromDTree = fromDTree' mempty+ where+ fromDTree' :: Transformation v n -> DTree b v n Annotation -> RTree b v n Annotation+ -- We put the accumulated transformation (accTr) and the prim+ -- into an RPrim node.+ fromDTree' accTr (Node (DPrim p) _)+ = Node (RPrim (transform accTr p)) []++ -- Styles are transformed then stored in their own node+ -- and accTr is push down the tree.+ fromDTree' accTr (Node (DStyle s) ts)+ = Node (RStyle (transform accTr s)) (fmap (fromDTree' accTr) ts)++ -- Transformations are accumulated and pushed down as well.+ fromDTree' accTr (Node (DTransform tr) ts)+ = Node REmpty (fmap (fromDTree' (accTr <> tr)) ts)++ fromDTree' accTr (Node (DAnnot a) ts)+ = Node (RAnnot a) (fmap (fromDTree' accTr) ts)++ -- Drop accumulated transformations upon encountering a DDelay+ -- node --- the tree unfolded beneath it already took into account+ -- any transformation at this point.+ fromDTree' _ (Node DDelay ts)+ = Node REmpty (fmap (fromDTree' mempty) ts)++ -- DEmpty nodes become REmpties, again accTr flows through.+ fromDTree' accTr (Node _ ts)+ = Node REmpty (fmap (fromDTree' accTr) ts)++-- | Compile a @QDiagram@ into an 'RTree', rewriting styles with the+-- given function along the way. Suitable for use by backends when+-- implementing 'renderData'. The first argument is the+-- transformation used to convert the diagram from local to output+-- units.+toRTree+ :: (HasLinearMap v, Metric v, Typeable n,+ OrderedField n, Monoid m, Semigroup m)+ => Transformation v n -> QDiagram b v n m -> RTree b v n Annotation+toRTree globalToOutput d+ = (fmap . onRStyle) (unmeasureAttrs gToO nToO)+ . fromDTree+ . fromMaybe (Node DEmpty [])+ . toDTree gToO nToO+ $ d+ where+ gToO = avgScale globalToOutput++ -- Scaling factor from normalized units to output units: nth root+ -- of product of diameters along each basis direction. Note at+ -- this point the diagram has already had the globalToOutput+ -- transformation applied, so output = global = local units.+ nToO = product (map (`diameter` d) basis) ** (1 / fromIntegral (dimension d))++-- | Apply a style transformation on 'RStyle' nodes; the identity for+-- other 'RNode's.+onRStyle :: (Style v n -> Style v n) -> RNode b v n a -> RNode b v n a+onRStyle f (RStyle s) = RStyle (f s)+onRStyle _ n = n++--------------------------------------------------++-- | Render a diagram, returning also the transformation which was+-- used to convert the diagram from its (\"global\") coordinate+-- system into the output coordinate system. The inverse of this+-- transformation can be used, for example, to convert output/screen+-- coordinates back into diagram coordinates. See also 'adjustDia'.+renderDiaT+ :: (Backend b v n , HasLinearMap v, Metric v,+ Typeable n, OrderedField n, Monoid' m)+ => b -> Options b v n -> QDiagram b v n m -> (Transformation v n, Result b v n)+renderDiaT b opts d = (g2o, renderRTree b opts' . toRTree g2o $ d')+ where (opts', g2o, d') = adjustDia b opts d++-- | Render a diagram.+renderDia+ :: (Backend b v n , HasLinearMap v, Metric v,+ Typeable n, OrderedField n, Monoid' m)+ => b -> Options b v n -> QDiagram b v n m -> Result b v n+renderDia b opts d = snd (renderDiaT b opts d)+
+ src/Diagrams/Core/Envelope.hs view
@@ -0,0 +1,365 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Envelope+-- Copyright : (c) 2011 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- diagrams-core defines the core library of primitives forming the+-- basis of an embedded domain-specific language for describing and+-- rendering diagrams.+--+-- The @Diagrams.Core.Envelope@ module defines a data type and type class for+-- \"envelopes\", aka functional bounding regions.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Envelope+ ( -- * Envelopes+ Envelope(..)++ , appEnvelope+ , onEnvelope+ , mkEnvelope+ , pointEnvelope++ , Enveloped(..)++ -- * Utility functions+ , diameter+ , radius+ , extent+ , size+ , envelopeVMay+ , envelopeV+ , envelopePMay+ , envelopeP+ , envelopeSMay+ , envelopeS++ -- * Miscellaneous+ , OrderedField+ ) where++#if __GLASGOW_HASKELL__ < 710+import Control.Applicative ((<$>))+#endif+import Control.Lens (Rewrapped, Wrapped (..), iso, mapped,+ op, over, (&), (.~), _Wrapping')+import Data.Functor.Rep+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Semigroup+import qualified Data.Set as S++import Diagrams.Core.HasOrigin+import Diagrams.Core.Points+import Diagrams.Core.Transform+import Diagrams.Core.V++import Linear.Metric+import Linear.Vector+++------------------------------------------------------------+-- Envelopes ---------------------------------------------+------------------------------------------------------------++-- | Every diagram comes equipped with an /envelope/. What is an envelope?+--+-- Consider first the idea of a /bounding box/. A bounding box+-- expresses the distance to a bounding plane in every direction+-- parallel to an axis. That is, a bounding box can be thought of+-- as the intersection of a collection of half-planes, two+-- perpendicular to each axis.+--+-- More generally, the intersection of half-planes in /every/+-- direction would give a tight \"bounding region\", or convex hull.+-- However, representing such a thing intensionally would be+-- impossible; hence bounding boxes are often used as an+-- approximation.+--+-- An envelope is an /extensional/ representation of such a+-- \"bounding region\". Instead of storing some sort of direct+-- representation, we store a /function/ which takes a direction as+-- input and gives a distance to a bounding half-plane as output.+-- The important point is that envelopes can be composed, and+-- transformed by any affine transformation.+--+-- Formally, given a vector @v@, the envelope computes a scalar @s@ such+-- that+--+-- * for every point @u@ inside the diagram,+-- if the projection of @(u - origin)@ onto @v@ is @s' *^ v@, then @s' <= s@.+--+-- * @s@ is the smallest such scalar.+--+-- There is also a special \"empty envelope\".+--+-- The idea for envelopes came from+-- Sebastian Setzer; see+-- <http://byorgey.wordpress.com/2009/10/28/collecting-attributes/#comment-2030>. See also Brent Yorgey, /Monoids: Theme and Variations/, published in the 2012 Haskell Symposium: <http://ozark.hendrix.edu/~yorgey/pub/monoid-pearl.pdf>; video: <http://www.youtube.com/watch?v=X-8NCkD2vOw>.+newtype Envelope v n = Envelope (Maybe (v n -> Max n))++instance Wrapped (Envelope v n) where+ type Unwrapped (Envelope v n) = Maybe (v n -> Max n)+ _Wrapped' = iso (\(Envelope e) -> e) Envelope++instance Rewrapped (Envelope v n) (Envelope v' n')++-- | \"Apply\" an envelope by turning it into a function. @Nothing@+-- is returned iff the envelope is empty.+appEnvelope :: Envelope v n -> Maybe (v n -> n)+appEnvelope (Envelope e) = (getMax .) <$> e++-- | A convenient way to transform an envelope, by specifying a+-- transformation on the underlying @v n -> n@ function. The empty+-- envelope is unaffected.+onEnvelope :: ((v n -> n) -> v n -> n) -> Envelope v n -> Envelope v n+onEnvelope t = over (_Wrapping' Envelope . mapped) ((Max .) . t . (getMax .))++-- | Create an envelope from a @v n -> n@ function.+mkEnvelope :: (v n -> n) -> Envelope v n+mkEnvelope = Envelope . Just . (Max .)++-- | Create a point envelope for the given point. A point envelope+-- has distance zero to a bounding hyperplane in every direction.+-- Note this is /not/ the same as the empty envelope.+pointEnvelope :: (Fractional n, Metric v) => Point v n -> Envelope v n+pointEnvelope p = moveTo p (mkEnvelope $ const 0)++-- | Envelopes form a semigroup with pointwise maximum as composition.+-- Hence, if @e1@ is the envelope for diagram @d1@, and+-- @e2@ is the envelope for @d2@, then @e1 \`mappend\` e2@+-- is the envelope for @d1 \`atop\` d2@.+deriving instance Ord n => Semigroup (Envelope v n)++-- | The special empty envelope is the identity for the+-- 'Monoid' instance.+deriving instance Ord n => Monoid (Envelope v n)++type instance V (Envelope v n) = v+type instance N (Envelope v n) = n++instance Show (Envelope v n) where+ show _ = "<envelope>"++------------------------------------------------------------+-- Transforming envelopes --------------------------------+------------------------------------------------------------++-- | The local origin of an envelope is the point with respect to+-- which bounding queries are made, /i.e./ the point from which the+-- input vectors are taken to originate.+instance (Metric v, Fractional n) => HasOrigin (Envelope v n) where+ moveOriginTo (P u) = onEnvelope $ \oldEnv v -> oldEnv v - ((u ^/ (v `dot` v)) `dot` v)+ -- For a detailed explanation of this code, see note+ -- [Transforming Envelopes] below.++instance (Metric v, Floating n) => Transformable (Envelope v n) where+ transform t = moveOriginTo (P . negated . transl $ t) . onEnvelope g+ where++ -- For a detailed explanation of this code, see note+ -- [Transforming Envelopes] below.+ g f v = f v' / (v' `dot` vi)+ where+ v' = signorm $ lapp (transp t) v+ vi = apply (inv t) v++{-++Note [Transforming Envelopes]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++We are given an envelope for some object, and want to apply an affine+transformation, such that the new envelope will be the envelope for+the transformed object. The HasOrigin instance handles the+translational component; the rest of the code in the Transformable+instance handles the linear component.++See <<diagrams/EnvHasOrigin.png>>.++To implement moveOriginTo, we need to move the "base point" from which+envelope queries are made. We are given the old envelope @oldEnv@ (a+function from vectors to scalars), a vector @u@ from the old origin to+the new origin, and a query vector @v@ which we imagine to emanate+from the new origin. If we query the old envelope with v, it will+find the correct perpendicular hyperplane, but the reported distance+may be wrong (it will only be correct if the origin was moved in a+direction perpendicular to v). The part that needs to be subtracted+is just the projection of u onto v, which is given by (u.v)/(v.v) *^+v. In fact envelopes return not a distance or vector, but a scalar+which is taken to be a multiple of the query vector, so the scalar we+need to subtract is just (u.v)/(v.v).++We now consider how to apply a linear transformation to an envelope.+Recall that an envelope is a function that takes a vector and returns+a scaling factor s such that scaling the vector by s will produce a+vector to the minimum separating hyperplane. (So if given a unit+vector as input, the output will be simply the distance to the minimum+separating hyperplane.)++We are given a linear transformation t and must produce a new envelope+function. Given an input vector v, the "obvious" thing to do is to+transform v back into the original coordinate system using the inverse+of t, apply the original envelope, and then adjust the resulting+scalar according to how much the transformation scales v.++However, this does not work, since linear transformations do not+preserve angles. Thus, in particular, given the query vector v and+the perpendicular separating hyperplane H which we wish to find, t^-1+v and t^-1 H are not necessarily perpendicular anymore. So if we+query the envelope with t^-1 v we will get information about the+distance to some separating hyperplane, which when mapped forward+through t will no longer be perpendicular to v.++However, it turns out that if v and w are perpendicular, then t^-1 v+will be perpendicular to t^T w, that is, the *transpose* of t (when+considered as a matrix) applied to w. The proof is simple. Recall+that v and w are perpendicular if and only if v . w = v^T w = 0. Thus,++ (t^-1 v) . (t^T w) = (t^-1 v)^T (t^T w) = v^T t^-T t^T w = v^T w = 0.++Now to explain this code:++ g f v = f v' / (v' `dot` vi)+ where+ v' = signorm $ lapp (transp t) v+ vi = apply (inv t) v++In our case, our new envelope function (transformed by t) will be+given a query vector v, and we suppose v is perpendicular to the+separating hyperplane H. Instead of querying the old envelope+function f with t^-1 v, we query it with t^T v (after normalizing),+since that vector will be perpendicular to t^-1 H.++Finally, to scale the resulting value correctly, we divide by (t^T v+. t^-1 v); I forget why. Perhaps I will come back later and complete+this explanation.++-}++------------------------------------------------------------+-- Enveloped class+------------------------------------------------------------++-- | When dealing with envelopes we often want scalars to be an+-- ordered field (i.e. support all four arithmetic operations and be+-- totally ordered) so we introduce this constraint as a convenient+-- shorthand.+type OrderedField s = (Floating s, Ord s)++-- | @Enveloped@ abstracts over things which have an envelope.+class (Metric (V a), OrderedField (N a)) => Enveloped a where++ -- | Compute the envelope of an object. For types with an intrinsic+ -- notion of \"local origin\", the envelope will be based there.+ -- Other types (e.g. 'Trail') may have some other default+ -- reference point at which the envelope will be based; their+ -- instances should document what it is.+ getEnvelope :: a -> Envelope (V a) (N a)++instance (Metric v, OrderedField n) => Enveloped (Envelope v n) where+ getEnvelope = id++instance (OrderedField n, Metric v) => Enveloped (Point v n) where+ getEnvelope p = moveTo p . mkEnvelope $ const 0++instance Enveloped t => Enveloped (TransInv t) where+ getEnvelope = getEnvelope . op TransInv++instance (Enveloped a, Enveloped b, V a ~ V b, N a ~ N b) => Enveloped (a,b) where+ getEnvelope (x,y) = getEnvelope x <> getEnvelope y++instance Enveloped b => Enveloped [b] where+ getEnvelope = mconcat . map getEnvelope++instance Enveloped b => Enveloped (M.Map k b) where+ getEnvelope = mconcat . map getEnvelope . M.elems++instance Enveloped b => Enveloped (S.Set b) where+ getEnvelope = mconcat . map getEnvelope . S.elems++------------------------------------------------------------+-- Computing with envelopes+------------------------------------------------------------++-- | Compute the vector from the local origin to a separating+-- hyperplane in the given direction, or @Nothing@ for the empty+-- envelope.+envelopeVMay :: Enveloped a => Vn a -> a -> Maybe (Vn a)+envelopeVMay v = fmap ((*^ v) . ($ v)) . appEnvelope . getEnvelope++-- | Compute the vector from the local origin to a separating+-- hyperplane in the given direction. Returns the zero vector for+-- the empty envelope.+envelopeV :: Enveloped a => Vn a -> a -> Vn a+envelopeV v = fromMaybe zero . envelopeVMay v++-- | Compute the point on a separating hyperplane in the given+-- direction, or @Nothing@ for the empty envelope.+envelopePMay :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Maybe (Point v n)+envelopePMay v = fmap P . envelopeVMay v++-- | Compute the point on a separating hyperplane in the given+-- direction. Returns the origin for the empty envelope.+envelopeP :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Point v n+envelopeP v = P . envelopeV v++-- | Equivalent to the norm of 'envelopeVMay':+--+-- @ envelopeSMay v x == fmap norm (envelopeVMay v x) @+--+-- (other than differences in rounding error)+--+-- Note that the 'envelopeVMay' / 'envelopePMay' functions above should be+-- preferred, as this requires a call to norm. However, it is more+-- efficient than calling norm on the results of those functions.+envelopeSMay :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Maybe n+envelopeSMay v = fmap ((* norm v) . ($ v)) . appEnvelope . getEnvelope++-- | Equivalent to the norm of 'envelopeV':+--+-- @ envelopeS v x == norm (envelopeV v x) @+--+-- (other than differences in rounding error)+--+-- Note that the 'envelopeV' / 'envelopeP' functions above should be+-- preferred, as this requires a call to norm. However, it is more+-- efficient than calling norm on the results of those functions.+envelopeS :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> n+envelopeS v = fromMaybe 0 . envelopeSMay v++-- | Compute the diameter of a enveloped object along a particular+-- vector. Returns zero for the empty envelope.+diameter :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> n+diameter v a = maybe 0 (\(lo,hi) -> (hi - lo) * norm v) (extent v a)++-- | Compute the \"radius\" (1\/2 the diameter) of an enveloped object+-- along a particular vector.+radius :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> n+radius v = (0.5*) . diameter v++-- | Compute the range of an enveloped object along a certain+-- direction. Returns a pair of scalars @(lo,hi)@ such that the+-- object extends from @(lo *^ v)@ to @(hi *^ v)@. Returns @Nothing@+-- for objects with an empty envelope.+extent :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Maybe (n, n)+extent v a = (\f -> (-f (negated v), f v)) <$> (appEnvelope . getEnvelope $ a)++-- | The smallest positive /axis-parallel/ vector that bounds the+-- envelope of an object.+size :: (V a ~ v, N a ~ n, Enveloped a, HasBasis v) => a -> v n+size d = tabulate $ \(E l) -> diameter (zero & l .~ 1) d
+ src/Diagrams/Core/HasOrigin.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++-- The UndecidableInstances flag is needed under 6.12.3 for the+-- HasOrigin (a,b) instance.++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.HasOrigin+-- Copyright : (c) 2011 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Types which have an intrinsic notion of a \"local origin\",+-- /i.e./ things which are /not/ invariant under translation.+--+-----------------------------------------------------------------------------++module Diagrams.Core.HasOrigin+ ( HasOrigin(..), moveOriginBy, moveTo, place+ ) where++import qualified Data.Map as M+import qualified Data.Set as S++import Diagrams.Core.Measure+import Diagrams.Core.Points ()+import Diagrams.Core.V++import Linear.Affine+import Linear.Vector++-- | Class of types which have an intrinsic notion of a \"local+-- origin\", i.e. things which are not invariant under translation,+-- and which allow the origin to be moved.+--+-- One might wonder why not just use 'Transformable' instead of+-- having a separate class for 'HasOrigin'; indeed, for types which+-- are instances of both we should have the identity+--+-- @+-- moveOriginTo (origin .^+ v) === translate (negated v)+-- @+--+-- The reason is that some things (e.g. vectors, 'Trail's) are+-- transformable but are translationally invariant, i.e. have no+-- origin.+class HasOrigin t where++ -- | Move the local origin to another point.+ --+ -- Note that this function is in some sense dual to 'translate'+ -- (for types which are also 'Transformable'); moving the origin+ -- itself while leaving the object \"fixed\" is dual to fixing the+ -- origin and translating the diagram.+ moveOriginTo :: Point (V t) (N t) -> t -> t++-- | Move the local origin by a relative vector.+moveOriginBy :: (V t ~ v, N t ~ n, HasOrigin t) => v n -> t -> t+moveOriginBy = moveOriginTo . P++-- | Translate the object by the translation that sends the origin to+-- the given point. Note that this is dual to 'moveOriginTo', i.e. we+-- should have+--+-- @+-- moveTo (origin .^+ v) === moveOriginTo (origin .^- v)+-- @+--+-- For types which are also 'Transformable', this is essentially the+-- same as 'translate', i.e.+--+-- @+-- moveTo (origin .^+ v) === translate v+-- @+moveTo :: (InSpace v n t, HasOrigin t) => Point v n -> t -> t+moveTo = moveOriginBy . (origin .-.)++-- | A flipped variant of 'moveTo', provided for convenience. Useful+-- when writing a function which takes a point as an argument, such+-- as when using 'withName' and friends.+place :: (InSpace v n t, HasOrigin t) => t -> Point v n -> t+place = flip moveTo++instance HasOrigin t => HasOrigin (Measured n t) where+ moveOriginTo = fmap . moveOriginTo++instance (Additive v, Num n) => HasOrigin (Point v n) where+ moveOriginTo (P u) p = p .-^ u++instance (HasOrigin t, HasOrigin s, SameSpace s t) => HasOrigin (s, t) where+ moveOriginTo p (x,y) = (moveOriginTo p x, moveOriginTo p y)++instance HasOrigin t => HasOrigin [t] where+ moveOriginTo = map . moveOriginTo++instance (HasOrigin t, Ord t) => HasOrigin (S.Set t) where+ moveOriginTo = S.map . moveOriginTo++instance HasOrigin t => HasOrigin (M.Map k t) where+ moveOriginTo = M.map . moveOriginTo+
+ src/Diagrams/Core/Juxtapose.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Juxtapose+-- Copyright : (c) 2011 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Things which can be placed \"next to\" other things, for some+-- appropriate notion of \"next to\".+--+-----------------------------------------------------------------------------++module Diagrams.Core.Juxtapose+ ( Juxtaposable(..), juxtaposeDefault+ ) where++import Control.Applicative+import qualified Data.Map as M+import qualified Data.Set as S++import Diagrams.Core.Envelope+import Diagrams.Core.Measure+import Diagrams.Core.HasOrigin+import Diagrams.Core.V++import Linear.Metric+import Linear.Vector++-- | Class of things which can be placed \"next to\" other things, for some+-- appropriate notion of \"next to\".+class Juxtaposable a where++ -- | @juxtapose v a1 a2@ positions @a2@ next to @a1@ in the+ -- direction of @v@. In particular, place @a2@ so that @v@ points+ -- from the local origin of @a1@ towards the old local origin of+ -- @a2@; @a1@'s local origin becomes @a2@'s new local origin. The+ -- result is just a translated version of @a2@. (In particular,+ -- this operation does not /combine/ @a1@ and @a2@ in any way.)+ juxtapose :: Vn a -> a -> a -> a++-- | Default implementation of 'juxtapose' for things which are+-- instances of 'Enveloped' and 'HasOrigin'. If either envelope is+-- empty, the second object is returned unchanged.+juxtaposeDefault :: (Enveloped a, HasOrigin a) => Vn a -> a -> a -> a+juxtaposeDefault v a1 a2 =+ case (mv1, mv2) of+ (Just v1, Just v2) -> moveOriginBy (v1 ^+^ v2) a2+ _ -> a2+ where mv1 = negated <$> envelopeVMay v a1+ mv2 = envelopeVMay (negated v) a2++instance (Metric v, OrderedField n) => Juxtaposable (Envelope v n) where+ juxtapose = juxtaposeDefault++instance (Enveloped a, HasOrigin a, Enveloped b, HasOrigin b, V a ~ V b, N a ~ N b)+ => Juxtaposable (a,b) where+ juxtapose = juxtaposeDefault++instance (Enveloped b, HasOrigin b) => Juxtaposable [b] where+ juxtapose = juxtaposeDefault++instance (Enveloped b, HasOrigin b) => Juxtaposable (M.Map k b) where+ juxtapose = juxtaposeDefault++instance (Enveloped b, HasOrigin b, Ord b) => Juxtaposable (S.Set b) where+ juxtapose = juxtaposeDefault++instance Juxtaposable a => Juxtaposable (b -> a) where+ juxtapose v f1 f2 b = juxtapose v (f1 b) (f2 b)++instance Juxtaposable a => Juxtaposable (Measured n a) where+ juxtapose v = liftA2 (juxtapose v)+
+ src/Diagrams/Core/Measure.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-}+ -- for Data.Semigroup import, which becomes redundant under GHC 8.4++module Diagrams.Core.Measure+ ( Measured (..)+ , Measure+ , fromMeasured+ , output+ , local+ , global+ , normalized+ , normalised+ , scaleLocal+ , atLeast+ , atMost+ ) where++import Control.Applicative+import Control.Lens+import qualified Control.Monad.Reader as R+import Data.Distributive+import Data.Functor.Rep+import Data.Semigroup+import Data.Typeable++import Diagrams.Core.V++import Linear.Vector++-- | 'Measured n a' is an object that depends on 'local', 'normalized'+-- and 'global' scales. The 'normalized' and 'global' scales are+-- calculated when rendering a diagram.+--+-- For attributes, the 'local' scale gets multiplied by the average+-- scale of the transform.+newtype Measured n a = Measured { unmeasure :: (n,n,n) -> a }+ deriving (Typeable, Functor, Applicative, Monad, Additive, R.MonadReader (n,n,n))+-- (local, global, normalized) -> output++type instance V (Measured n a) = V a+type instance N (Measured n a) = N a++-- | A measure is a 'Measured' number.+type Measure n = Measured n n++-- | @fromMeasured globalScale normalizedScale measure -> a@+fromMeasured :: Num n => n -> n -> Measured n a -> a+fromMeasured g n (Measured m) = m (1,g,n)++-- | Output units don't change.+output :: n -> Measure n+output = pure++-- | Local units are scaled by the average scale of a transform.+local :: Num n => n -> Measure n+local x = views _1 (*x)++-- | Global units are scaled so that they are interpreted relative to+-- the size of the final rendered diagram.+global :: Num n => n -> Measure n+global x = views _2 (*x)++-- | Normalized units get scaled so that one normalized unit is the size of the+-- final diagram.+normalized :: Num n => n -> Measure n+normalized x = views _3 (*x)++-- | Just like 'normalized' but spelt properly.+normalised :: Num n => n -> Measure n+normalised x = views _3 (*x)++-- | Scale the local units of a 'Measured' thing.+scaleLocal :: Num n => n -> Measured n a -> Measured n a+scaleLocal s = R.local (_1 *~ s)++-- | Calculate the larger of two measures.+atLeast :: Ord n => Measure n -> Measure n -> Measure n+atLeast = liftA2 max++-- | Calculate the smaller of two measures.+atMost :: Ord n => Measure n -> Measure n -> Measure n+atMost = liftA2 min++instance Num a => Num (Measured n a) where+ (+) = (^+^)+ (-) = (^-^)+ (*) = liftA2 (*)++ fromInteger = pure . fromInteger+ abs = fmap abs+ signum = fmap signum++instance Fractional a => Fractional (Measured n a) where+ (/) = liftA2 (/)+ recip = fmap recip++ fromRational = pure . fromRational++instance Floating a => Floating (Measured n a) where+ pi = pure pi+ exp = fmap exp+ sqrt = fmap sqrt+ log = fmap log+ (**) = liftA2 (**)+ logBase = liftA2 logBase+ sin = fmap sin+ tan = fmap tan+ cos = fmap cos+ asin = fmap asin+ atan = fmap atan+ acos = fmap acos+ sinh = fmap sinh+ tanh = fmap tanh+ cosh = fmap cosh+ asinh = fmap asinh+ atanh = fmap atanh+ acosh = fmap acosh++instance Semigroup a => Semigroup (Measured n a) where+ (<>) = liftA2 (<>)++instance Monoid a => Monoid (Measured n a) where+ mempty = pure mempty++instance Distributive (Measured n) where+ distribute a = Measured $ \x -> fmap (\(Measured m) -> m x) a++instance Representable (Measured n) where+ type Rep (Measured n) = (n,n,n)+ tabulate = Measured+ index = unmeasure++instance Profunctor Measured where+ lmap f (Measured m) = Measured $ \(l,g,n) -> m (f l, f g, f n)+ rmap f (Measured m) = Measured $ f . m+
+ src/Diagrams/Core/Names.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-}+ -- for Data.Semigroup import, which becomes redundant under GHC 8.4++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Names+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- This module defines a type of names which can be used for referring+-- to subdiagrams, and related types.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Names+ (-- * Names+ -- ** Atomic names+ AName(..)+ , _AName++ -- ** Names+ , Name(..)+ , IsName(..)+ , (.>)+ , eachName++ -- ** Qualifiable+ , Qualifiable(..)++ ) where++import Control.Lens hiding ((.>))+import qualified Data.Map as M+import Data.Semigroup+import qualified Data.Set as S+import Data.Typeable++import Diagrams.Core.Transform+import Diagrams.Core.Measure++------------------------------------------------------------+-- Names -------------------------------------------------+------------------------------------------------------------++-- | Class for those types which can be used as names. They must+-- support 'Typeable' (to facilitate extracting them from+-- existential wrappers), 'Ord' (for comparison and efficient+-- storage) and 'Show'.+--+-- To make an instance of 'IsName', you need not define any methods,+-- just declare it.+--+-- WARNING: it is not recommended to use+-- @GeneralizedNewtypeDeriving@ in conjunction with @IsName@, since+-- in that case the underlying type and the @newtype@ will be+-- considered equivalent when comparing names. For example:+--+-- @+-- newtype WordN = WordN Int deriving (Show, Ord, Eq, Typeable, IsName)+-- @+--+-- is unlikely to work as intended, since @(1 :: Int)@ and @(WordN 1)@+-- will be considered equal as names. Instead, use+--+-- @+-- newtype WordN = WordN Int deriving (Show, Ord, Eq, Typeable, IsName)+-- instance IsName WordN+-- @+class (Typeable a, Ord a, Show a) => IsName a where+ toName :: a -> Name+ toName = Name . (:[]) . AName++instance IsName ()+instance IsName Bool+instance IsName Char+instance IsName Int+instance IsName Float+instance IsName Double+instance IsName Integer+instance IsName a => IsName [a]+instance IsName a => IsName (Maybe a)+instance (IsName a, IsName b) => IsName (a,b)+instance (IsName a, IsName b, IsName c) => IsName (a,b,c)++-- | Atomic names. @AName@ is just an existential wrapper around+-- things which are 'Typeable', 'Ord' and 'Show'.+data AName where+ AName :: (Typeable a, Ord a, Show a) => a -> AName+ deriving Typeable++instance IsName AName where+ toName = Name . (:[])++instance Eq AName where+ AName a1 == AName a2 =+ case cast a2 of+ Nothing -> False+ Just a2' -> a1 == a2'++instance Ord AName where+ AName a1 `compare` AName a2 =+ case cast a2 of+ Just a2' -> a1 `compare` a2'+ Nothing -> typeOf a1 `compare` typeOf a2++instance Show AName where+ showsPrec d (AName a) = showParen (d > 10) $+ showString "AName " . showsPrec 11 a++-- | Prism onto 'AName'.+_AName :: (Typeable a, Ord a, Show a) => Prism' AName a+_AName = prism' AName (\(AName a) -> cast a)++-- | A (qualified) name is a (possibly empty) sequence of atomic names.+newtype Name = Name [AName]+ deriving (Eq, Ord, Semigroup, Monoid, Typeable)++instance Rewrapped Name Name+instance Wrapped Name where+ type Unwrapped Name = [AName]+ _Wrapped' = iso (\(Name ns) -> ns) Name++instance Each Name Name AName AName where+ each = _Wrapped . traversed+ {-# INLINE each #-}++-- | Traversal over each name in a 'Name' that matches the target type.+--+-- @+-- >>> toListOf eachName ('a' .> False .> 'b') :: String+-- "ab"+-- >>> 'a' .> True .> 'b' & eachName %~ not+-- 'a' .> False .> 'b'+-- @+--+-- Note that the type of the name is very important.+--+-- @+-- >>> sumOf eachName ((1::Int) .> (2 :: Integer) .> (3 :: Int)) :: Int+-- 4+-- >>> sumOf eachName ((1::Int) .> (2 :: Integer) .> (3 :: Int)) :: Integer+-- 2+-- @+eachName :: (Typeable a, Ord a, Show a) => Traversal' Name a+eachName = each . _AName++instance Show Name where+ showsPrec d (Name xs) = case xs of+ [] -> showParen (d > 10) $ showString "toName []"+ [n] -> showParen (d > 10) $ showString "toName " . showsName 11 n+ (n:ns) -> showParen (d > 5) $ showsName 6 n . go ns+ where+ go (y:ys) = showString " .> " . showsName 6 y . go ys+ go _ = id+ where showsName dd (AName a) = showsPrec dd a++instance IsName Name where+ toName = id++-- | Convenient operator for writing qualified names with atomic+-- components of different types. Instead of writing @toName a1 \<\>+-- toName a2 \<\> toName a3@ you can just write @a1 .> a2 .> a3@.+(.>) :: (IsName a1, IsName a2) => a1 -> a2 -> Name+a1 .> a2 = toName a1 <> toName a2++-- | Instances of 'Qualifiable' are things which can be qualified by+-- prefixing them with a name.+class Qualifiable q where+ -- | Qualify with the given name.+ (.>>) :: IsName a => a -> q -> q++-- | Of course, names can be qualified using @(.>)@.+instance Qualifiable Name where+ (.>>) = (.>)++instance Qualifiable a => Qualifiable (TransInv a) where+ (.>>) n = over (_Unwrapping' TransInv) (n .>>)++instance (Qualifiable a, Qualifiable b) => Qualifiable (a,b) where+ n .>> (a,b) = (n .>> a, n .>> b)++instance (Qualifiable a, Qualifiable b, Qualifiable c) => Qualifiable (a,b,c) where+ n .>> (a,b,c) = (n .>> a, n .>> b, n .>> c)++instance Qualifiable a => Qualifiable [a] where+ n .>> as = map (n .>>) as++instance (Ord a, Qualifiable a) => Qualifiable (S.Set a) where+ n .>> s = S.map (n .>>) s++instance Qualifiable a => Qualifiable (M.Map k a) where+ n .>> m = fmap (n .>>) m++instance Qualifiable a => Qualifiable (b -> a) where+ n .>> f = (n .>>) . f++instance Qualifiable a => Qualifiable (Measured n a) where+ n .>> m = fmap (n .>>) m++infixr 5 .>>+infixr 5 .>
+ src/Diagrams/Core/Points.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Points+-- Copyright : (c) 2011 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- A type for /points/ (as distinct from vectors).+--+-----------------------------------------------------------------------------++module Diagrams.Core.Points+ ( -- * Points++ Point(..), origin, (*.), relative, _Point++ , reflectThrough, mirror, relative2, relative3+ ) where++import Control.Lens (over)++import Linear.Affine+import Linear.Vector++import Diagrams.Core.V++type instance V (Point v n) = v+type instance N (Point v n) = n++-- | Reflect a point across the origin.+mirror :: (Additive v, Num n) => Point v n -> Point v n+mirror = reflectThrough origin++-- | Scale a point by a scalar. Specialized version of '(*^)'.+(*.) :: (Functor v, Num n) => n -> Point v n -> Point v n+(*.) = (*^)++-- | Apply a transformation relative to the given point.+relative2 :: (Additive v, Num n)+ => Point v n -> (v n -> v n -> v n)+ -> Point v n -> Point v n -> Point v n+relative2 p f x y = (p .+^) $ f (inj x) (inj y) where inj = (.-. p)++-- | Apply a transformation relative to the given point.+relative3 :: (Additive v, Num n)+ => Point v n -> (v n -> v n -> v n -> v n)+ -> Point v n -> Point v n -> Point v n -> Point v n+relative3 p f x y z = (p .+^) $ f (inj x) (inj y) (inj z) where inj = (.-. p)++-- | Mirror a point through a given point.+reflectThrough :: (Additive v, Num n) => Point v n -> Point v n -> Point v n+reflectThrough o = over (relative o) negated+
+ src/Diagrams/Core/Query.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Query+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- The @Query@ module defines a type for \"queries\" on diagrams, which+-- are functions from points in a vector space to some monoid.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Query+ ( Query (..)+ ) where++import Control.Applicative+import Control.Lens+import Data.Semigroup+import Data.Distributive+import Data.Functor.Rep+import Data.Profunctor+import Data.Profunctor.Sieve+import Data.Profunctor.Closed+import qualified Data.Profunctor.Rep as P++import Linear.Affine+import Linear.Vector++import Diagrams.Core.HasOrigin+import Diagrams.Core.Transform+import Diagrams.Core.V++------------------------------------------------------------------------+-- Queries+------------------------------------------------------------------------++-- | A query is a function that maps points in a vector space to+-- values in some monoid. Queries naturally form a monoid, with+-- two queries being combined pointwise.+--+-- The idea for annotating diagrams with monoidal queries came from+-- the graphics-drawingcombinators package,+-- <http://hackage.haskell.org/package/graphics-drawingcombinators>.+newtype Query v n m = Query { runQuery :: Point v n -> m }+ deriving (Functor, Applicative, Monad, Semigroup, Monoid)++instance Distributive (Query v n) where+ distribute a = Query $ \p -> fmap (\(Query q) -> q p) a++instance Representable (Query v n) where+ type Rep (Query v n) = Point v n+ tabulate = Query+ index = runQuery++instance Functor v => Profunctor (Query v) where+ lmap f (Query q) = Query $ \p -> q (fmap f p)+ rmap = fmap++instance Functor v => Cosieve (Query v) (Point v) where+ cosieve = runQuery++instance Functor v => Closed (Query v) where+ closed (Query fab) = Query $ \fxa x -> fab (fmap ($ x) fxa)++instance Functor v => Costrong (Query v) where+ unfirst (Query f) = Query f'+ where f' fa = b where (b, d) = f ((\a -> (a, d)) <$> fa)+ unsecond (Query f) = Query f'+ where f' fa = b where (d, b) = f ((,) d <$> fa)++instance Functor v => P.Corepresentable (Query v) where+ type Corep (Query v) = Point v+ cotabulate = Query++-- | Setter over the input point of a query.+queryPoint :: Setter (Query v' n' m) (Query v n m) (Point v n) (Point v' n')+queryPoint = sets $ \f (Query q) -> Query $ q . f++instance Wrapped (Query v n m) where+ type Unwrapped (Query v n m) = Point v n -> m+ _Wrapped' = iso runQuery Query++instance Rewrapped (Query v a m) (Query v' a' m')++type instance V (Query v n m) = v+type instance N (Query v n m) = n++instance (Additive v, Num n) => HasOrigin (Query v n m) where+ moveOriginTo (P u) = queryPoint %~ (.+^ u)++instance (Additive v, Num n) => Transformable (Query v n m) where+ transform t = queryPoint %~ papply (inv t)+
+ src/Diagrams/Core/Style.hs view
@@ -0,0 +1,375 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Style+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- A definition of /styles/ for diagrams as extensible, heterogeneous+-- collections of attributes.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Style+ ( -- * Attributes+ -- $attr++ AttributeClass+ , Attribute(..)++ -- ** Attributes prisms+ , _Attribute+ , _MAttribute+ , _TAttribute++ -- ** Attributes utilities+ , unwrapAttribute+ , unmeasureAttribute+ , attributeType++ -- * Styles+ -- $style++ , Style(..)++ -- ** Making styles+ , attributeToStyle++ -- ** Extracting attibutes from styles+ , getAttr+ , unmeasureAttrs++ -- ** Attibute lenses+ , atAttr+ , atMAttr+ , atTAttr++ -- ** Applying styles+ , applyAttr+ , applyMAttr+ , applyTAttr++ , HasStyle(..)++ ) where++import Control.Applicative+import Control.Arrow ((***))+import Control.Lens hiding (transform)+import qualified Data.HashMap.Strict as HM+import Data.Kind (Type)+import qualified Data.Map as M+import Data.Monoid.Action as A+import Data.Semigroup+import qualified Data.Set as S+import Data.Typeable++import Diagrams.Core.Measure+import Diagrams.Core.Transform+import Diagrams.Core.V++import Linear.Vector++------------------------------------------------------------+-- Attributes --------------------------------------------+------------------------------------------------------------++-- $attr+-- An /attribute/ is anything that determines some aspect of a+-- diagram's rendering. The standard diagrams library defines several+-- standard attributes (line color, line width, fill color, etc.) but+-- additional attributes may easily be created. Additionally, a given+-- backend need not handle (or even know about) attributes used in+-- diagrams it renders.+--+-- The attribute code is inspired by xmonad's @Message@ type, which+-- was in turn based on ideas in:+--+-- Simon Marlow.+-- /An Extensible Dynamically-Typed Hierarchy of Exceptions/.+-- Proceedings of the 2006 ACM SIGPLAN workshop on+-- Haskell. <http://research.microsoft.com/apps/pubs/default.aspx?id=67968>.++-- | Every attribute must be an instance of @AttributeClass@, which+-- simply guarantees 'Typeable' and 'Semigroup' constraints. The+-- 'Semigroup' instance for an attribute determines how it will combine+-- with other attributes of the same type.+class (Typeable a, Semigroup a) => AttributeClass a++-- | An existential wrapper type to hold attributes. Some attributes+-- are simply inert/static; some are affected by transformations;+-- and some are affected by transformations and can be modified+-- generically.+data Attribute (v :: Type -> Type) n :: Type where+ Attribute :: AttributeClass a => a -> Attribute v n+ MAttribute :: AttributeClass a => Measured n a -> Attribute v n+ TAttribute :: (AttributeClass a, Transformable a, V a ~ v, N a ~ n) => a -> Attribute v n++type instance V (Attribute v n) = v+type instance N (Attribute v n) = n++-- | Attributes form a semigroup, where the semigroup operation simply+-- returns the right-hand attribute when the types do not match, and+-- otherwise uses the semigroup operation specific to the (matching)+-- types.+instance Typeable n => Semigroup (Attribute v n) where+ (Attribute a1) <> (preview _Attribute -> Just a2) = Attribute (a1 <> a2)+ (MAttribute a1) <> (preview _MAttribute -> Just a2) = MAttribute (a1 <> a2)+ (TAttribute a1) <> (preview _TAttribute -> Just a2) = TAttribute (a1 <> a2)+ _ <> a2 = a2++-- | 'TAttribute's are transformed directly, 'MAttribute's have their+-- local scale multiplied by the average scale of the transform.+-- Plain 'Attribute's are unaffected.+instance (Additive v, Traversable v, Floating n) => Transformable (Attribute v n) where+ transform _ (Attribute a) = Attribute a+ transform t (MAttribute a) = MAttribute $ scaleLocal (avgScale t) a+ transform t (TAttribute a) = TAttribute $ transform t a++-- | Shows the kind of attribute and the type contained in the+-- attribute.+instance Show (Attribute v n) where+ showsPrec d attr = showParen (d > 10) $ case attr of+ Attribute a -> showString "Attribute " . showsPrec 11 (typeOf a)+ MAttribute a -> showString "MAttribute " . showsPrec 11 (mType a)+ TAttribute a -> showString "TAttribute " . showsPrec 11 (typeOf a)++-- | Unwrap an unknown 'Attribute' type, performing a dynamic (but+-- safe) check on the type of the result. If the required type+-- matches the type of the attribute, the attribute value is+-- returned wrapped in @Just@; if the types do not match, @Nothing@+-- is returned.+--+-- Measured attributes cannot be extrated from this function until+-- they have been unmeasured with 'unmeasureAttribute'. If you want a+-- measured attibute use the '_MAttribute' prism.+unwrapAttribute :: AttributeClass a => Attribute v n -> Maybe a+unwrapAttribute (Attribute a) = cast a+unwrapAttribute (MAttribute _) = Nothing+unwrapAttribute (TAttribute a) = cast a+{-# INLINE unwrapAttribute #-}++-- | Prism onto an 'Attribute'.+_Attribute :: AttributeClass a => Prism' (Attribute v n) a+_Attribute = prism' Attribute $ \t -> case t of Attribute a -> cast a; _ -> Nothing+{-# INLINE _Attribute #-}++-- | Prism onto an 'MAttribute'.+_MAttribute :: (AttributeClass a, Typeable n) => Prism' (Attribute v n) (Measured n a)+_MAttribute = prism' MAttribute $ \t -> case t of MAttribute a -> cast a; _ -> Nothing+{-# INLINE _MAttribute #-}++-- | Prism onto a 'TAttribute'.+_TAttribute :: (V a ~ v, N a ~ n, AttributeClass a, Transformable a)+ => Prism' (Attribute v n) a+_TAttribute = prism' TAttribute $ \t -> case t of TAttribute a -> cast a; _ -> Nothing+{-# INLINE _TAttribute #-}++-- | Turn an 'MAttribute' into an 'Attribute' using the given 'global'+-- and 'normalized' scale.+unmeasureAttribute :: (Num n)+ => n -> n -> Attribute v n -> Attribute v n+unmeasureAttribute g n (MAttribute m) = Attribute (fromMeasured g n m)+unmeasureAttribute _ _ a = a++-- | Type of an attribute that is stored with a style. Measured+-- attributes return the type as if it where unmeasured.+attributeType :: Attribute v n -> TypeRep+attributeType (Attribute a) = typeOf a+attributeType (MAttribute a) = mType a+attributeType (TAttribute a) = typeOf a++-- Note that we use type 'a' not 'Measured n a' so we don't have to rebuild+-- when unmeasuring the attributes.+mType :: forall n a. Typeable a => Measured n a -> TypeRep+mType _ = typeOf (undefined :: a)++-- naming convention: "Attribute" deals with the 'AttibuteType'+-- directly and "Attr" is for other things (like styles). Users should+-- rarely (if at all) deal with the 'Attibute' type directly.++------------------------------------------------------------+-- Styles ------------------------------------------------+------------------------------------------------------------++-- $style+-- A 'Style' is a heterogeneous collection of attributes, containing+-- at most one attribute of any given type. This is also based on+-- ideas stolen from xmonad, specifically xmonad's implementation of+-- user-extensible state.++-- | A @Style@ is a heterogeneous collection of attributes, containing+-- at most one attribute of any given type.+newtype Style v n = Style (HM.HashMap TypeRep (Attribute v n))++-- instances -----------------------------------------------------------++type instance V (Style v n) = v+type instance N (Style v n) = n++instance Rewrapped (Style v n) (Style v' n')+instance Wrapped (Style v n) where+ type Unwrapped (Style v n) = HM.HashMap TypeRep (Attribute v n)+ _Wrapped' = iso (\(Style m) -> m) Style+ {-# INLINE _Wrapped' #-}++instance Each (Style v n) (Style v' n') (Attribute v n) (Attribute v' n') where+ each = _Wrapped . each+ {-# INLINE each #-}++type instance Index (Style v n) = TypeRep+type instance IxValue (Style v n) = Attribute v n++instance Ixed (Style v n) where+ ix k = _Wrapped' . ix k+ {-# INLINE ix #-}++instance At (Style v n) where+ at k = _Wrapped' . at k+ {-# INLINE at #-}++-- | Combine a style by combining the attributes; if the two styles have+-- attributes of the same type they are combined according to their+-- semigroup structure.+instance Typeable n => Semigroup (Style v n) where+ Style s1 <> Style s2 = Style $ HM.unionWith (<>) s1 s2++-- | The empty style contains no attributes.+instance Typeable n => Monoid (Style v n) where+ mempty = Style HM.empty+ mappend = (<>)++instance (Additive v, Traversable v, Floating n) => Transformable (Style v n) where+ transform t = over each (transform t)++-- | Styles have no action on other monoids.+instance A.Action (Style v n) m++-- | Show the attributes in the style.+instance Show (Style v n) where+ showsPrec d sty = showParen (d > 10) $+ showString "Style " . showsPrec d (sty ^.. each)++-- making styles -------------------------------------------------------++-- | Turn an attribute into a style. An easier way to make a style is to+-- use the monoid instance and apply library functions for applying+-- that attribute:+--+-- @+-- myStyle = mempty # fc blue :: Style V2 Double+-- @+attributeToStyle :: Attribute v n -> Style v n+attributeToStyle a = Style $ HM.singleton (attributeType a) a++-- extracting attributes -----------------------------------------------++-- | Extract an attribute from a style of a particular type. If the+-- style contains an attribute of the requested type, it will be+-- returned wrapped in @Just@; otherwise, @Nothing@ is returned.+--+-- Trying to extract a measured attibute will fail. It either has to+-- be unmeasured with 'unmeasureAttrs' or use the 'atMAttr' lens.+getAttr :: forall a v n. AttributeClass a => Style v n -> Maybe a+getAttr (Style s) = HM.lookup ty s >>= unwrapAttribute+ where ty = typeOf (undefined :: a)+ -- unwrapAttribute can fail if someone tries to unwrap a measured+ -- attribute before it gets "unmeasured"++-- | Replace all 'MAttribute's with 'Attribute's using the 'global' and+-- 'normalized' scales.+unmeasureAttrs :: (Num n) => n -> n -> Style v n -> Style v n+unmeasureAttrs g n = over each (unmeasureAttribute g n)++-- style lenses --------------------------------------------------------++mkAttrLens :: forall v n a. Typeable a+ => (a -> TypeRep)+ -> Prism' (Attribute v n) a+ -> Lens' (Style v n) (Maybe a)+mkAttrLens tyF p f sty =+ f (sty ^? ix ty . p) <&> \mAtt -> sty & at ty .~ (review p <$> mAtt)+ where ty = tyF (undefined :: a)+{-# INLINE mkAttrLens #-}++-- | Lens onto a plain attribute of a style.+atAttr :: AttributeClass a+ => Lens' (Style v n) (Maybe a)+atAttr = mkAttrLens typeOf _Attribute+{-# INLINE atAttr #-}++-- | Lens onto a measured attribute of a style.+atMAttr :: (AttributeClass a, Typeable n)+ => Lens' (Style v n) (Maybe (Measured n a))+atMAttr = mkAttrLens mType _MAttribute+{-# INLINE atMAttr #-}++-- | Lens onto a transformable attribute of a style.+atTAttr :: (V a ~ v, N a ~ n, AttributeClass a, Transformable a)+ => Lens' (Style v n) (Maybe a)+atTAttr = mkAttrLens typeOf _TAttribute+{-# INLINE atTAttr #-}++-- applying styles -----------------------------------------------------++-- | Type class for things which have a style.+class HasStyle a where+ -- | /Apply/ a style by combining it (on the left) with the+ -- existing style.+ applyStyle :: Style (V a) (N a) -> a -> a++instance Typeable n => HasStyle (Style v n) where+ applyStyle = mappend++instance (HasStyle a, HasStyle b, V a ~ V b, N a ~ N b) => HasStyle (a,b) where+ applyStyle s = applyStyle s *** applyStyle s++instance HasStyle a => HasStyle [a] where+ applyStyle = fmap . applyStyle++instance HasStyle b => HasStyle (a -> b) where+ applyStyle = fmap . applyStyle++instance HasStyle a => HasStyle (M.Map k a) where+ applyStyle = fmap . applyStyle++instance (HasStyle a, Ord a) => HasStyle (S.Set a) where+ applyStyle = S.map . applyStyle++instance HasStyle b => HasStyle (Measured n b) where+ applyStyle = fmap . applyStyle++-- | Apply an attribute to an instance of 'HasStyle' (such as a+-- diagram or a style). If the object already has an attribute of+-- the same type, the new attribute is combined on the left with the+-- existing attribute, according to their semigroup structure.+applyAttr :: (AttributeClass a, HasStyle d) => a -> d -> d+applyAttr = applyStyle . attributeToStyle . Attribute++-- | Apply a measured attribute to an instance of 'HasStyle' (such as a+-- diagram or a style). If the object already has an attribute of+-- the same type, the new attribute is combined on the left with the+-- existing attribute, according to their semigroup structure.+applyMAttr :: (AttributeClass a, N d ~ n, HasStyle d) => Measured n a -> d -> d+applyMAttr = applyStyle . attributeToStyle . MAttribute++-- | Apply a transformable attribute to an instance of 'HasStyle'+-- (such as a diagram or a style). If the object already has an+-- attribute of the same type, the new attribute is combined on the+-- left with the existing attribute, according to their semigroup+-- structure.+applyTAttr :: (AttributeClass a, Transformable a, V a ~ V d, N a ~ N d, HasStyle d) => a -> d -> d+applyTAttr = applyStyle . attributeToStyle . TAttribute+
+ src/Diagrams/Core/Trace.hs view
@@ -0,0 +1,432 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-}+ -- for Data.Semigroup import, which becomes redundant under GHC 8.4++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Trace+-- Copyright : (c) 2012-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- @diagrams-core@ defines the core library of primitives+-- forming the basis of an embedded domain-specific language for+-- describing and rendering diagrams.+--+-- The @Trace@ module defines a data type and type class for+-- \"traces\", aka functional boundaries, essentially corresponding to+-- embedding a raytracer with each diagram.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Trace+ ( -- * SortedList+ SortedList+ , mkSortedList, getSortedList, onSortedList, unsafeOnSortedList++ -- * Traces+ , Trace(Trace)++ , appTrace+ , mkTrace++ -- * Traced class++ , Traced(..)++ -- * Computing with traces++ , traceV, traceP+ , maxTraceV, maxTraceP+ , getRayTrace+ , rayTraceV, rayTraceP+ , maxRayTraceV, maxRayTraceP++ ) where++#if __GLASGOW_HASKELL__ < 710+import Control.Applicative+#endif+import Control.Lens+import Data.List (sort)+import qualified Data.Map as M+import Data.Semigroup+import qualified Data.Set as S++import Diagrams.Core.HasOrigin+import Diagrams.Core.Transform+import Diagrams.Core.V++import Linear.Affine+import Linear.Vector+++------------------------------------------------------------+-- SortedList --------------------------------------------+------------------------------------------------------------++-- Traces return sorted lists of intersections, so we define a newtype+-- wrapper to represent sorted lists.++-- | A newtype wrapper around a list which maintains the invariant+-- that the list is sorted. The constructor is not exported; use+-- the smart constructor 'mkSortedList' (which sorts the given list)+-- instead.+newtype SortedList a = SortedList [a]++-- | A smart constructor for the 'SortedList' type, which sorts the+-- input to ensure the 'SortedList' invariant.+mkSortedList :: Ord a => [a] -> SortedList a+mkSortedList = SortedList . sort++-- | Project the (guaranteed sorted) list out of a 'SortedList'+-- wrapper.+getSortedList :: SortedList a -> [a]+getSortedList (SortedList as) = as++-- | Apply a list function to a 'SortedList'. The function need not+-- result in a sorted list; the result will be sorted before being+-- rewrapped as a 'SortedList'.+onSortedList :: Ord b => ([a] -> [b]) -> SortedList a -> SortedList b+onSortedList f = unsafeOnSortedList (sort . f)++-- | Apply an /order-preserving/ list function to a 'SortedList'. No+-- sorts or checks are done.+unsafeOnSortedList :: ([a] -> [b]) -> SortedList a -> SortedList b+unsafeOnSortedList f (SortedList as) = SortedList (f as)++-- | Merge two sorted lists. The result is the sorted list containing+-- all the elements of both input lists (with duplicates).+merge :: Ord a => SortedList a -> SortedList a -> SortedList a+merge (SortedList as) (SortedList bs) = SortedList (merge' as bs)+ where+ merge' xs [] = xs+ merge' [] ys = ys+ merge' (x:xs) (y:ys) =+ if x <= y+ then x : merge' xs (y:ys)+ else y : merge' (x:xs) ys++-- | 'SortedList' forms a semigroup with 'merge' as composition.+instance Ord a => Semigroup (SortedList a) where+ (<>) = merge++-- | 'SortedList' forms a monoid with 'merge' and the empty list.+instance Ord a => Monoid (SortedList a) where+ mappend = (<>)+ mempty = SortedList []++------------------------------------------------------------+-- Trace -------------------------------------------------+------------------------------------------------------------++-- > traceEx = mkTraceDia def++-- | Every diagram comes equipped with a /trace/. Intuitively, the+-- trace for a diagram is like a raytracer: given a line+-- (represented as a base point and a direction vector), the trace+-- computes a sorted list of signed distances from the base point to+-- all intersections of the line with the boundary of the+-- diagram.+--+-- Note that the outputs are not absolute distances, but multipliers+-- relative to the input vector. That is, if the base point is @p@+-- and direction vector is @v@, and one of the output scalars is+-- @s@, then there is an intersection at the point @p .+^ (s *^ v)@.+--+-- <<diagrams/src_Diagrams_Core_Trace_traceEx.svg#diagram=traceEx&width=200>>++newtype Trace v n = Trace { appTrace :: Point v n -> v n -> SortedList n }++instance Wrapped (Trace v n) where+ type Unwrapped (Trace v n) = Point v n -> v n -> SortedList n+ _Wrapped' = iso appTrace Trace++instance Rewrapped (Trace v n) (Trace v' n')++mkTrace :: (Point v n -> v n -> SortedList n) -> Trace v n+mkTrace = Trace++-- | Traces form a semigroup with pointwise minimum as composition.+-- Hence, if @t1@ is the trace for diagram @d1@, and+-- @e2@ is the trace for @d2@, then @e1 \`mappend\` e2@+-- is the trace for @d1 \`atop\` d2@.++deriving instance (Ord n) => Semigroup (Trace v n)++deriving instance (Ord n) => Monoid (Trace v n)++type instance V (Trace v n) = v+type instance N (Trace v n) = n++instance (Additive v, Num n) => HasOrigin (Trace v n) where+ moveOriginTo (P u) = _Wrapping' Trace %~ \f p -> f (p .+^ u)++instance Show (Trace v n) where+ show _ = "<trace>"++------------------------------------------------------------+-- Transforming traces -----------------------------------+------------------------------------------------------------++instance (Additive v, Num n) => Transformable (Trace v n) where+ transform t = _Wrapped %~ \f p v -> f (papply (inv t) p) (apply (inv t) v)++------------------------------------------------------------+-- Traced class ------------------------------------------+------------------------------------------------------------++-- | @Traced@ abstracts over things which have a trace.+class (Additive (V a), Ord (N a)) => Traced a where++ -- | Compute the trace of an object.+ getTrace :: a -> Trace (V a) (N a)++instance (Additive v, Ord n) => Traced (Trace v n) where+ getTrace = id++-- | The trace of a single point is the empty trace, /i.e./ the one+-- which returns no intersection points for every query. Arguably+-- it should return a single finite distance for vectors aimed+-- directly at the given point, but due to floating-point inaccuracy+-- this is problematic. Note that the envelope for a single point+-- is /not/ the empty envelope (see "Diagrams.Core.Envelope").+instance (Additive v, Ord n) => Traced (Point v n) where+ getTrace = const mempty++instance Traced t => Traced (TransInv t) where+ getTrace = getTrace . op TransInv++instance (Traced a, Traced b, SameSpace a b) => Traced (a,b) where+ getTrace (x,y) = getTrace x <> getTrace y++instance (Traced b) => Traced [b] where+ getTrace = mconcat . map getTrace++instance (Traced b) => Traced (M.Map k b) where+ getTrace = mconcat . map getTrace . M.elems++instance (Traced b) => Traced (S.Set b) where+ getTrace = mconcat . map getTrace . S.elems++------------------------------------------------------------+-- Computing with traces ---------------------------------+------------------------------------------------------------++-- | Compute the vector from the given point @p@ to the \"smallest\"+-- boundary intersection along the given vector @v@. The+-- \"smallest\" boundary intersection is defined as the one given by+-- @p .+^ (s *^ v)@ for the smallest (most negative) value of+-- @s@. Return @Nothing@ if there is no intersection. See also+-- 'traceP'.+--+-- See also 'rayTraceV' which uses the smallest /positive/+-- intersection, which is often more intuitive behavior.+--+-- <<diagrams/src_Diagrams_Core_Trace_traceVEx.svg#diagram=traceVEx&width=600>>+traceV :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (V a n)+traceV p v a = case getSortedList $ op Trace (getTrace a) p v of+ (s:_) -> Just (s *^ v)+ [] -> Nothing++-- > traceVEx = mkTraceDiasABC def { drawV = True, sFilter = take 1 }+++-- | Compute the \"smallest\" boundary point along the line determined+-- by the given point @p@ and vector @v@. The \"smallest\" boundary+-- point is defined as the one given by @p .+^ (s *^ v)@ for+-- the smallest (most negative) value of @s@. Return @Nothing@ if+-- there is no such boundary point. See also 'traceV'.+--+-- See also 'rayTraceP' which uses the smallest /positive/+-- intersection, which is often more intuitive behavior.+--+-- <<diagrams/src_Diagrams_Core_Trace_tracePEx.svg#diagram=tracePEx&width=600>>+traceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)+traceP p v a = (p .+^) <$> traceV p v a++-- > tracePEx = mkTraceDiasABC def { sFilter = take 1 }+++-- | Like 'traceV', but computes a vector to the \"largest\" boundary+-- point instead of the smallest. (Note, however, the \"largest\"+-- boundary point may still be in the opposite direction from the+-- given vector, if all the boundary points are, as in the third+-- example shown below.)+--+-- <<diagrams/src_Diagrams_Core_Trace_maxTraceVEx.svg#diagram=maxTraceVEx&width=600>>+maxTraceV :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (V a n)+maxTraceV p = traceV p . negated++-- > maxTraceVEx = mkTraceDiasABC def { drawV = True, sFilter = dropAllBut1 }+++-- | Like 'traceP', but computes the \"largest\" boundary point+-- instead of the smallest. (Note, however, the \"largest\" boundary+-- point may still be in the opposite direction from the given+-- vector, if all the boundary points are.)+--+-- <<diagrams/src_Diagrams_Core_Trace_maxTracePEx.svg#diagram=maxTracePEx&width=600>>+maxTraceP :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)+maxTraceP p v a = (p .+^) <$> maxTraceV p v a++-- > maxTracePEx = mkTraceDiasABC def { sFilter = dropAllBut1 }+++-- | Get a modified 'Trace' for an object which only returns positive+-- boundary points, /i.e./ those boundary points given by a positive+-- scalar multiple of the direction vector. Note, this property+-- will be destroyed if the resulting 'Trace' is translated at all.+getRayTrace :: (n ~ N a, Traced a, Num n) => a -> Trace (V a) n+getRayTrace a = Trace $ \p v -> unsafeOnSortedList (dropWhile (<0)) $ appTrace (getTrace a) p v++-- | Compute the vector from the given point to the closest boundary+-- point of the given object in the given direction, or @Nothing@ if+-- there is no such boundary point (as in the third example+-- below). Note that unlike 'traceV', only /positive/ boundary+-- points are considered, /i.e./ boundary points corresponding to a+-- positive scalar multiple of the direction vector. This is+-- intuitively the \"usual\" behavior of a raytracer, which only+-- considers intersections \"in front of\" the camera. Compare the+-- second example diagram below with the second example shown for+-- 'traceV'.+--+-- <<diagrams/src_Diagrams_Core_Trace_rayTraceVEx.svg#diagram=rayTraceVEx&width=600>>+rayTraceV :: (n ~ N a, Traced a, Num n)+ => Point (V a) n -> V a n -> a -> Maybe (V a n)+rayTraceV p v a = case getSortedList $ op Trace (getRayTrace a) p v of+ (s:_) -> Just (s *^ v)+ [] -> Nothing++-- > rayTraceVEx = mkTraceDiasABC def { drawV = True, sFilter = take 1 . filter (>0) }+++-- | Compute the boundary point on an object which is closest to the+-- given base point in the given direction, or @Nothing@ if there is+-- no such boundary point. Note that unlike 'traceP', only /positive/+-- boundary points are considered, /i.e./ boundary points+-- corresponding to a positive scalar multiple of the direction+-- vector. This is intuitively the \"usual\" behavior of a raytracer,+-- which only considers intersection points \"in front of\" the+-- camera.+--+-- <<diagrams/src_Diagrams_Core_Trace_rayTracePEx.svg#diagram=rayTracePEx&width=600>>+rayTraceP :: (n ~ N a, Traced a, Num n)+ => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)+rayTraceP p v a = (p .+^) <$> rayTraceV p v a++-- > rayTracePEx = mkTraceDiasABC def { sFilter = take 1 . filter (>0) }+++-- | Like 'rayTraceV', but computes a vector to the \"largest\"+-- boundary point instead of the smallest. Considers only+-- /positive/ boundary points.+--+-- <<diagrams/src_Diagrams_Core_Trace_maxRayTraceVEx.svg#diagram=maxRayTraceVEx&width=600>>+maxRayTraceV :: (n ~ N a, Traced a, Num n)+ => Point (V a) n -> V a n -> a -> Maybe (V a n)+maxRayTraceV p v a =+ case getSortedList $ op Trace (getRayTrace a) p v of+ [] -> Nothing+ xs -> Just (last xs *^ v)++-- > maxRayTraceVEx = mkTraceDiasABC def { drawV = True, sFilter = dropAllBut1 . filter (>0) }+++-- | Like 'rayTraceP', but computes the \"largest\" boundary point+-- instead of the smallest. Considers only /positive/ boundary+-- points.+--+-- <<diagrams/src_Diagrams_Core_Trace_maxRayTracePEx.svg#diagram=maxRayTracePEx&width=600>>+maxRayTraceP :: (n ~ N a, Traced a, Num n)+ => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)+maxRayTraceP p v a = (p .+^) <$> maxRayTraceV p v a++-- > maxRayTracePEx = mkTraceDiasABC def { sFilter = dropAllBut1 . filter (>0) }+++------------------------------------------------------------+-- Drawing trace diagrams+------------------------------------------------------------++-- > import Data.Default.Class+-- > import Control.Lens ((^.))+-- > import Data.Maybe (fromMaybe)+-- >+-- > thingyT :: Trail V2 Double+-- > thingyT =+-- > fromOffsets+-- > [ 3 *^ unitX, 3 *^ unitY, 2 *^ unit_X, 1 *^ unit_Y+-- > , 1 *^ unitX, 1 *^ unit_Y, 2 *^ unit_X, 1 *^ unit_Y ]+-- >+-- > thingy = strokeTrail thingyT+-- >+-- > data TraceDiaOpts+-- > = TDO { traceShape :: Diagram B+-- > , basePt :: P2 Double+-- > , dirV :: V2 Double+-- > , sFilter :: [Double] -> [Double]+-- > , drawV :: Bool+-- > }+-- >+-- > instance Default TraceDiaOpts where+-- > def = TDO { traceShape = thingy+-- > , basePt = pointB+-- > , dirV = 0.3 ^& 0.5+-- > , sFilter = id+-- > , drawV = False+-- > }+-- >+-- > pointA = 1 ^& (-1.5)+-- > pointB = 1 ^& 1.2+-- > pointC = 2.5 ^& 3.5+-- >+-- > dot' = circle 0.05 # lw none+-- >+-- > mkTraceDia :: TraceDiaOpts -> Diagram B+-- > mkTraceDia tdo = mconcat+-- > [ mconcat $ map (place (dot' # fc red)) pts+-- > , if drawV tdo then resultArrow else mempty+-- > , arrowAt (basePt tdo) (dirV tdo) # lc blue+-- > , dot' # fc blue # moveTo (basePt tdo)+-- > , traceLine (basePt tdo) maxPosPt+-- > , traceLine (basePt tdo) minNegPt+-- > , traceShape tdo+-- > ]+-- > # centerXY # pad 1.1+-- > where+-- > ss = sFilter tdo . getSortedList+-- > $ appTrace (traceShape tdo ^. trace) (basePt tdo) (dirV tdo)+-- > pts = map mkPt ss+-- > mkPt s = basePt tdo .+^ (s *^ dirV tdo)+-- > maxPosPt = (mkPt <$>) . safeLast $ filter (>0) ss+-- > minNegPt = (mkPt <$>) . safeHead $ filter (<0) ss+-- > minPt = (mkPt <$>) . safeHead $ ss+-- > resultArrow = fromMaybe mempty (arrowBetween (basePt tdo) <$> minPt)+-- > # lc green+-- >+-- > safeLast [] = Nothing+-- > safeLast xs = Just $ last xs+-- > safeHead [] = Nothing+-- > safeHead (x:_) = Just x+-- > dropAllBut1 [] = []+-- > dropAllBut1 xs = [last xs]+-- >+-- > traceLine _ Nothing = mempty+-- > traceLine p (Just q) = (p ~~ q) # dashingG [0.1,0.1] 0+-- >+-- > mkTraceDias :: [TraceDiaOpts] -> Diagram B+-- > mkTraceDias = hcat' (with & sep .~ 1) . map mkTraceDia+-- >+-- > mkTraceDiasABC :: TraceDiaOpts -> Diagram B+-- > mkTraceDiasABC tdo = mkTraceDias (map (\p -> tdo { basePt = p }) [pointA, pointB, pointC])
+ src/Diagrams/Core/Transform.hs view
@@ -0,0 +1,427 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}++-- |+-- Module : Diagrams.Core.Transform+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- "Diagrams" defines the core library of primitives+-- forming the basis of an embedded domain-specific language for+-- describing and rendering diagrams.+--+-- The @Transform@ module defines generic transformations+-- parameterized by any vector space.+--+-----------------------------------------------------------------------------++module Diagrams.Core.Transform+ (+ -- * Transformations++ -- ** Invertible linear transformations+ (:-:)(..), (<->), linv, lapp++ -- ** General transformations+ , Transformation(..)+ , inv, transp, transl+ , dropTransl+ , apply+ , papply+ , fromLinear+ , fromOrthogonal+ , fromSymmetric+ , basis+ , dimension+ , onBasis+ , listRep+ , matrixRep+ , matrixHomRep+ , determinant+ , isReflection+ , avgScale+ , eye++ -- * The Transformable class++ , HasLinearMap+ , HasBasis+ , Transformable(..)++ -- * Translational invariance++ , TransInv(TransInv)++ -- * Vector space independent transformations+ -- | Most transformations are specific to a particular vector+ -- space, but a few can be defined generically over any+ -- vector space.++ , translation, translate+ , scaling, scale++ ) where++import Control.Lens (Rewrapped, Traversable, Wrapped (..),+ iso, (&), (.~))+import qualified Data.Map as M+import Data.Semigroup+import qualified Data.Set as S++import Data.Monoid.Action+import Data.Monoid.Deletable++import Linear.Affine+import Linear.Vector++import Data.Foldable (Foldable, toList)+import Data.Functor.Rep++import Diagrams.Core.HasOrigin+import Diagrams.Core.Measure+import Diagrams.Core.Points ()+import Diagrams.Core.V++------------------------------------------------------------+-- Transformations ---------------------------------------+------------------------------------------------------------++-------------------------------------------------------+-- Invertible linear transformations ----------------+-------------------------------------------------------++-- | @(v1 :-: v2)@ is a linear map paired with its inverse.+data (:-:) u v = (u -> v) :-: (v -> u)+infixr 7 :-:++-- | Create an invertible linear map from two functions which are+-- assumed to be linear inverses.+(<->) :: (u -> v) -> (v -> u) -> (u :-: v)+f <-> g = f :-: g++instance Semigroup (a :-: a) where+ (f :-: f') <> (g :-: g') = f . g :-: g' . f'++-- | Invertible linear maps from a vector space to itself form a+-- monoid under composition.+instance Monoid (v :-: v) where+ mempty = id :-: id+ mappend = (<>)++-- | Invert a linear map.+linv :: (u :-: v) -> (v :-: u)+linv (f :-: g) = g :-: f++-- | Apply a linear map to a vector.+lapp :: (u :-: v) -> u -> v+lapp (f :-: _) = f++--------------------------------------------------+-- Affine transformations ----------------------+--------------------------------------------------++-- | General (affine) transformations, represented by an invertible+-- linear map, its /transpose/, and a vector representing a+-- translation component.+--+-- By the /transpose/ of a linear map we mean simply the linear map+-- corresponding to the transpose of the map's matrix+-- representation. For example, any scale is its own transpose,+-- since scales are represented by matrices with zeros everywhere+-- except the diagonal. The transpose of a rotation is the same as+-- its inverse.+--+-- The reason we need to keep track of transposes is because it+-- turns out that when transforming a shape according to some linear+-- map L, the shape's /normal vectors/ transform according to L's+-- inverse transpose. (For a more detailed explanation and proof,+-- see <https://wiki.haskell.org/Diagrams/Dev/Transformations>.)+-- This is exactly what we need when transforming bounding+-- functions, which are defined in terms of /perpendicular/+-- (i.e. normal) hyperplanes.+--+-- For more general, non-invertible transformations, see+-- @Diagrams.Deform@ (in @diagrams-lib@).++data Transformation v n = Transformation (v n :-: v n) (v n :-: v n) (v n)++type instance V (Transformation v n) = v+type instance N (Transformation v n) = n++-- | Identity matrix.+eye :: (HasBasis v, Num n) => v (v n)+eye = tabulate $ \(E e) -> zero & e .~ 1++-- | Invert a transformation.+inv :: (Functor v, Num n) => Transformation v n -> Transformation v n+inv (Transformation t t' v) = Transformation (linv t) (linv t')+ (negated (lapp (linv t) v))++-- | Get the transpose of a transformation (ignoring the translation+-- component).+transp :: Transformation v n -> (v n :-: v n)+transp (Transformation _ t' _) = t'++-- | Get the translational component of a transformation.+transl :: Transformation v n -> v n+transl (Transformation _ _ v) = v++-- | Drop the translational component of a transformation, leaving only+-- the linear part.+dropTransl :: (Additive v, Num n) => Transformation v n -> Transformation v n+dropTransl (Transformation a a' _) = Transformation a a' zero++-- | Transformations are closed under composition; @t1 <> t2@ is the+-- transformation which performs first @t2@, then @t1@.+instance (Additive v, Num n) => Semigroup (Transformation v n) where+ Transformation t1 t1' v1 <> Transformation t2 t2' v2+ = Transformation (t1 <> t2) (t2' <> t1') (v1 ^+^ lapp t1 v2)++instance (Additive v, Num n) => Monoid (Transformation v n) where+ mempty = Transformation mempty mempty zero+ mappend = (<>)++-- | Transformations can act on transformable things.+instance (Transformable a, V a ~ v, N a ~ n) => Action (Transformation v n) a where+ act = transform++-- | Apply a transformation to a vector. Note that any translational+-- component of the transformation will not affect the vector, since+-- vectors are invariant under translation.+apply :: Transformation v n -> v n -> v n+apply (Transformation (t :-: _) _ _) = t++-- | Apply a transformation to a point.+papply :: (Additive v, Num n) => Transformation v n -> Point v n -> Point v n+papply (Transformation t _ v) (P p) = P $ lapp t p ^+^ v++-- | Create a general affine transformation from an invertible linear+-- transformation and its transpose. The translational component is+-- assumed to be zero.+fromLinear :: (Additive v, Num n) => (v n :-: v n) -> (v n :-: v n) -> Transformation v n+fromLinear l1 l2 = Transformation l1 l2 zero++-- | An orthogonal linear map is one whose inverse is also its transpose.+fromOrthogonal :: (Additive v, Num n) => (v n :-: v n) -> Transformation v n+fromOrthogonal t = fromLinear t (linv t)++-- | A symmetric linear map is one whose transpose is equal to its self.+fromSymmetric :: (Additive v, Num n) => (v n :-: v n) -> Transformation v n+fromSymmetric t = fromLinear t t++-- | Get the dimension of an object whose vector space is an instance of+-- @HasLinearMap@, e.g. transformations, paths, diagrams, etc.+dimension :: forall a. (Additive (V a), Traversable (V a)) => a -> Int+dimension _ = length (basis :: [V a Int])++-- | Get the matrix equivalent of the linear transform,+-- (as a list of columns) and the translation vector. This+-- is mostly useful for implementing backends.+onBasis :: (Additive v, Traversable v, Num n) => Transformation v n -> ([v n], v n)+onBasis (Transformation (f :-: _) _ t) = (map f basis, t)++-- Remove the nth element from a list+remove :: Int -> [a] -> [a]+remove n xs | n < 0 = xs+remove n xs = ys ++ drop 1 zs+ where+ (ys, zs) = splitAt n xs++-- Minor matrix of cofactor C(i,j)+minor :: Int -> Int -> [[a]] -> [[a]]+minor i j xs = remove j $ map (remove i) xs++-- The determinant of a square matrix represented as a nonempty list of lists+-- representing column vectors, that is [column].+det :: Num a => [[a]] -> a+det [] = error "determinant of empty matrix!"+det [a : _] = a+det m@(c1 : _) = sum [(-1) ^ i * (c1 !! i) * det (minor i 0 m) | i <- [0 .. (n - 1)]]+ where+ n = length m++-- | Convert a vector v to a list of scalars.+listRep :: Foldable v => v n -> [n]+listRep = toList++-- | Convert the linear part of a `Transformation` to a matrix+-- representation as a list of column vectors which are also lists.+matrixRep :: (Additive v, Traversable v, Num n) => Transformation v n -> [[n]]+matrixRep (Transformation (f :-: _) _ _) = map (toList . f) basis++-- | Convert a `Transformation v` to a homogeneous matrix representation.+-- The final list is the translation.+-- The representation leaves off the last row of the matrix as it is+-- always [0,0, ... 1] and this representation is the defacto standard+-- for backends.+matrixHomRep :: (Additive v, Traversable v, Num n) => Transformation v n -> [[n]]+matrixHomRep t = mr ++ [toList tl]+ where+ mr = matrixRep t+ tl = transl t++-- | The determinant of (the linear part of) a `Transformation`.+determinant :: (Additive v, Traversable v, Num n) => Transformation v n -> n+determinant = det . matrixRep++-- | Determine whether a `Transformation` includes a reflection+-- component, that is, whether it reverses orientation.+isReflection :: (Additive v, Traversable v, Num n, Ord n) => Transformation v n -> Bool+isReflection = (<0) . determinant++-- | Compute the \"average\" amount of scaling performed by a+-- transformation. Satisfies the properties+--+-- @+-- avgScale (scaling k) == k+-- avgScale (t1 <> t2) == avgScale t1 * avgScale t2+-- @+--+avgScale :: (Additive v, Traversable v, Floating n) => Transformation v n -> n+avgScale t = (abs . determinant) t ** (recip . fromIntegral . dimension) t++{-++avgScale is computed as the nth root of the positive determinant.+This works because the determinant is the factor by which a transformation+scales area/volume. See http://en.wikipedia.org/wiki/Determinant.++Proofs for the specified properties:++1. |det (scaling k)|^(1/n) = (k^n)^(1/n) = k+2. |det t1|^(1/n) * |det t2|^(1/n)+ = (|det t1| * |det t2|)^(1/n)+ = |det t1 * det t2|^(1/n)+ = |det (t1 <> t2)|^(1/n)++-}++------------------------------------------------------------+-- The Transformable class -------------------------------+------------------------------------------------------------++-- | 'HasLinearMap' is a constraint synonym, just to+-- help shorten some of the ridiculously long constraint sets.+type HasLinearMap v = (HasBasis v, Traversable v)++-- | An 'Additive' vector space whose representation is made up of basis elements.+type HasBasis v = (Additive v, Representable v, Rep v ~ E v)++-- | Type class for things @t@ which can be transformed.+class Transformable t where++ -- | Apply a transformation to an object.+ transform :: Transformation (V t) (N t) -> t -> t++instance (Additive v, Num n) => Transformable (Transformation v n) where+ transform t1 t2 = t1 <> t2++instance (Additive v, Num n) => HasOrigin (Transformation v n) where+ moveOriginTo p = translate (origin .-. p)++instance (Transformable t, Transformable s, V t ~ V s, N t ~ N s)+ => Transformable (t, s) where+ transform t (x,y) = ( transform t x+ , transform t y+ )++instance (Transformable t, Transformable s, Transformable u, V s ~ V t, N s ~ N t, V s ~ V u, N s ~ N u)+ => Transformable (t,s,u) where+ transform t (x,y,z) = ( transform t x+ , transform t y+ , transform t z+ )++-- Transform functions by conjugation. That is, reverse-transform argument and+-- forward-transform result. Intuition: If someone shrinks you, you see your+-- environment enlarged. If you rotate right, you see your environment+-- rotating left. Etc. This technique was used extensively in Pan for modular+-- construction of image filters. Works well for curried functions, since all+-- arguments get inversely transformed.++instance ( V t ~ v, N t ~ n, V t ~ V s, N t ~ N s, Functor v, Num n+ , Transformable t, Transformable s)+ => Transformable (s -> t) where+ transform tr f = transform tr . f . transform (inv tr)++instance Transformable t => Transformable [t] where+ transform = map . transform++instance (Transformable t, Ord t) => Transformable (S.Set t) where+ transform = S.map . transform++instance Transformable t => Transformable (M.Map k t) where+ transform = M.map . transform++instance (Additive v, Num n) => Transformable (Point v n) where+ transform = papply++instance Transformable m => Transformable (Deletable m) where+ transform = fmap . transform++------------------------------------------------------------+-- Translational invariance ------------------------------+------------------------------------------------------------++-- | @TransInv@ is a wrapper which makes a transformable type+-- translationally invariant; the translational component of+-- transformations will no longer affect things wrapped in+-- @TransInv@.+newtype TransInv t = TransInv t+ deriving (Eq, Ord, Show, Semigroup, Monoid)++instance Wrapped (TransInv t) where+ type Unwrapped (TransInv t) = t+ _Wrapped' = iso (\(TransInv t) -> t) TransInv++instance Rewrapped (TransInv t) (TransInv t')++type instance V (TransInv t) = V t+type instance N (TransInv t) = N t++instance HasOrigin (TransInv t) where+ moveOriginTo = const id++instance (Num (N t), Additive (V t), Transformable t) => Transformable (TransInv t) where+ transform (Transformation a a' _) (TransInv t)+ = TransInv (transform (Transformation a a' zero) t)++instance (InSpace v n t, Transformable t, HasLinearMap v, Floating n)+ => Transformable (Measured n t) where+ transform t = scaleLocal n . fmap (transform t')+ where+ t' = t <> scaling (1 / avgScale t)+ n = avgScale t++------------------------------------------------------------+-- Generic transformations -------------------------------+------------------------------------------------------------++-- | Create a translation.+translation :: v n -> Transformation v n+translation = Transformation mempty mempty++-- | Translate by a vector.+translate :: (Transformable t) => Vn t -> t -> t+translate = transform . translation++-- | Create a uniform scaling transformation.+scaling :: (Additive v, Fractional n) => n -> Transformation v n+scaling s = fromSymmetric lin+ where lin = (s *^) <-> (^/ s)++-- | Scale uniformly in every dimension by the given scalar.+scale :: (InSpace v n a, Eq n, Fractional n, Transformable a)+ => n -> a -> a+scale 0 = error "scale by zero! Halp!" -- XXX what should be done here?+scale s = transform $ scaling s+
+ src/Diagrams/Core/Types.hs view
@@ -0,0 +1,1010 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}+-- We have some orphan Action instances here, but since Action is a multi-param+-- class there is really no better place to put them.++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.Types+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- The core library of primitives forming the basis of an embedded+-- domain-specific language for describing and rendering diagrams.+--+-- "Diagrams.Core.Types" defines types and classes for+-- primitives, diagrams, and backends.+--+-----------------------------------------------------------------------------++{- ~~~~ Note [breaking up Types module]++ Although it's not as bad as it used to be, this module has a lot of+ stuff in it, and it might seem a good idea in principle to break it up+ into smaller modules. However, it's not as easy as it sounds: everything+ in this module cyclically depends on everything else.+-}++module Diagrams.Core.Types+ (+ -- * Diagrams++ -- ** Annotations++ -- *** Static annotations+ Annotation(Href, OpacityGroup, KeyVal)+ , applyAnnotation, href, opacityGroup, groupOpacity, keyVal++ -- *** Dynamic (monoidal) annotations+ , UpAnnots, DownAnnots, transfToAnnot, transfFromAnnot++ -- ** Basic type definitions+ , QDiaLeaf(..), withQDiaLeaf+ , QDiagram(..), Diagram++ -- * Operations on diagrams+ -- ** Creating diagrams+ , mkQD, mkQD', pointDiagram++ -- ** Extracting information+ , envelope, trace, subMap, names, query++ -- ** Combining diagrams++ -- | For many more ways of combining diagrams, see+ -- "Diagrams.Combinators" and "Diagrams.TwoD.Combinators"+ -- from the diagrams-lib package.++ , atop++ -- ** Modifying diagrams+ -- *** Names+ , nameSub+ , lookupName+ , withName+ , withNameAll+ , withNames+ , localize++ -- *** Other+ , setEnvelope+ , setTrace++ -- * Subdiagrams++ , Subdiagram(..), mkSubdiagram+ , getSub, rawSub+ , location+ , subPoint++ -- * Subdiagram maps++ , SubMap(..)++ , fromNames, rememberAs, lookupSub++ -- * Primtives+ -- $prim++ , Prim(..)+ , _Prim++ -- * Backends++ , Backend(..)+ , DTree+ , DNode(..)++ , RTree+ , RNode(..)+ , _RStyle+ , _RAnnot+ , _RPrim+ , _REmpty++ -- ** Null backend++ , NullBackend, D++ -- ** Number classes+ , TypeableFloat++ -- * Renderable++ , Renderable(..)++ ) where++import Control.Arrow (first, second, (***))+import Control.Lens (Lens', Prism', Rewrapped,+ Wrapped (..), iso, lens, over,+ prism', view, (^.), _Wrapped,+ _Wrapping)+import Control.Monad (mplus)+import Data.Kind (Type)+import Data.List (isSuffixOf)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, listToMaybe)+import Data.Semigroup+import qualified Data.Traversable as T+import Data.Tree+import Data.Typeable++import Data.Monoid.Action+import Data.Monoid.Coproduct+import Data.Monoid.Deletable+import Data.Monoid.MList+import Data.Monoid.WithSemigroup+import qualified Data.Tree.DUAL as D++import Diagrams.Core.Envelope+import Diagrams.Core.HasOrigin+import Diagrams.Core.Juxtapose+import Diagrams.Core.Names+import Diagrams.Core.Points+import Diagrams.Core.Query+import Diagrams.Core.Style+import Diagrams.Core.Trace+import Diagrams.Core.Transform+import Diagrams.Core.V++import Linear.Affine+import Linear.Metric+import Linear.Vector++-- XXX TODO: add lots of actual diagrams to illustrate the+-- documentation! Haddock supports \<\<inline image urls\>\>.++-- | Constraint for numeric types that are 'RealFloat' and 'Typeable',+-- which often occur together. This is used to shorten shorten type+-- constraint contexts.+type TypeableFloat n = (Typeable n, RealFloat n)++------------------------------------------------------------+-- Diagrams ----------------------------------------------+------------------------------------------------------------++-- | Monoidal annotations which travel up the diagram tree, /i.e./ which+-- are aggregated from component diagrams to the whole:+--+-- * envelopes (see "Diagrams.Core.Envelope").+-- The envelopes are \"deletable\" meaning that at any point we can+-- throw away the existing envelope and replace it with a new one;+-- sometimes we want to consider a diagram as having a different+-- envelope unrelated to its \"natural\" envelope.+--+-- * traces (see "Diagrams.Core.Trace"), also+-- deletable.+--+-- * name/subdiagram associations (see "Diagrams.Core.Names")+--+-- * query functions (see "Diagrams.Core.Query")+type UpAnnots b v n m = Deletable (Envelope v n)+ ::: Deletable (Trace v n)+ ::: Deletable (SubMap b v n m)+ ::: Query v n m+ ::: ()++-- | Monoidal annotations which travel down the diagram tree,+-- /i.e./ which accumulate along each path to a leaf (and which can+-- act on the upwards-travelling annotations):+--+-- * styles (see "Diagrams.Core.Style")+--+-- * names (see "Diagrams.Core.Names")+type DownAnnots v n = (Transformation v n :+: Style v n)+ ::: Name+ ::: ()++ -- Note that we have to put the transformations and styles together+ -- using a coproduct because the transformations can act on the+ -- styles.++-- | Inject a transformation into a default downwards annotation+-- value.+transfToAnnot :: Transformation v n -> DownAnnots v n+transfToAnnot+ = inj+ . (inL :: Transformation v n -> Transformation v n :+: Style v n)++-- | Extract the (total) transformation from a downwards annotation+-- value.+transfFromAnnot :: (Additive v, Num n) => DownAnnots v n -> Transformation v n+transfFromAnnot = maybe mempty killR . fst++-- | A leaf in a 'QDiagram' tree is either a 'Prim', or a \"delayed\"+-- @QDiagram@ which expands to a real @QDiagram@ once it learns the+-- \"final context\" in which it will be rendered. For example, in+-- order to decide how to draw an arrow, we must know the precise+-- transformation applied to it (since the arrow head and tail are+-- scale-invariant).+data QDiaLeaf b v n m+ = PrimLeaf (Prim b v n)+ | DelayedLeaf (DownAnnots v n -> n -> n -> QDiagram b v n m)+ -- ^ The @QDiagram@ produced by a @DelayedLeaf@ function /must/+ -- already apply any transformation in the given+ -- @DownAnnots@ (that is, the transformation will not+ -- be applied by the context).+ deriving Functor++withQDiaLeaf :: (Prim b v n -> r)+ -> ((DownAnnots v n -> n -> n -> QDiagram b v n m) -> r)+ -> QDiaLeaf b v n m -> r+withQDiaLeaf f _ (PrimLeaf p) = f p+withQDiaLeaf _ g (DelayedLeaf dgn) = g dgn++-- | Static annotations which can be placed at a particular node of a+-- diagram tree.+data Annotation+ = Href String -- ^ Hyperlink+ | OpacityGroup Double+ | KeyVal (String, String)+ deriving Show++-- | Apply a static annotation at the root of a diagram.+applyAnnotation+ :: (Metric v, OrderedField n, Semigroup m)+ => Annotation -> QDiagram b v n m -> QDiagram b v n m+applyAnnotation an (QD dt) = QD (D.annot an dt)++-- | Make a diagram into a hyperlink. Note that only some backends+-- will honor hyperlink annotations.+href :: (Metric v, OrderedField n, Semigroup m)+ => String -> QDiagram b v n m -> QDiagram b v n m+href = applyAnnotation . Href++-- | Change the transparency of a 'Diagram' as a group.+opacityGroup, groupOpacity :: (Metric v, OrderedField n, Semigroup m)+ => Double -> QDiagram b v n m -> QDiagram b v n m+opacityGroup = applyAnnotation . OpacityGroup+groupOpacity = applyAnnotation . OpacityGroup++-- | Apply a general Key-Value annotation+keyVal :: (Metric v, OrderedField n, Semigroup m)+ => (String, String) -> QDiagram b v n m -> QDiagram b v n m+keyVal = applyAnnotation . KeyVal++-- | The fundamental diagram type. The type variables are as follows:+--+-- * @b@ represents the backend, such as @SVG@ or @Cairo@. Note+-- that each backend also exports a type synonym @B@ for itself,+-- so the type variable @b@ may also typically be instantiated by+-- @B@, meaning \"use whatever backend is in scope\".+--+-- * @v@ represents the vector space of the diagram. Typical+-- instantiations include @V2@ (for a two-dimensional diagram) or+-- @V3@ (for a three-dimensional diagram).+--+-- * @n@ represents the numerical field the diagram uses. Typically+-- this will be a concrete numeric type like @Double@.+--+-- * @m@ is the monoidal type of \"query annotations\": each point+-- in the diagram has a value of type @m@ associated to it, and+-- these values are combined according to the 'Monoid' instance+-- for @m@. Most often, @m@ is simply instantiated to 'Any',+-- associating a simple @Bool@ value to each point indicating+-- whether the point is inside the diagram; 'Diagram' is a synonym+-- for @QDiagram@ with @m@ thus instantiated to @Any@.+--+-- Diagrams can be combined via their 'Monoid' instance, transformed+-- via their 'Transformable' instance, and assigned attributes via+-- their 'HasStyle' instance.+--+-- Note that the @Q@ in @QDiagram@ stands for \"Queriable\", as+-- distinguished from 'Diagram', where @m@ is fixed to @Any@. This+-- is not really a very good name, but it's probably not worth+-- changing it at this point.+newtype QDiagram b v n m+ = QD (D.DUALTree (DownAnnots v n) (UpAnnots b v n m) Annotation (QDiaLeaf b v n m))+#if __GLASGOW_HASKELL__ >= 707+ deriving Typeable+#else++instance forall b v. (Typeable b, Typeable1 v) => Typeable2 (QDiagram b v) where+ typeOf2 _ = mkTyConApp (mkTyCon3 "diagrams-core" "Diagrams.Core.Types" "QDiagram") [] `mkAppTy`+ typeOf (undefined :: b) `mkAppTy`+ typeOf1 (undefined :: v n)+#endif++instance Wrapped (QDiagram b v n m) where+ type Unwrapped (QDiagram b v n m) =+ D.DUALTree (DownAnnots v n) (UpAnnots b v n m) Annotation (QDiaLeaf b v n m)+ _Wrapped' = iso (\(QD d) -> d) QD++instance Rewrapped (QDiagram b v n m) (QDiagram b' v' n' m')++type instance V (QDiagram b v n m) = v+type instance N (QDiagram b v n m) = n++-- | @Diagram b@ is a synonym for @'QDiagram' b (V b) (N b) 'Any'@. That is,+-- the default sort of diagram is one where querying at a point+-- simply tells you whether the diagram contains that point or not.+-- Transforming a default diagram into one with a more interesting+-- query can be done via the 'Functor' instance of @'QDiagram' b v n@ or+-- the 'value' function.+type Diagram b = QDiagram b (V b) (N b) Any++-- | Create a \"point diagram\", which has no content, no trace, an+-- empty query, and a point envelope.+pointDiagram :: (Metric v, Fractional n)+ => Point v n -> QDiagram b v n m+pointDiagram p = QD $ D.leafU (inj . toDeletable $ pointEnvelope p)++-- | A useful variant of 'getU' which projects out a certain+-- component.+getU' :: (Monoid u', u :>: u') => D.DUALTree d u a l -> u'+getU' = maybe mempty (maybe mempty id . get) . D.getU++-- | Lens onto the 'Envelope' of a 'QDiagram'.+envelope :: (OrderedField n, Metric v, Monoid' m)+ => Lens' (QDiagram b v n m) (Envelope v n)+envelope = lens (unDelete . getU' . view _Wrapped') (flip setEnvelope)++-- | Replace the envelope of a diagram.+setEnvelope :: forall b v n m. ( OrderedField n, Metric v+ , Monoid' m)+ => Envelope v n -> QDiagram b v n m -> QDiagram b v n m+setEnvelope e =+ over _Wrapped' ( D.applyUpre (inj . toDeletable $ e)+ . D.applyUpre (inj (deleteL :: Deletable (Envelope v n)))+ . D.applyUpost (inj (deleteR :: Deletable (Envelope v n)))+ )++-- | Lens onto the 'Trace' of a 'QDiagram'.+trace :: (Metric v, OrderedField n, Semigroup m) =>+ Lens' (QDiagram b v n m) (Trace v n)+trace = lens (unDelete . getU' . view _Wrapped') (flip setTrace)++-- | Replace the trace of a diagram.+setTrace :: forall b v n m. ( OrderedField n, Metric v+ , Semigroup m)+ => Trace v n -> QDiagram b v n m -> QDiagram b v n m+setTrace t = over _Wrapped' ( D.applyUpre (inj . toDeletable $ t)+ . D.applyUpre (inj (deleteL :: Deletable (Trace v n)))+ . D.applyUpost (inj (deleteR :: Deletable (Trace v n)))+ )++-- | Lens onto the 'SubMap' of a 'QDiagram' (/i.e./ an association from+-- names to subdiagrams).+subMap :: (Metric v, Semigroup m, OrderedField n)+ => Lens' (QDiagram b v n m) (SubMap b v n m)+subMap = lens (unDelete . getU' . view _Wrapped') (flip setMap)+ where+ setMap :: (Metric v, Semigroup m, OrderedField n) =>+ SubMap b v n m -> QDiagram b v n m -> QDiagram b v n m+ setMap m = over _Wrapped' ( D.applyUpre . inj . toDeletable $ m)++-- | Get a list of names of subdiagrams and their locations.+names :: (Metric v, Semigroup m, OrderedField n)+ => QDiagram b v n m -> [(Name, [Point v n])]+names = (map . second . map) location . M.assocs . view (subMap . _Wrapped')++-- | Attach an atomic name to a certain subdiagram, computed from the+-- given diagram /with the mapping from name to subdiagram+-- included/. The upshot of this knot-tying is that if @d' = d #+-- named x@, then @lookupName x d' == Just d'@ (instead of @Just+-- d@).+nameSub :: (IsName nm , Metric v, OrderedField n, Semigroup m)+ => (QDiagram b v n m -> Subdiagram b v n m) -> nm -> QDiagram b v n m -> QDiagram b v n m+nameSub s n d = d'+ where d' = over _Wrapped' (D.applyUpre . inj . toDeletable $ fromNames [(n,s d')]) d++-- | Lookup the most recent diagram associated with (some+-- qualification of) the given name.+lookupName :: (IsName nm, Metric v, Semigroup m, OrderedField n)+ => nm -> QDiagram b v n m -> Maybe (Subdiagram b v n m)+lookupName n d = lookupSub (toName n) (d^.subMap) >>= listToMaybe++-- | Given a name and a diagram transformation indexed by a+-- subdiagram, perform the transformation using the most recent+-- subdiagram associated with (some qualification of) the name,+-- or perform the identity transformation if the name does not exist.+withName :: (IsName nm, Metric v+ , Semigroup m, OrderedField n)+ => nm -> (Subdiagram b v n m -> QDiagram b v n m -> QDiagram b v n m)+ -> QDiagram b v n m -> QDiagram b v n m+withName n f d = maybe id f (lookupName n d) d++-- | Given a name and a diagram transformation indexed by a list of+-- subdiagrams, perform the transformation using the+-- collection of all such subdiagrams associated with (some+-- qualification of) the given name.+withNameAll :: (IsName nm, Metric v+ , Semigroup m, OrderedField n)+ => nm -> ([Subdiagram b v n m] -> QDiagram b v n m -> QDiagram b v n m)+ -> QDiagram b v n m -> QDiagram b v n m+withNameAll n f d = f (fromMaybe [] (lookupSub (toName n) (d^.subMap))) d++-- | Given a list of names and a diagram transformation indexed by a+-- list of subdiagrams, perform the transformation using the+-- list of most recent subdiagrams associated with (some qualification+-- of) each name. Do nothing (the identity transformation) if any+-- of the names do not exist.+withNames :: (IsName nm, Metric v+ , Semigroup m, OrderedField n)+ => [nm] -> ([Subdiagram b v n m] -> QDiagram b v n m -> QDiagram b v n m)+ -> QDiagram b v n m -> QDiagram b v n m+withNames ns f d = maybe id f ns' d+ where+ nd = d^.subMap+ ns' = T.sequence (map ((listToMaybe=<<) . ($ nd) . lookupSub . toName) ns)++-- | \"Localize\" a diagram by hiding all the names, so they are no+-- longer visible to the outside.+localize :: forall b v n m. (Metric v, OrderedField n, Semigroup m)+ => QDiagram b v n m -> QDiagram b v n m+localize = over _Wrapped' ( D.applyUpre (inj (deleteL :: Deletable (SubMap b v n m)))+ . D.applyUpost (inj (deleteR :: Deletable (SubMap b v n m)))+ )++-- | Get the query function associated with a diagram.+query :: Monoid m => QDiagram b v n m -> Query v n m+query = getU' . view _Wrapped'++-- | Create a diagram from a single primitive, along with an envelope,+-- trace, subdiagram map, and query function.+mkQD :: Prim b v n -> Envelope v n -> Trace v n -> SubMap b v n m -> Query v n m+ -> QDiagram b v n m+mkQD p = mkQD' (PrimLeaf p)++-- | Create a diagram from a generic QDiaLeaf, along with an envelope,+-- trace, subdiagram map, and query function.+mkQD' :: QDiaLeaf b v n m -> Envelope v n -> Trace v n -> SubMap b v n m -> Query v n m+ -> QDiagram b v n m+mkQD' l e t n q+ = QD $ D.leaf (toDeletable e *: toDeletable t *: toDeletable n *: q *: ()) l++------------------------------------------------------------+-- Instances+------------------------------------------------------------++---- Monoid++-- | Diagrams form a monoid since each of their components do: the+-- empty diagram has no primitives, an empty envelope, an empty+-- trace, no named subdiagrams, and a constantly empty query+-- function.+--+-- Diagrams compose by aligning their respective local origins. The+-- new diagram has all the primitives and all the names from the two+-- diagrams combined, and query functions are combined pointwise.+-- The first diagram goes on top of the second. \"On top of\"+-- probably only makes sense in vector spaces of dimension lower+-- than 3, but in theory it could make sense for, say, 3-dimensional+-- diagrams when viewed by 4-dimensional beings.+instance (Metric v, OrderedField n, Semigroup m)+ => Monoid (QDiagram b v n m) where+ mempty = QD D.empty+ mappend = (<>)++instance (Metric v, OrderedField n, Semigroup m)+ => Semigroup (QDiagram b v n m) where+ (QD d1) <> (QD d2) = QD (d2 <> d1)+ -- swap order so that primitives of d2 come first, i.e. will be+ -- rendered first, i.e. will be on the bottom.++-- | A convenient synonym for 'mappend' on diagrams, designed to be+-- used infix (to help remember which diagram goes on top of which+-- when combining them, namely, the first on top of the second).+atop :: (OrderedField n, Metric v, Semigroup m)+ => QDiagram b v n m -> QDiagram b v n m -> QDiagram b v n m+atop = (<>)++infixl 6 `atop`++---- Functor++instance Functor (QDiagram b v n) where+ fmap f = over (_Wrapping QD)+ ( (D.mapU . second . second)+ ( (first . fmap . fmap . fmap) f+ . (second . first . fmap . fmap) f+ )+ . (fmap . fmap) f+ )++---- Applicative++-- XXX what to do with this?+-- A diagram with queries of result type @(a -> b)@ can be \"applied\"+-- to a diagram with queries of result type @a@, resulting in a+-- combined diagram with queries of result type @b@. In particular,+-- all components of the two diagrams are combined as in the+-- @Monoid@ instance, except the queries which are combined via+-- @(<*>)@.++-- instance (Backend b v n, Num n, Ord n)+-- => Applicative (QDiagram b v n) where+-- pure a = Diagram mempty mempty mempty (Query $ const a)+--+-- (Diagram ps1 bs1 ns1 smp1) <*> (Diagram ps2 bs2 ns2 smp2)+-- = Diagram (ps1 <> ps2) (bs1 <> bs2) (ns1 <> ns2) (smp1 <*> smp2)++---- HasStyle++instance (Metric v, OrderedField n, Semigroup m)+ => HasStyle (QDiagram b v n m) where+ applyStyle = over _Wrapped' . D.applyD . inj+ . (inR :: Style v n -> Transformation v n :+: Style v n)++---- Juxtaposable++instance (Metric v, OrderedField n, Monoid' m)+ => Juxtaposable (QDiagram b v n m) where+ juxtapose = juxtaposeDefault++---- Enveloped++instance (Metric v, OrderedField n, Monoid' m)+ => Enveloped (QDiagram b v n m) where+ getEnvelope = view envelope++---- Traced++instance (Metric v, OrderedField n, Semigroup m)+ => Traced (QDiagram b v n m) where+ getTrace = view trace++---- HasOrigin++-- | Every diagram has an intrinsic \"local origin\" which is the+-- basis for all combining operations.+instance (Metric v, OrderedField n, Semigroup m)+ => HasOrigin (QDiagram b v n m) where+ moveOriginTo = translate . (origin .-.)++---- Transformable++-- | Diagrams can be transformed by transforming each of their+-- components appropriately.+instance (OrderedField n, Metric v, Semigroup m)+ => Transformable (QDiagram b v n m) where+ transform = over _Wrapped' . D.applyD . transfToAnnot++---- Qualifiable++-- | Diagrams can be qualified so that all their named points can+-- now be referred to using the qualification prefix.+instance (Metric v, OrderedField n, Semigroup m)+ => Qualifiable (QDiagram b v n m) where+ (.>>) = over _Wrapped' . D.applyD . inj . toName+++------------------------------------------------------------+-- Subdiagrams+------------------------------------------------------------++-- | A @Subdiagram@ represents a diagram embedded within the context+-- of a larger diagram. Essentially, it consists of a diagram+-- paired with any accumulated information from the larger context+-- (transformations, attributes, etc.).++data Subdiagram b v n m = Subdiagram (QDiagram b v n m) (DownAnnots v n)++type instance V (Subdiagram b v n m) = v+type instance N (Subdiagram b v n m) = n++-- | Turn a diagram into a subdiagram with no accumulated context.+mkSubdiagram :: QDiagram b v n m -> Subdiagram b v n m+mkSubdiagram d = Subdiagram d empty++-- | Create a \"point subdiagram\", that is, a 'pointDiagram' (with no+-- content and a point envelope) treated as a subdiagram with local+-- origin at the given point. Note this is not the same as+-- @mkSubdiagram . pointDiagram@, which would result in a subdiagram+-- with local origin at the parent origin, rather than at the given+-- point.+subPoint :: (Metric v, OrderedField n)+ => Point v n -> Subdiagram b v n m+subPoint p = Subdiagram+ (pointDiagram origin)+ (transfToAnnot $ translation (p .-. origin))++instance Functor (Subdiagram b v n) where+ fmap f (Subdiagram d a) = Subdiagram (fmap f d) a++instance (OrderedField n, Metric v, Monoid' m)+ => Enveloped (Subdiagram b v n m) where+ getEnvelope (Subdiagram d a) = transform (transfFromAnnot a) $ getEnvelope d++instance (OrderedField n, Metric v, Semigroup m)+ => Traced (Subdiagram b v n m) where+ getTrace (Subdiagram d a) = transform (transfFromAnnot a) $ getTrace d++instance (Metric v, OrderedField n)+ => HasOrigin (Subdiagram b v n m) where+ moveOriginTo = translate . (origin .-.)++instance Transformable (Subdiagram b v n m) where+ transform t (Subdiagram d a) = Subdiagram d (transfToAnnot t <> a)++-- | Get the location of a subdiagram; that is, the location of its+-- local origin /with respect to/ the vector space of its parent+-- diagram. In other words, the point where its local origin+-- \"ended up\".+location :: (Additive v, Num n) => Subdiagram b v n m -> Point v n+location (Subdiagram _ a) = transform (transfFromAnnot a) origin++-- | Turn a subdiagram into a normal diagram, including the enclosing+-- context. Concretely, a subdiagram is a pair of (1) a diagram and+-- (2) a \"context\" consisting of an extra transformation and+-- attributes. @getSub@ simply applies the transformation and+-- attributes to the diagram to get the corresponding \"top-level\"+-- diagram.+getSub :: (Metric v, OrderedField n, Semigroup m)+ => Subdiagram b v n m -> QDiagram b v n m+getSub (Subdiagram d a) = over _Wrapped' (D.applyD a) d++-- | Extract the \"raw\" content of a subdiagram, by throwing away the+-- context.+rawSub :: Subdiagram b v n m -> QDiagram b v n m+rawSub (Subdiagram d _) = d++------------------------------------------------------------+-- Subdiagram maps ---------------------------------------+------------------------------------------------------------++-- | A 'SubMap' is a map associating names to subdiagrams. There can+-- be multiple associations for any given name.+newtype SubMap b v n m = SubMap (M.Map Name [Subdiagram b v n m])+ -- See Note [SubMap Set vs list]++instance Wrapped (SubMap b v n m) where+ type Unwrapped (SubMap b v n m) = M.Map Name [Subdiagram b v n m]+ _Wrapped' = iso (\(SubMap m) -> m) SubMap++instance Rewrapped (SubMap b v n m) (SubMap b' v' n' m')++-- ~~~~ [SubMap Set vs list]+-- In some sense it would be nicer to use+-- Sets instead of a list, but then we would have to put Ord+-- constraints on v everywhere. =P++type instance V (SubMap b v n m) = v+type instance N (SubMap b v n m) = n++instance Functor (SubMap b v n) where+ fmap = over _Wrapped . fmap . map . fmap++instance Semigroup (SubMap b v n m) where+ SubMap s1 <> SubMap s2 = SubMap $ M.unionWith (++) s1 s2++-- | 'SubMap's form a monoid with the empty map as the identity, and+-- map union as the binary operation. No information is ever lost:+-- if two maps have the same name in their domain, the resulting map+-- will associate that name to the concatenation of the information+-- associated with that name.+instance Monoid (SubMap b v n m) where+ mempty = SubMap M.empty+ mappend = (<>)++instance (OrderedField n, Metric v)+ => HasOrigin (SubMap b v n m) where+ moveOriginTo = over _Wrapped' . moveOriginTo++instance Transformable (SubMap b v n m) where+ transform = over _Wrapped' . transform++-- | 'SubMap's are qualifiable: if @ns@ is a 'SubMap', then @a |>+-- ns@ is the same 'SubMap' except with every name qualified by+-- @a@.+instance Qualifiable (SubMap b v n m) where+ a .>> (SubMap m) = SubMap $ M.mapKeys (a .>>) m++-- | Construct a 'SubMap' from a list of associations between names+-- and subdiagrams.+fromNames :: IsName a => [(a, Subdiagram b v n m)] -> SubMap b v n m+fromNames = SubMap . M.fromListWith (++) . map (toName *** (:[]))++-- | Add a name/diagram association to a submap.+rememberAs :: IsName a => a -> QDiagram b v n m -> SubMap b v n m -> SubMap b v n m+rememberAs n b = over _Wrapped' $ M.insertWith (++) (toName n) [mkSubdiagram b]++-- | A name acts on a name map by qualifying every name in it.+instance Action Name (SubMap b v n m) where+ act = (.>>)++instance Action Name a => Action Name (Deletable a) where+ act n (Deletable l a r) = Deletable l (act n a) r++-- Names do not act on other things.++instance Action Name (Query v n m)+instance Action Name (Envelope v n)+instance Action Name (Trace v n)++-- | Look for the given name in a name map, returning a list of+-- subdiagrams associated with that name. If no names match the+-- given name exactly, return all the subdiagrams associated with+-- names of which the given name is a suffix.+lookupSub :: IsName nm => nm -> SubMap b v n m -> Maybe [Subdiagram b v n m]+lookupSub a (SubMap m)+ = M.lookup n m `mplus`+ (flattenNames . filter ((n `nameSuffixOf`) . fst) . M.assocs $ m)+ where (Name n1) `nameSuffixOf` (Name n2) = n1 `isSuffixOf` n2+ flattenNames [] = Nothing+ flattenNames xs = Just . concatMap snd $ xs+ n = toName a++------------------------------------------------------------+-- Primitives --------------------------------------------+------------------------------------------------------------++-- $prim+-- Ultimately, every diagram is essentially a tree whose leaves are /primitives/,+-- basic building blocks which can be rendered by backends. However,+-- not every backend must be able to render every type of primitive;+-- the collection of primitives a given backend knows how to render is+-- determined by instances of 'Renderable'.++-- | A value of type @Prim b v n@ is an opaque (existentially quantified)+-- primitive which backend @b@ knows how to render in vector space @v@.+data Prim b v n where+ Prim :: (Transformable p, Typeable p, Renderable p b) => p -> Prim b (V p) (N p)++_Prim :: (Typeable p, Renderable p b) => Prism' (Prim b (V p) (N p)) p+_Prim = prism' Prim (\(Prim p) -> cast p)++type instance V (Prim b v n) = v+type instance N (Prim b v n) = n++-- | The 'Transformable' instance for 'Prim' just pushes calls to+-- 'transform' down through the 'Prim' constructor.+instance Transformable (Prim b v n) where+ transform t (Prim p) = Prim (transform t p)++-- | The 'Renderable' instance for 'Prim' just pushes calls to+-- 'render' down through the 'Prim' constructor.+instance Renderable (Prim b v n) b where+ render b (Prim p) = render b p++------------------------------------------------------------+-- Backends -----------------------------------------------+------------------------------------------------------------++-- | A 'DTree' is a raw tree representation of a 'QDiagram', with all+-- the @u@-annotations removed. It is used as an intermediate type+-- by diagrams-core; backends should not need to make use of it.+-- Instead, backends can make use of 'RTree', which 'DTree' gets+-- compiled and optimized to.+type DTree b v n a = Tree (DNode b v n a)++data DNode b v n a = DStyle (Style v n)+ | DTransform (Transformation v n)+ | DAnnot a+ | DDelay+ -- ^ @DDelay@ marks a point where a delayed subtree+ -- was expanded. Such subtrees already take all+ -- non-frozen transforms above them into account,+ -- so when later processing the tree, upon+ -- encountering a @DDelay@ node we must drop any+ -- accumulated non-frozen transformation.+ | DPrim (Prim b v n)+ | DEmpty++-- | An 'RTree' is a compiled and optimized representation of a+-- 'QDiagram', which can be used by backends. They have the+-- following invariant which backends may rely upon:+--+-- * @RPrim@ nodes never have any children.+type RTree b v n a = Tree (RNode b v n a)++data RNode b v n a = RStyle (Style v n) -- ^ A style node.+ | RAnnot a+ | RPrim (Prim b v n) -- ^ A primitive.+ | REmpty++-- | Prism onto a style of an 'RNode'.+_RStyle :: Prism' (RNode b v n a) (Style v n)+_RStyle = prism' RStyle $ \n -> case n of RStyle s -> Just s; _ -> Nothing++-- | Prism onto an annotation of an 'RNode'.+_RAnnot :: Prism' (RNode b v n a) a+_RAnnot = prism' RAnnot $ \n -> case n of RAnnot a -> Just a; _ -> Nothing++-- | Prism onto a 'Prim' of an 'RNode'.+_RPrim :: Prism' (RNode b v n a) (Prim b v n)+_RPrim = prism' RPrim $ \n -> case n of RPrim p -> Just p; _ -> Nothing++-- | Prism onto an empty 'RNode'.+_REmpty :: Prism' (RNode b v n a) ()+_REmpty = prism' (const REmpty) $ \n -> case n of REmpty -> Just (); _ -> Nothing++-- | Abstract diagrams are rendered to particular formats by+-- /backends/. Each backend/vector space combination must be an+-- instance of the 'Backend' class.+--+-- A minimal complete definition consists of 'Render', 'Result',+-- 'Options', and 'renderRTree'. However, most backends will want to+-- implement 'adjustDia' as well; the default definition does+-- nothing. Some useful standard definitions are provided in the+-- @Diagrams.TwoD.Adjust@ module from the @diagrams-lib@ package.+class Backend b v n where++ -- | An intermediate representation used for rendering primitives.+ -- (Typically, this will be some sort of monad, but it need not+ -- be.) The 'Renderable' class guarantees that a backend will be+ -- able to convert primitives into this type; how these rendered+ -- primitives are combined into an ultimate 'Result' is completely+ -- up to the backend.+ data Render b v n :: Type++ -- | The result of running/interpreting a rendering operation.+ type Result b v n :: Type++ -- | Backend-specific rendering options.+ data Options b v n :: Type++ -- | 'adjustDia' allows the backend to make adjustments to the final+ -- diagram (e.g. to adjust the size based on the options) before+ -- rendering it. It returns a modified options record, the+ -- transformation applied to the diagram (which can be used to+ -- convert attributes whose value is @Measure@, or transform+ -- /e.g./ screen coordinates back into local diagram coordinates),+ -- and the adjusted diagram itself.+ --+ -- See the diagrams-lib package (particularly the+ -- @Diagrams.TwoD.Adjust@ module) for some useful implementations.+ adjustDia :: (Additive v, Monoid' m, Num n) => b -> Options b v n+ -> QDiagram b v n m -> (Options b v n, Transformation v n, QDiagram b v n m)+ adjustDia _ o d = (o,mempty,d)++ -- | Given some options, take a representation of a diagram as a+ -- tree and render it. The 'RTree' has already been simplified+ -- and has all measurements converted to @Output@ units.+ renderRTree :: b -> Options b v n -> RTree b v n Annotation -> Result b v n++ -- See Note [backend token]++-- | The @D@ type is provided for convenience in situations where you+-- must give a diagram a concrete, monomorphic type, but don't care+-- which one. Such situations arise when you pass a diagram to a+-- function which is polymorphic in its input but monomorphic in its+-- output, such as 'width', 'height', 'phantom', or 'names'. Such+-- functions compute some property of the diagram, or use it to+-- accomplish some other purpose, but do not result in the diagram+-- being rendered. If the diagram does not have a monomorphic type,+-- GHC complains that it cannot determine the diagram's type.+--+-- For example, here is the error we get if we try to compute the+-- width of an image (this example requires @diagrams-lib@):+--+-- @+-- ghci> width (image (uncheckedImageRef \"foo.png\" 200 200))+-- \<interactive\>:11:8:+-- No instance for (Renderable (DImage n0 External) b0)+-- arising from a use of `image'+-- The type variables `n0', `b0' are ambiguous+-- Possible fix: add a type signature that fixes these type variable(s)+-- Note: there is a potential instance available:+-- instance Fractional n => Renderable (DImage n a) NullBackend+-- -- Defined in `Diagrams.TwoD.Image'+-- Possible fix:+-- add an instance declaration for+-- (Renderable (DImage n0 External) b0)+-- In the first argument of `width', namely+-- `(image (uncheckedImageRef \"foo.png\" 200 200))'+-- In the expression:+-- width (image (uncheckedImageRef \"foo.png\" 200 200))+-- In an equation for `it':+-- it = width (image (uncheckedImageRef \"foo.png\" 200 200))+-- @+--+-- GHC complains that there is no instance for @Renderable (DImage n0+-- External) b0@; what is really going on is that it does not have enough+-- information to decide what backend to use (hence the+-- uninstantiated @n0@ and @b0@). This is annoying because /we/ know that the+-- choice of backend cannot possibly affect the width of the image+-- (it's 200! it's right there in the code!); /but/ there is no way+-- for GHC to know that.+--+-- The solution is to annotate the call to 'image' with the type+-- @'D' 'V2' 'Double'@, like so:+--+-- @+-- ghci> width (image (uncheckedImageRef \"foo.png\" 200 200) :: D V2 Double)+-- 200.00000000000006+-- @+--+-- (It turns out the width wasn't 200 after all...)+--+-- As another example, here is the error we get if we try to compute+-- the width of a radius-1 circle:+--+-- @+-- ghci> width (circle 1)+-- \<interactive\>:12:1:+-- Couldn't match expected type `V2' with actual type `V a0'+-- The type variable `a0' is ambiguous+-- Possible fix: add a type signature that fixes these type variable(s)+-- In the expression: width (circle 1)+-- In an equation for `it': it = width (circle 1)+-- @+--+-- There's even more ambiguity here. Whereas 'image' always returns+-- a 'Diagram', the 'circle' function can produce any 'TrailLike'+-- type, and the 'width' function can consume any 'Enveloped' type,+-- so GHC has no idea what type to pick to go in the middle.+-- However, the solution is the same:+--+-- @+-- ghci> width (circle 1 :: D V2 Double)+-- 1.9999999999999998+-- @++type D v n = QDiagram NullBackend v n Any+++-- | A null backend which does no actual rendering. It is provided+-- mainly for convenience in situations where you must give a+-- diagram a concrete, monomorphic type, but don't actually care+-- which one. See 'D' for more explanation and examples.+--+-- It is courteous, when defining a new primitive @P@, to make an instance+--+-- > instance Renderable P NullBackend where+-- > render _ _ = mempty+--+-- This ensures that the trick with 'D' annotations can be used for+-- diagrams containing your primitive.+data NullBackend+ deriving Typeable++-- Note: we can't make a once-and-for-all instance+--+-- > instance Renderable a NullBackend where+-- > render _ _ = mempty+--+-- because it overlaps with the Renderable instance for NullPrim.++instance Semigroup (Render NullBackend v n) where+ _ <> _ = NullBackendRender++instance Monoid (Render NullBackend v n) where+ mempty = NullBackendRender+#if !MIN_VERSION_base(4,11,0)+ mappend = (<>)+#endif++instance Backend NullBackend v n where+ data Render NullBackend v n = NullBackendRender+ type Result NullBackend v n = ()+ data Options NullBackend v n++ renderRTree _ _ _ = ()++-- | The Renderable type class connects backends to primitives which+-- they know how to render.+class Transformable t => Renderable t b where+ render :: b -> t -> Render b (V t) (N t)+ -- ^ Given a token representing the backend and a+ -- transformable object, render it in the appropriate rendering+ -- context.++ -- See Note [backend token]++{-+~~~~ Note [backend token]++A bunch of methods here take a "backend token" as an argument. The+backend token is expected to carry no actual information; it is solely+to help out the type system. The problem is that all these methods+return some associated type applied to b (e.g. Render b) and unifying+them with something else will never work, since type families are not+necessarily injective.+-}
+ src/Diagrams/Core/V.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++-----------------------------------------------------------------------------+-- |+-- Module : Diagrams.Core.V+-- Copyright : (c) 2011-2015 diagrams-core team (see LICENSE)+-- License : BSD-style (see LICENSE)+-- Maintainer : diagrams-discuss@googlegroups.com+--+-- Type family for identifying associated vector spaces.+--+-----------------------------------------------------------------------------++module Diagrams.Core.V+ ( V , N , Vn+ , InSpace, SameSpace+ ) where++import Data.Kind (Type)+import Data.Map+import Data.Monoid.Coproduct+import Data.Monoid.Deletable+import Data.Monoid.Split+import Data.Semigroup+import Data.Set++import Linear.Vector++------------------------------------------------------------+-- Vector spaces -------------------------------------------+------------------------------------------------------------++-- | Many sorts of objects have an associated vector space in which+-- they \"live\". The type function @V@ maps from object types to+-- the associated vector space. The resulting vector space has kind @* -> *@+-- which means it takes another value (a number) and returns a concrete+-- vector. For example 'V2' has kind @* -> *@ and @V2 Double@ is a vector.+type family V a :: Type -> Type++-- Note, to use these instances one often needs a constraint of the form+-- V a ~ V b, etc.+type instance V (a,b) = V a+type instance V (a,b,c) = V a++type instance V (a -> b) = V b+type instance V [a] = V a+type instance V (Maybe a) = V a+type instance V (Set a) = V a+type instance V (Map k a) = V a++type instance V (Deletable m) = V m+type instance V (Split m) = V m+type instance V (m :+: n) = V m++-- | The numerical field for the object, the number type used for calculations.+type family N a :: Type++type instance N (a,b) = N a+type instance N (a,b,c) = N a++type instance N (a -> b) = N b+type instance N [a] = N a+type instance N (Maybe a) = N a+type instance N (Set a) = N a+type instance N (Map k a) = N a++type instance N (Deletable m) = N m+type instance N (Split m) = N m+type instance N (m :+: n) = N m++-- | Convenient type alias to retrieve the vector type associated with an+-- object's vector space. This is usually used as @Vn a ~ v n@ where @v@ is+-- the vector space and @n@ is the numerical field.+type Vn a = V a (N a)++-- | @InSpace v n a@ means the type @a@ belongs to the vector space @v n@,+-- where @v@ is 'Additive' and @n@ is a 'Num'.+type InSpace v n a = (V a ~ v, N a ~ n, Additive v, Num n)++-- | @SameSpace a b@ means the types @a@ and @b@ belong to the same+-- vector space @v n@.+type SameSpace a b = (V a ~ V b, N a ~ N b)+
− src/Graphics/Rendering/Diagrams.hs
@@ -1,153 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ The core library of primitives forming the basis of an embedded--- domain-specific language for describing and rendering diagrams.--- Normal users of the diagrams library should almost never need to--- import anything from this package directly; instead, import modules--- (especially "Diagrams.Prelude") from the diagrams-lib package,--- which re-exports most things of value to users.------ For most library code needing access to core internals, it should--- be sufficient to import this module, which simply re-exports useful--- functionality from other modules in the core library. Library--- writers needing finer-grained access or functionality may--- occasionally find it useful to directly import one of the--- constituent core modules.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams- ( -- * Associated vector spaces-- V-- -- * Points-- , Point, origin, (*.)-- -- * Vectors-- , withLength-- -- * Transformations-- -- ** Invertible linear transformations- , (:-:), (<->), linv, lapp-- -- ** General transformations- , Transformation- , inv, transp, transl- , apply- , papply- , fromLinear-- -- ** Some specific transformations- , translation, translate, moveTo, place- , scaling, scale-- -- ** The Transformable class-- , Transformable(..)-- -- ** Translational invariance-- , TransInv(..)-- -- * Names-- , AName- , Name, IsName(..)- , Qualifiable(..), (.>)- , NameMap- , fromNames, fromNamesB- , rememberAs-- , lookupN-- -- * Attributes and styles-- , AttributeClass- , Attribute, mkAttr, mkTAttr, unwrapAttr-- , Style, HasStyle(..)- , getAttr, combineAttr- , applyAttr, applyTAttr-- -- * Envelopes-- , Envelope- , inEnvelope, appEnvelope, onEnvelope, mkEnvelope- , Enveloped(..)- , envelopeV, envelopeP, boundaryFrom- , diameter, radius-- , LocatedEnvelope(..)- , location, locateEnvelope-- -- * Things with local origins-- , HasOrigin(..), moveOriginBy-- -- * Juxtaposable things-- , Juxtaposable(..), juxtaposeDefault-- -- * Queries-- , Query(..)-- -- * Primtives-- , Prim(..), nullPrim-- -- * Diagrams-- , QDiagram, mkQD, Diagram- , prims- , envelope, names, query, sample- , value, resetValue, clearValue-- , named, namePoint- , withName- , withNameAll- , withNames-- , freeze, setEnvelope-- , atop-- -- * Backends-- , Backend(..)- , MultiBackend(..)- , Renderable(..)-- -- ** The null backend-- , NullBackend, D-- -- * Convenience classes-- , HasLinearMap- , OrderedField- , Monoid'-- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Util-import Graphics.Rendering.Diagrams.Transform-import Graphics.Rendering.Diagrams.Envelope-import Graphics.Rendering.Diagrams.HasOrigin-import Graphics.Rendering.Diagrams.Juxtapose-import Graphics.Rendering.Diagrams.Query-import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.Names-import Graphics.Rendering.Diagrams.Style-import Graphics.Rendering.Diagrams.Core-import Graphics.Rendering.Diagrams.Monoids (Monoid')
− src/Graphics/Rendering/Diagrams/Core.hs
@@ -1,632 +0,0 @@-{-# LANGUAGE FlexibleContexts- , FlexibleInstances- , TypeFamilies- , MultiParamTypeClasses- , GADTs- , ExistentialQuantification- , ScopedTypeVariables- , GeneralizedNewtypeDeriving- , DeriveDataTypeable- , TypeOperators- , OverlappingInstances- , UndecidableInstances- , TupleSections- , EmptyDataDecls- #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Core--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ The core library of primitives forming the basis of an embedded--- domain-specific language for describing and rendering diagrams.------ "Graphics.Rendering.Diagrams.Core" defines types and classes for--- primitives, diagrams, and backends.-----------------------------------------------------------------------------------{- ~~~~ Note [breaking up Core module]-- Although it's not as bad as it used to be, this module has a lot of- stuff in it, and it might seem a good idea in principle to break it up- into smaller modules. However, it's not as easy as it sounds: everything- in this module cyclically depends on everything else.--}--module Graphics.Rendering.Diagrams.Core- (- -- * Diagrams-- -- ** Annotations- UpAnnots, DownAnnots- , QDiagram(..), mkQD, Diagram-- -- * Operations on diagrams- -- ** Extracting information- , prims- , envelope, names, query, sample- , value, resetValue, clearValue-- -- ** Combining diagrams-- -- | For many more ways of combining diagrams, see- -- "Diagrams.Combinators" from the diagrams-lib package.-- , atop-- -- ** Modifying diagrams- -- *** Names- , named- , namePoint- , withName- , withNameAll- , withNames-- -- *** Other- , freeze- , setEnvelope-- -- * Primtives- -- $prim-- , Prim(..), nullPrim-- -- * Backends-- , Backend(..)- , MultiBackend(..)-- -- ** Null backend-- , NullBackend, D-- -- * Renderable-- , Renderable(..)-- ) where--import Graphics.Rendering.Diagrams.Monoids-import Graphics.Rendering.Diagrams.MList-import Graphics.Rendering.Diagrams.UDTree--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Query-import Graphics.Rendering.Diagrams.Transform-import Graphics.Rendering.Diagrams.Envelope-import Graphics.Rendering.Diagrams.HasOrigin-import Graphics.Rendering.Diagrams.Juxtapose-import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.Names-import Graphics.Rendering.Diagrams.Style--import Data.VectorSpace-import Data.AffineSpace ((.-.))--import Data.Maybe (listToMaybe, fromMaybe)-import Data.Semigroup-import qualified Data.Traversable as T-import Control.Arrow (second)-import Control.Applicative ((<$>), (<*>))--import Control.Newtype--import Data.Typeable---- XXX TODO: add lots of actual diagrams to illustrate the--- documentation! Haddock supports \<\<inline image urls\>\>.----------------------------------------------------------------- Diagrams --------------------------------------------------------------------------------------------------------------- | Monoidal annotations which travel up the diagram tree, i.e. which--- are aggregated from component diagrams to the whole:------ * envelopes (see "Graphics.Rendering.Diagrams.Envelope").--- The envelopes are \"deletable\" meaning that at any point we can--- throw away the existing envelope and replace it with a new one;--- sometimes we want to consider a diagram as having a different--- envelope unrelated to its \"natural\" envelope.------ * name/point associations (see "Graphics.Rendering.Diagrams.Names")------ * query functions (see "Graphics.Rendering.Diagrams.Query")-type UpAnnots v m = Deletable (Envelope v) ::: NameMap v ::: Query v m ::: Nil---- | Monoidal annotations which travel down the diagram tree,--- i.e. which accumulate along each path to a leaf (and which can--- act on the upwards-travelling annotations):------ * transformations (split at the innermost freeze): see--- "Graphics.Rendering.Diagrams.Transform"------ * styles (see "Graphics.Rendering.Diagrams.Style")------ * names (see "Graphics.Rendering.Diagrams.Names")-type DownAnnots v = (Split (Transformation v) :+: Style v) ::: AM [] Name ::: Nil---- | The fundamental diagram type is represented by trees of--- primitives with various monoidal annotations. The @Q@ in--- @QDiagram@ stands for \"Queriable\", as distinguished from--- 'Diagram', a synonym for @QDiagram@ with the query type--- specialized to 'Any'.-newtype QDiagram b v m- = QD { unQD :: UDTree (UpAnnots v m) (DownAnnots v) (Prim b v) }- deriving (Typeable)--instance Newtype (QDiagram b v m)- (UDTree (UpAnnots v m) (DownAnnots v) (Prim b v)) where- pack = QD- unpack = unQD--type instance V (QDiagram b v m) = v---- | The default sort of diagram is one where querying at a point--- simply tells you whether that point is occupied or not.--- Transforming a default diagram into one with a more interesting--- query can be done via the 'Functor' instance of @'QDiagram' b@.-type Diagram b v = QDiagram b v Any---- | Extract a list of primitives from a diagram, together with their--- associated transformations and styles.-prims :: (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m)- => QDiagram b v m -> [(Prim b v, (Split (Transformation v), Style v))]-prims = (map . second) (untangle . fst . toTuple) . flatten . unQD---- | Get the envelope of a diagram.-envelope :: (OrderedField (Scalar v), InnerSpace v, HasLinearMap v)- => QDiagram b v m -> Envelope v-envelope = unDelete . getU' . unQD---- | Replace the envelope of a diagram.-setEnvelope :: forall b v m. (OrderedField (Scalar v), InnerSpace v, HasLinearMap v, Monoid' m)- => Envelope v -> QDiagram b v m -> QDiagram b v m-setEnvelope b = over QD ( applyUpre (inj . toDeletable $ b)- . applyUpre (inj (deleteL :: Deletable (Envelope v)))- . applyUpost (inj (deleteR :: Deletable (Envelope v)))- )---- | Get the name map of a diagram.-names :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v)- => QDiagram b v m -> NameMap v-names = getU' . unQD---- | Attach an atomic name to (the local origin of) a diagram.-named :: forall v b n m.- ( IsName n- , HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid' m)- => n -> QDiagram b v m -> QDiagram b v m-named = namePoint (locateEnvelope <$> const origin <*> envelope)---- | Attach an atomic name to a certain point and envelope, computed--- from the given diagram.-namePoint :: forall v b n m.- ( IsName n- , HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid' m)- => (QDiagram b v m -> LocatedEnvelope v) -> n -> QDiagram b v m -> QDiagram b v m-namePoint p n d = over QD (applyUpre . inj $ fromNamesB [(n,p d)]) d---- | Given a name and a diagram transformation indexed by a located--- envelope, perform the transformation using the most recent--- located envelope associated with (some qualification of) the--- name, or perform the identity transformation if the name does not--- exist.-withName :: ( IsName n, AdditiveGroup (Scalar v), Floating (Scalar v)- , InnerSpace v, HasLinearMap v)- => n -> (LocatedEnvelope v -> QDiagram b v m -> QDiagram b v m)- -> QDiagram b v m -> QDiagram b v m-withName n f d = maybe id f (lookupN (toName n) (names d) >>= listToMaybe) d---- | Given a name and a diagram transformation indexed by a list of--- located envelopes, perform the transformation using the--- collection of all such located envelopes associated with (some--- qualification of) the given name.-withNameAll :: ( IsName n, AdditiveGroup (Scalar v), Floating (Scalar v)- , InnerSpace v, HasLinearMap v)- => n -> ([LocatedEnvelope v] -> QDiagram b v m -> QDiagram b v m)- -> QDiagram b v m -> QDiagram b v m-withNameAll n f d = f (fromMaybe [] (lookupN (toName n) (names d))) d---- | Given a list of names and a diagram transformation indexed by a--- list of located envelopes, perform the transformation using the--- list of most recent envelopes associated with (some qualification--- of) each name. Do nothing (the identity transformation) if any--- of the names do not exist.-withNames :: ( IsName n, AdditiveGroup (Scalar v), Floating (Scalar v)- , InnerSpace v, HasLinearMap v)- => [n] -> ([LocatedEnvelope v] -> QDiagram b v m -> QDiagram b v m)- -> QDiagram b v m -> QDiagram b v m-withNames ns f d = maybe id f (T.sequence (map ((listToMaybe=<<) . ($nd) . lookupN . toName) ns)) d- where nd = names d---- | Get the query function associated with a diagram.-query :: (HasLinearMap v, Monoid m) => QDiagram b v m -> Query v m-query = getU' . unQD---- | Sample a diagram's query function at a given point.-sample :: (HasLinearMap v, Monoid m) => QDiagram b v m -> Point v -> m-sample = runQuery . query---- | Set the query value for 'True' points in a diagram (/i.e./ points--- "inside" the diagram); 'False' points will be set to 'mempty'.-value :: Monoid m => m -> QDiagram b v Any -> QDiagram b v m-value m = fmap fromAny- where fromAny (Any True) = m- fromAny (Any False) = mempty---- | Reset the query values of a diagram to True/False: any values--- equal to 'mempty' are set to 'False'; any other values are set to--- 'True'.-resetValue :: (Eq m, Monoid m) => QDiagram b v m -> QDiagram b v Any-resetValue = fmap toAny- where toAny m | m == mempty = Any False- | otherwise = Any True---- | Set all the query values of a diagram to 'False'.-clearValue :: QDiagram b v m -> QDiagram b v Any-clearValue = fmap (const (Any False))---- | Create a diagram from a single primitive, along with an envelope,--- name map, and query function.-mkQD :: Prim b v -> Envelope v -> NameMap v -> Query v m -> QDiagram b v m-mkQD p b n a = QD $ leaf (toDeletable b ::: n ::: a ::: Nil) p----------------------------------------------------------------- Instances------------------------------------------------------------------- Monoid---- | Diagrams form a monoid since each of their components do: the--- empty diagram has no primitives, an empty envelope, no named--- points, and a constantly empty query function.------ Diagrams compose by aligning their respective local origins. The--- new diagram has all the primitives and all the names from the two--- diagrams combined, and query functions are combined pointwise.--- The first diagram goes on top of the second. \"On top of\"--- probably only makes sense in vector spaces of dimension lower--- than 3, but in theory it could make sense for, say, 3-dimensional--- diagrams when viewed by 4-dimensional beings.-instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid' m)- => Monoid (QDiagram b v m) where- mempty = QD mempty- (QD d1) `mappend` (QD d2) = QD (d2 `mappend` d1)- -- swap order so that primitives of d2 come first, i.e. will be- -- rendered first, i.e. will be on the bottom.--instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid' m)- => Semigroup (QDiagram b v m) where- (<>) = mappend---- | A convenient synonym for 'mappend' on diagrams, designed to be--- used infix (to help remember which diagram goes on top of which--- when combining them, namely, the first on top of the second).-atop :: (HasLinearMap v, OrderedField (Scalar v), InnerSpace v, Monoid' m)- => QDiagram b v m -> QDiagram b v m -> QDiagram b v m-atop = mappend--infixl 6 `atop`------ Functor---- This is a bit ugly, but it will have to do for now...-instance Functor (QDiagram b v) where- fmap f = over QD (mapU g)- where g (b ::: n ::: a ::: Nil) = b ::: n ::: fmap f a ::: Nil- g _ = error "impossible case in Functor (QDiagram b v) instance (g)"------ Applicative---- XXX what to do with this?--- A diagram with queries of result type @(a -> b)@ can be \"applied\"--- to a diagram with queries of result type @a@, resulting in a--- combined diagram with queries of result type @b@. In particular,--- all components of the two diagrams are combined as in the--- @Monoid@ instance, except the queries which are combined via--- @(<*>)@.---- instance (Backend b v, s ~ Scalar v, AdditiveGroup s, Ord s)--- => Applicative (QDiagram b v) where--- pure a = Diagram mempty mempty mempty (Query $ const a)---- (Diagram ps1 bs1 ns1 smp1) <*> (Diagram ps2 bs2 ns2 smp2)--- = Diagram (ps1 <> ps2) (bs1 <> bs2) (ns1 <> ns2) (smp1 <*> smp2)------ HasStyle--instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m)- => HasStyle (QDiagram b v m) where- applyStyle = over QD . applyD . inj- . (inR :: Style v -> Split (Transformation v) :+: Style v)---- | By default, diagram attributes are not affected by--- transformations. This means, for example, that @lw 0.01 circle@--- and @scale 2 (lw 0.01 circle)@ will be drawn with lines of the--- /same/ width, and @scaleY 3 circle@ will be an ellipse drawn with--- a uniform line. Once a diagram is frozen, however,--- transformations do affect attributes, so, for example, @scale 2--- (freeze (lw 0.01 circle))@ will be drawn with a line twice as--- thick as @lw 0.01 circle@, and @scaleY 3 (freeze circle)@ will be--- drawn with a \"stretched\", variable-width line.------ Another way of thinking about it is that pre-@freeze@, we are--- transforming the \"abstract idea\" of a diagram, and the--- transformed version is then drawn; when doing a @freeze@, we--- produce a concrete drawing of the diagram, and it is this visual--- representation itself which is acted upon by subsequent--- transformations.-freeze :: forall v b m. (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m)- => QDiagram b v m -> QDiagram b v m-freeze = over QD . applyD . inj- . (inL :: Split (Transformation v) -> Split (Transformation v) :+: Style v)- $ split------ Juxtaposable--instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid' m)- => Juxtaposable (QDiagram b v m) where- juxtapose = juxtaposeDefault------ Enveloped--instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v) )- => Enveloped (QDiagram b v m) where- getEnvelope = envelope------ HasOrigin---- | Every diagram has an intrinsic \"local origin\" which is the--- basis for all combining operations.-instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid' m)- => HasOrigin (QDiagram b v m) where-- moveOriginTo = translate . (origin .-.)------ Transformable---- | Diagrams can be transformed by transforming each of their--- components appropriately.-instance (HasLinearMap v, OrderedField (Scalar v), InnerSpace v, Monoid' m)- => Transformable (QDiagram b v m) where- transform = over QD . applyD . inj- . (inL :: Split (Transformation v) -> Split (Transformation v) :+: Style v)- . M------ Qualifiable---- | Diagrams can be qualified so that all their named points can--- now be referred to using the qualification prefix.-instance (HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m)- => Qualifiable (QDiagram b v m) where- (|>) = over QD . applyD . inj . AM . (:[]) . toName------------------------------------------------------------------ Primitives ------------------------------------------------------------------------------------------------------------- $prim--- Ultimately, every diagram is essentially a collection of--- /primitives/, basic building blocks which can be rendered by--- backends. However, not every backend must be able to render every--- type of primitive; the collection of primitives a given backend--- knows how to render is determined by instances of 'Renderable'.---- | A value of type @Prim b v@ is an opaque (existentially quantified)--- primitive which backend @b@ knows how to render in vector space @v@.-data Prim b v where- Prim :: Renderable t b => t -> Prim b (V t)--type instance V (Prim b v) = v---- | The 'Transformable' instance for 'Prim' just pushes calls to--- 'transform' down through the 'Prim' constructor.-instance HasLinearMap v => Transformable (Prim b v) where- transform v (Prim p) = Prim (transform v p)---- | The 'Renderable' instance for 'Prim' just pushes calls to--- 'render' down through the 'Prim' constructor.-instance HasLinearMap v => Renderable (Prim b v) b where- render b (Prim p) = render b p---- | The null primitive.-data NullPrim v = NullPrim--type instance (V (NullPrim v)) = v--instance HasLinearMap v => Transformable (NullPrim v) where- transform _ _ = NullPrim--instance (HasLinearMap v, Monoid (Render b v)) => Renderable (NullPrim v) b where- render _ _ = mempty---- | The null primitive, which every backend can render by doing--- nothing.-nullPrim :: (HasLinearMap v, Monoid (Render b v)) => Prim b v-nullPrim = Prim NullPrim------------------------------------------------------------------ Backends ---------------------------------------------------------------------------------------------------------------- | Abstract diagrams are rendered to particular formats by--- /backends/. Each backend/vector space combination must be an--- instance of the 'Backend' class. A minimal complete definition--- consists of the three associated types and implementations for--- 'withStyle' and 'doRender'.----class (HasLinearMap v, Monoid (Render b v)) => Backend b v where- -- | The type of rendering operations used by this backend, which- -- must be a monoid. For example, if @Render b v = M ()@ for some- -- monad @M@, a monoid instance can be made with @mempty = return- -- ()@ and @mappend = (>>)@.- data Render b v :: *-- -- | The result of running/interpreting a rendering operation.- type Result b v :: *-- -- | Backend-specific rendering options.- data Options b v :: *-- -- | Perform a rendering operation with a local style.- withStyle :: b -- ^ Backend token (needed only for type inference)- -> Style v -- ^ Style to use- -> Transformation v -- ^ Transformation to be applied to the style- -> Render b v -- ^ Rendering operation to run- -> Render b v -- ^ Rendering operation using the style locally-- -- | 'doRender' is used to interpret rendering operations.- doRender :: b -- ^ Backend token (needed only for type inference)- -> Options b v -- ^ Backend-specific collection of rendering options- -> Render b v -- ^ Rendering operation to perform- -> Result b v -- ^ Output of the rendering operation-- -- | 'adjustDia' allows the backend to make adjustments to the final- -- diagram (e.g. to adjust the size based on the options) before- -- rendering it. It can also make adjustments to the options- -- record, usually to fill in incompletely specified size- -- information. A default implementation is provided which makes- -- no adjustments. See the diagrams-lib package for other useful- -- implementations.- adjustDia :: Monoid' m => b -> Options b v- -> QDiagram b v m -> (Options b v, QDiagram b v m)- adjustDia _ o d = (o,d)-- -- XXX expand this comment. Explain about freeze, split- -- transformations, etc.- -- | Render a diagram. This has a default implementation in terms- -- of 'adjustDia', 'withStyle', 'doRender', and the 'render'- -- operation from the 'Renderable' class (first 'adjustDia' is- -- used, then 'withStyle' and 'render' are used to render each- -- primitive, the resulting operations are combined with- -- 'mconcat', and the final operation run with 'doRender') but- -- backends may override it if desired.- renderDia :: (InnerSpace v, OrderedField (Scalar v), Monoid' m)- => b -> Options b v -> QDiagram b v m -> Result b v- renderDia b opts d =- doRender b opts' . mconcat . map renderOne . prims $ d'- where (opts', d') = adjustDia b opts d- renderOne :: (Prim b v, (Split (Transformation v), Style v))- -> Render b v- renderOne (p, (M t, s))- = withStyle b s mempty (render b (transform t p))-- renderOne (p, (t1 :| t2, s))- = withStyle b s t1 (render b (transform (t1 <> t2) p))-- -- See Note [backend token]---- | The @D@ type is provided for convenience in situations where you--- must give a diagram a concrete, monomorphic type, but don't care--- which one. Such situations arise when you pass a diagram to a--- function which is polymorphic in its input but monomorphic in its--- output, such as 'width', 'height', 'phantom', or 'names'. Such--- functions compute some property of the diagram, or use it to--- accomplish some other purpose, but do not result in the diagram--- being rendered. If the diagram does not have a monomorphic type,--- GHC complains that it cannot determine the diagram's type.------ For example, here is the error we get if we try to compute the--- width of a radius-1 circle (this example requires--- @diagrams-lib@):------ > ghci> width (circle 1)--- >--- > <interactive>:1:8:--- > No instances for (Backend b0 R2,--- > Renderable Diagrams.TwoD.Ellipse.Ellipse b0)--- > arising from a use of `circle'--- > Possible fix:--- > add instance declarations for--- > (Backend b0 R2, Renderable Diagrams.TwoD.Ellipse.Ellipse b0)--- > In the first argument of `width', namely `(circle 1)'--- > In the expression: width (circle 1)--- > In an equation for `it': it = width (circle 1)------ GHC complains that it cannot find an instance for \"@Backend b0--- R2@\"; what is really going on is that it does not have enough--- information to decide which backend to use for the circle (hence--- the type variable @b0@). This is annoying because /we/ know that--- the choice of backend cannot possibly affect the width of the--- circle; but there is no way for GHC to know that.------ The solution is to annotate @circle 1@ with the type @'D' 'R2'@,--- like so:------ > ghci> width (circle 1 :: D R2)--- > 2.0--type D v = Diagram NullBackend v----- | A null backend which does no actual rendering. It is provided--- mainly for convenience in situations where you must give a--- diagram a concrete, monomorphic type, but don't actually care--- which one. See 'D' for more explanation and examples.------ It is courteous, when defining a new primitive @P@, to make an instance------ > instance Renderable P NullBackend where--- > render _ _ = mempty------ This ensures that the trick with 'D' annotations can be used for--- diagrams containing your primitive.-data NullBackend---- Note: we can't make a once-and-for-all instance------ > instance Renderable a NullBackend where--- > render _ _ = mempty------ because it overlaps with the Renderable instance for NullPrim.--instance Monoid (Render NullBackend v) where- mempty = NullBackendRender- mappend _ _ = NullBackendRender--instance HasLinearMap v => Backend NullBackend v where- data Render NullBackend v = NullBackendRender- type Result NullBackend v = ()- data Options NullBackend v-- withStyle _ _ _ _ = NullBackendRender- doRender _ _ _ = ()---- | A class for backends which support rendering multiple diagrams,--- e.g. to a multi-page pdf or something similar.-class Backend b v => MultiBackend b v where-- -- | Render multiple diagrams at once.- renderDias :: b -> Options b v -> [QDiagram b v m] -> Result b v-- -- See Note [backend token]----- | The Renderable type class connects backends to primitives which--- they know how to render.-class Transformable t => Renderable t b where- render :: b -> t -> Render b (V t)- -- ^ Given a token representing the backend and a- -- transformable object, render it in the appropriate rendering- -- context.-- -- See Note [backend token]--{--~~~~ Note [backend token]--A bunch of methods here take a "backend token" as an argument. The-backend token is expected to carry no actual information; it is solely-to help out the type system. The problem is that all these methods-return some associated type applied to b (e.g. Render b) and unifying-them with something else will never work, since type families are not-necessarily injective.--}-
− src/Graphics/Rendering/Diagrams/Envelope.hs
@@ -1,254 +0,0 @@-{-# LANGUAGE TypeFamilies- , FlexibleInstances- , FlexibleContexts- , UndecidableInstances- , GeneralizedNewtypeDeriving- , StandaloneDeriving- , MultiParamTypeClasses- #-}--------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Envelope--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ "Graphics.Rendering.Diagrams" defines the core library of primitives--- forming the basis of an embedded domain-specific language for--- describing and rendering diagrams.------ The @Envelope@ module defines a data type and type class for--- \"envelopes\", aka functional bounding regions.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Envelope- ( -- * Envelopes- Envelope(..)-- , inEnvelope- , appEnvelope- , onEnvelope- , mkEnvelope-- , Enveloped(..)-- , LocatedEnvelope(..)- , location- , locateEnvelope-- -- * Utility functions- , diameter- , radius- , envelopeV, envelopeP, boundaryFrom-- -- * Miscellaneous- , OrderedField- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Transform-import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.HasOrigin--import Data.VectorSpace-import Data.AffineSpace ((.+^), (.-^))--import Data.Semigroup-import Control.Applicative ((<$>))--import qualified Data.Map as M-import qualified Data.Set as S----------------------------------------------------------------- Envelopes -------------------------------------------------------------------------------------------------------------- | Every diagram comes equipped with an *envelope*.--- Intuitively, the envelope for a diagram tells us the--- minimum distance we have to go in a given direction to get to a--- (hyper)plane entirely containing the diagram on one side of--- it. Formally, given a vector @v@, it returns a scalar @s@ such--- that------ * for every point @u@ inside the diagram,--- if the projection of @(u - origin)@ onto @v@ is @s' *^ v@, then @s' <= s@.------ * @s@ is the smallest such scalar.------ This could probably be expressed in terms of a Galois connection;--- this is left as an exercise for the reader.------ There is also a special \"empty envelope\".------ Essentially, envelopes are a functional representation--- of (a conservative approximation to) convex bounding regions.--- The idea for this representation came from Sebastian Setzer; see--- <http://byorgey.wordpress.com/2009/10/28/collecting-attributes/#comment-2030>.-newtype Envelope v = Envelope { unEnvelope :: Option (v -> Max (Scalar v)) }--inEnvelope :: (Option (v -> Max (Scalar v)) -> Option (v -> Max (Scalar v)))- -> Envelope v -> Envelope v-inEnvelope f = Envelope . f . unEnvelope--appEnvelope :: Envelope v -> Maybe (v -> Scalar v)-appEnvelope (Envelope (Option b)) = (getMax .) <$> b--onEnvelope :: ((v -> Scalar v) -> (v -> Scalar v)) -> Envelope v -> Envelope v-onEnvelope t = (inEnvelope . fmap) ((Max .) . t . (getMax .))--mkEnvelope :: (v -> Scalar v) -> Envelope v-mkEnvelope = Envelope . Option . Just . (Max .)---- | Envelopes form a semigroup with pointwise maximum as composition.--- Hence, if @b1@ is the envelope for diagram @d1@, and--- @b2@ is the envelope for @d2@, then @b1 \`mappend\` b2@--- is the envelope for @d1 \`atop\` d2@.-deriving instance Ord (Scalar v) => Semigroup (Envelope v)---- | The special empty envelope is the identity for the--- 'Monoid' instance.-deriving instance Ord (Scalar v) => Monoid (Envelope v)------ XXX add some diagrams here to illustrate! Note that Haddock supports--- inline images, using a \<\<url\>\> syntax.--type instance V (Envelope v) = v---- | The local origin of an envelope is the point with respect to--- which bounding queries are made, /i.e./ the point from which the--- input vectors are taken to originate.-instance (InnerSpace v, AdditiveGroup (Scalar v), Fractional (Scalar v))- => HasOrigin (Envelope v) where- moveOriginTo (P u) = onEnvelope $ \f v -> f v ^-^ ((u ^/ (v <.> v)) <.> v)--instance Show (Envelope v) where- show _ = "<envelope>"----------------------------------------------------------------- Transforming envelopes ------------------------------------------------------------------------------------------------- XXX can we get away with removing this Floating constraint? It's the--- call to normalized here which is the culprit.-instance ( HasLinearMap v, InnerSpace v- , Floating (Scalar v), AdditiveGroup (Scalar v) )- => Transformable (Envelope v) where- transform t = -- XXX add lots of comments explaining this!- moveOriginTo (P . negateV . transl $ t) .- (onEnvelope $ \f v ->- let v' = normalized $ lapp (transp t) v- vi = apply (inv t) v- in f v' / (v' <.> vi)- )----------------------------------------------------------------- Enveloped class----------------------------------------------------------------- | When dealing with envelopes we often want scalars to be an--- ordered field (i.e. support all four arithmetic operations and be--- totally ordered) so we introduce this class as a convenient--- shorthand.-class (Fractional s, Floating s, Ord s, AdditiveGroup s) => OrderedField s-instance (Fractional s, Floating s, Ord s, AdditiveGroup s) => OrderedField s---- | @Enveloped@ abstracts over things which have an envelope.-class (InnerSpace (V b), OrderedField (Scalar (V b))) => Enveloped b where-- -- | Compute the envelope of an object. For types with an intrinsic- -- notion of \"local origin\", the envelope will be based there.- -- Other types (e.g. 'Trail') may have some other default- -- reference point at which the envelope will be based; their- -- instances should document what it is.- getEnvelope :: b -> Envelope (V b)--instance (InnerSpace v, OrderedField (Scalar v)) => Enveloped (Envelope v) where- getEnvelope = id--instance (OrderedField (Scalar v), InnerSpace v) => Enveloped (Point v) where- getEnvelope p = moveTo p . mkEnvelope $ const zeroV--instance (Enveloped a, Enveloped b, V a ~ V b) => Enveloped (a,b) where- getEnvelope (x,y) = getEnvelope x <> getEnvelope y--instance (Enveloped b) => Enveloped [b] where- getEnvelope = mconcat . map getEnvelope--instance (Enveloped b) => Enveloped (M.Map k b) where- getEnvelope = mconcat . map getEnvelope . M.elems--instance (Enveloped b) => Enveloped (S.Set b) where- getEnvelope = mconcat . map getEnvelope . S.elems---- XXX rename this? Move it elsewhere?---------------------------------------------------------------- Located envelopes----------------------------------------------------------------- | A @LocatedEnvelope@ value represents an envelope with its--- base point at a particular location.-data LocatedEnvelope v = LocatedEnvelope (Point v) (TransInv (Envelope v))- deriving (Show)--type instance V (LocatedEnvelope v) = v--instance (OrderedField (Scalar v), InnerSpace v) => Enveloped (LocatedEnvelope v) where- getEnvelope (LocatedEnvelope _ (TransInv b)) = b--instance VectorSpace v => HasOrigin (LocatedEnvelope v) where- moveOriginTo (P u) (LocatedEnvelope p b) = LocatedEnvelope (p .-^ u) b--instance ( HasLinearMap v, InnerSpace v- , Floating (Scalar v), AdditiveGroup (Scalar v) )- => Transformable (LocatedEnvelope v) where- transform t (LocatedEnvelope p b) = LocatedEnvelope (papply t p)- (transform t b)---- | Get the location of a located envelope.-location :: LocatedEnvelope v -> Point v-location (LocatedEnvelope p _) = p---- XXX boundaryFrom really ought to use the 'trace' of a diagram--- instead of the envelope. Leave it here for now, move it when we--- implement traces so it will have a different semantics.---- | @boundaryFrom v b@ computes the point on the boundary of the--- located envelope @b@ in the direction of @v@ from the--- bounding region's base point. This is most often used to compute--- a point on the boundary of a named subdiagram.-boundaryFrom :: (OrderedField (Scalar v), InnerSpace v)- => LocatedEnvelope v -> v -> Point v-boundaryFrom b v = location b .+^ envelopeV v b---- | Create a 'LocatedEnvelope' value by specifying a location and an--- envelope.-locateEnvelope :: Point v -> Envelope v -> LocatedEnvelope v-locateEnvelope p b = LocatedEnvelope p (TransInv b)----------------------------------------------------------------- Computing with envelopes----------------------------------------------------------------- | Compute the vector from the local origin to a separating--- hyperplane in the given direction. Returns the zero vector for--- the empty envelope.-envelopeV :: Enveloped a => V a -> a -> V a-envelopeV v a = maybe zeroV ((*^ v) . ($ v)) $ appEnvelope (getEnvelope a)---- | Compute the point on a separating hyperplane in the given--- direction. Returns the origin for the empty envelope.-envelopeP :: Enveloped a => V a -> a -> Point (V a)-envelopeP v a = P $ envelopeV v a---- | Compute the diameter of a enveloped object along a particular--- vector. Returns zero for the empty envelope.-diameter :: Enveloped a => V a -> a -> Scalar (V a)-diameter v a = magnitude (envelopeV v a ^-^ envelopeV (negateV v) a)---- | Compute the \"radius\" (1\/2 the diameter) of an enveloped object--- along a particular vector.-radius :: Enveloped a => V a -> a -> Scalar (V a)-radius v a = 0.5 * diameter v a
− src/Graphics/Rendering/Diagrams/HasOrigin.hs
@@ -1,94 +0,0 @@-{-# LANGUAGE FlexibleInstances- , FlexibleContexts- , TypeFamilies- , UndecidableInstances- #-}---- The UndecidableInstances flag is needed under 6.12.3 for the--- HasOrigin (a,b) instance.---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.HasOrigin--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Types which have an intrinsic notion of a \"local origin\",--- /i.e./ things which are /not/ invariant under translation.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.HasOrigin- ( HasOrigin(..), moveOriginBy, moveTo, place- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Points--import qualified Data.Map as M-import qualified Data.Set as S--import Data.AffineSpace ((.-^), (.-.))-import Data.VectorSpace---- | Class of types which have an intrinsic notion of a \"local--- origin\", i.e. things which are not invariant under translation,--- and which allow the origin to be moved.------ One might wonder why not just use 'Transformable' instead of--- having a separate class for 'HasOrigin'; indeed, for types which--- are instances of both we should have the identity------ > moveOriginTo (origin .^+ v) === translate (negateV v)------ The reason is that some things (e.g. vectors, 'Trail's) are--- transformable but are translationally invariant, i.e. have no--- origin.-class VectorSpace (V t) => HasOrigin t where-- -- | Move the local origin to another point.- --- -- Note that this function is in some sense dual to 'translate'- -- (for types which are also 'Transformable'); moving the origin- -- itself while leaving the object \"fixed\" is dual to fixing the- -- origin and translating the diagram.- moveOriginTo :: Point (V t) -> t -> t---- | Move the local origin by a relative vector.-moveOriginBy :: HasOrigin t => V t -> t -> t-moveOriginBy = moveOriginTo . P---- | Translate the object by the translation that sends the origin to--- the given point. Note that this is dual to 'moveOriginTo', i.e. we--- should have------ > moveTo (origin .^+ v) === moveOriginTo (origin .^- v)------ For types which are also 'Transformable', this is essentially the--- same as 'translate', i.e.------ > moveTo (origin .^+ v) === translate v-moveTo :: HasOrigin t => Point (V t) -> t -> t-moveTo = moveOriginBy . (origin .-.)---- | A flipped variant of 'moveTo', provided for convenience. Useful--- when writing a function which takes a point as an argument, such--- as when using 'withName' and friends.-place :: HasOrigin t => t -> Point (V t) -> t-place = flip moveTo--instance VectorSpace v => HasOrigin (Point v) where- moveOriginTo (P u) p = p .-^ u--instance (HasOrigin a, HasOrigin b, V a ~ V b) => HasOrigin (a,b) where- moveOriginTo p (x,y) = (moveOriginTo p x, moveOriginTo p y)--instance HasOrigin a => HasOrigin [a] where- moveOriginTo = map . moveOriginTo--instance (HasOrigin a, Ord a) => HasOrigin (S.Set a) where- moveOriginTo = S.map . moveOriginTo--instance HasOrigin a => HasOrigin (M.Map k a) where- moveOriginTo = M.map . moveOriginTo
− src/Graphics/Rendering/Diagrams/Juxtapose.hs
@@ -1,63 +0,0 @@-{-# LANGUAGE FlexibleContexts- , UndecidableInstances- , TypeFamilies- #-}--------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Juxtapose--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Things which can be placed \"next to\" other things, for some--- appropriate notion of \"next to\".-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Juxtapose- ( Juxtaposable(..), juxtaposeDefault- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Envelope-import Graphics.Rendering.Diagrams.HasOrigin--import qualified Data.Map as M-import qualified Data.Set as S--import Data.VectorSpace---- | Class of things which can be placed \"next to\" other things, for some--- appropriate notion of \"next to\".-class Juxtaposable a where-- -- | @juxtapose v a1 a2@ positions @a2@ next to @a1@ in the- -- direction of @v@. In particular, place @a2@ so that @v@ points- -- from the local origin of @a1@ towards the old local origin of- -- @a2@; @a1@'s local origin becomes @a2@'s new local origin. The- -- result is just a translated version of @a2@. (In particular,- -- this operation does not /combine/ @a1@ and @a2@ in any way.)- juxtapose :: V a -> a -> a -> a---- | Default implementation of 'juxtapose' for things which are--- instances of 'Enveloped' and 'HasOrigin'.-juxtaposeDefault :: (Enveloped a, HasOrigin a) => V a -> a -> a -> a-juxtaposeDefault v a1 a2 = moveOriginBy (v1 ^+^ v2) a2- where v1 = negateV (envelopeV v a1)- v2 = envelopeV (negateV v) a2--instance (InnerSpace v, OrderedField (Scalar v)) => Juxtaposable (Envelope v) where- juxtapose = juxtaposeDefault--instance (Enveloped a, HasOrigin a, Enveloped b, HasOrigin b, V a ~ V b)- => Juxtaposable (a,b) where- juxtapose = juxtaposeDefault--instance (Enveloped b, HasOrigin b) => Juxtaposable [b] where- juxtapose = juxtaposeDefault--instance (Enveloped b, HasOrigin b) => Juxtaposable (M.Map k b) where- juxtapose = juxtaposeDefault--instance (Enveloped b, HasOrigin b, Ord b) => Juxtaposable (S.Set b) where- juxtapose = juxtaposeDefault
− src/Graphics/Rendering/Diagrams/MList.hs
@@ -1,180 +0,0 @@-{-# LANGUAGE TypeOperators- , MultiParamTypeClasses- , FlexibleInstances- , OverlappingInstances- , UndecidableInstances- , TypeFamilies- , GeneralizedNewtypeDeriving- #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.MList--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Heterogeneous lists of monoids.----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.MList- ( -- * Heterogeneous monoidal lists-- -- $mlist-- Nil(..), (:::)(..)-- , MList(..)-- -- * Converting to tuples- , Tuple, ToTuple(..)-- -- * Accessing embedded values- , (:>:)(..)-- -- * Monoid actions of heterogeneous lists-- -- $mlist-actions-- , SM(..)- ) where--import Data.Semigroup-import Graphics.Rendering.Diagrams.Monoids---- $mlist------ The idea of /heterogeneous lists/ has been around for a long time.--- Here, we adopt heterogeneous lists where the element types are all--- monoids: this allows us to leave out identity values, so that a--- heterogeneous list containing only a single non-identity value can--- be created without incurring constraints due to all the other--- types, by leaving all the other values out.--infixr 5 :::---- | The empty heterogeneous list.-data Nil = Nil- deriving (Show, Eq, Ord)---- | Cons for heterogeneous lists.-data a ::: l = Missing l -- ^ The @a@ value is missing, and should be- -- construed as 'mempty'.- | a ::: l -- ^ An @a@ value followed by a heterogeneous- -- list @l@.- deriving (Show, Eq, Ord)---- MList --------------------------------------- | Type class for heterogeneous monoidal lists, with a single method--- allowing construction of an empty list.-class MList l where- -- | The /empty/ heterogeneous list of type @l@. Of course, @empty- -- == 'mempty'@, but unlike 'mempty', @empty@ does not require- -- 'Monoid' constraints on all the elements of @l@.- empty :: l--instance MList Nil where- empty = Nil--instance MList l => MList (a ::: l) where- empty = Missing empty---- Monoid ------------------------------------instance Semigroup Nil where- _ <> _ = Nil--instance Monoid Nil where- mempty = Nil- mappend = (<>)--instance (Semigroup a, Semigroup tl) => Semigroup (a ::: tl) where- (Missing t1) <> (Missing t2) = Missing (t1 <> t2)- (Missing t1) <> (a2 ::: t2) = a2 ::: (t1 <> t2)- (a1 ::: t1) <> (Missing t2) = a1 ::: (t1 <> t2)- (a1 ::: t1) <> (a2 ::: t2) = (a1 <> a2) ::: (t1 <> t2)---- | Heterogeneous monoidal lists are themselves instances of 'Monoid'--- as long as all their elements are, where 'mappend' is done--- elementwise.-instance (Semigroup a, Semigroup tl, Monoid tl) => Monoid (a ::: tl) where- mempty = Missing mempty- mappend = (<>)---- ToTuple ------------------------------------- | A type function to compute the tuple-based representation for--- instances of 'MList'.-type family Tuple l :: *-type instance Tuple Nil = ()-type instance Tuple (a ::: b) = (a, Tuple b)---- | @toTuple@ can be used to convert a heterogeneous list to its--- tuple-based representation.-class ToTuple l where- toTuple :: l -> Tuple l--instance ToTuple Nil where- toTuple _ = ()--instance (Monoid a, ToTuple l) => ToTuple (a ::: l) where- toTuple (Missing l) = (mempty, toTuple l)- toTuple (a ::: l) = (a, toTuple l)---- Embedding ----------------------------------------------- | The relation @l :>: a@ holds when @a@ is the type of an element--- in @l@. For example, @(Char ::: Int ::: Bool ::: Nil) :>: Int@.-class l :>: a where- -- | Inject a value into an otherwise empty heterogeneous list.- inj :: a -> l-- -- | Get the value of type @a@ from a heterogeneous list.- get :: l -> a-- -- | Alter the value of type @a@ by applying the given function to it.- alt :: (a -> a) -> l -> l--instance (MList t, Monoid a) => (:>:) (a ::: t) a where- inj a = a ::: empty- get (Missing _) = mempty- get (a ::: _) = a- alt f (Missing l) = f mempty ::: l- alt f (a ::: l) = f a ::: l--instance (t :>: a) => (:>:) (b ::: t) a where- inj a = Missing (inj a)- get (Missing l) = get l- get (_ ::: l) = get l- alt f (Missing l) = Missing (alt f l)- alt f (a ::: l) = a ::: alt f l---- Monoid actions --------------------------------------------- $mlist-actions--- Monoidal heterogeneous lists may act on one another as you would--- expect, with each element in the first list acting on each in the--- second. Unfortunately, coding this up in type class instances is a--- bit fiddly.---- | @SM@, an abbreviation for \"single monoid\" (as opposed to a--- heterogeneous list of monoids), is only used internally to help--- guide instance selection when defining the action of--- heterogeneous monoidal lists on each other.-newtype SM m = SM m- deriving (Monoid)--instance Action Nil l where- act _ a = a--instance (Monoid a, Action (SM a) l2, Action l1 l2) => Action (a ::: l1) l2 where- act (Missing l1) l2 = act l1 l2- act (a ::: l1) l2 = act (SM a) (act l1 l2)--instance Monoid a => Action (SM a) Nil where- act _ _ = Nil--instance (Action a a', Action (SM a) l) => Action (SM a) (a' ::: l) where- act (SM a) (Missing l) = Missing (act (SM a) l)- act (SM a) (a' ::: l) = act a a' ::: act (SM a) l
− src/Graphics/Rendering/Diagrams/Monoids.hs
@@ -1,467 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses- , FlexibleInstances- , GeneralizedNewtypeDeriving- , DeriveFunctor- , TypeFamilies- , TypeOperators- , UndecidableInstances- #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Monoids--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Various monoid-related definitions (monoid actions, split monoids,--- applicative monoids) used in the core diagrams library.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Monoids- ( -- * Monoids and semigroups-- Monoid'-- -- * Monoid actions-- , Action(..)-- -- * Split monoids- -- $split-- , Split(..), split-- -- * Forgetful monoids- -- $forget-- , Forgetful(..), unForget, forget-- , Deletable(..), unDelete, toDeletable, deleteL, deleteR-- -- * Applicative monoids-- , AM(..), inAM2-- -- * Coproduct monoid- , (:+:)- , inL, inR- , mappendL, mappendR- , killL, killR- , untangle- ) where--import Graphics.Rendering.Diagrams.V--import Data.Semigroup-import Data.Foldable-import Control.Applicative-import Data.Either (lefts, rights)----------------------------------------------------------------- Monoids and semigroups----------------------------------------------------------------- Poor man's constraint synonym. Eventually, once it becomes--- standard, we can make this a real constraint synonym and get rid of--- the UndecidableInstances flag. Better yet, hopefully the Monoid--- class will eventually have a Semigroup superclass.---- | The @Monoid'@ class is a synonym for things which are instances--- of both 'Semigroup' and 'Monoid'. Ideally, the 'Monoid' class--- itself will eventually include a 'Semigroup' superclass and we--- can get rid of this.-class (Semigroup m, Monoid m) => Monoid' m-instance (Semigroup m, Monoid m) => Monoid' m----------------------------------------------------------------- Monoid actions----------------------------------------------------------------- | Type class for monoid actions, where monoidal values of type @m@--- \"act\" on values of another type @s@. Instances are required to--- satisfy the laws------ * @act mempty = id@------ * @act (m1 ``mappend`` m2) = act m1 . act m2@------ Additionally, if the type @s@ has any algebraic structure, @act--- m@ should be a homomorphism. For example, if @s@ is also a--- monoid we should have @act m mempty = mempty@ and @act m (s1--- ``mappend`` s2) = (act m s1) ``mappend`` (act m s2)@.------ By default, @act = const id@, so for a monoidal type @M@ which--- should have no action on anything, it suffices to write------ > instance Action M s------ with no method implementations.-class Action m s where-- -- | Convert a monoidal value of type @m@ to an action on @s@ values.- act :: m -> s -> s- act = const id----------------------------------------------------------------- Split monoids----------------------------------------------------------------- $split--- Sometimes we want to accumulate values from some monoid, but have--- the ability to introduce a \"split\" which separates values on--- either side. For example, this is used when accumulating--- transformations to be applied to primitive diagrams: the 'freeze'--- operation introduces a split, since only transformations occurring--- outside the freeze should be applied to attributes.--infix 5 :|---- | A value of type @Split m@ is either a single @m@, or a pair of--- @m@'s separated by a divider.-data Split m = M m- | m :| m---- | If @m@ is a @Semigroup@, then @Split m@ is a semigroup which--- combines values on either side of a split, keeping only the--- rightmost split.-instance Semigroup m => Semigroup (Split m) where- (M m1) <> (M m2) = M (m1 <> m2)- (M m1) <> (m1' :| m2) = m1 <> m1' :| m2- (m1 :| m2) <> (M m2') = m1 :| m2 <> m2'- (m11 :| m12) <> (m21 :| m22) = m11 <> m12 <> m21 :| m22--instance (Semigroup m, Monoid m) => Monoid (Split m) where- mempty = M mempty- mappend = (<>)---- | A convenient name for @mempty :| mempty@, so @a \<\> split \<\> b == a :| b@.-split :: Monoid m => Split m-split = mempty :| mempty---- | By default, the action of a split monoid is the same as for--- the underlying monoid, as if the split were removed.-instance Action m n => Action (Split m) n where- act (M m) n = act m n- act (m1 :| m2) n = act m1 (act m2 n)----------------------------------------------------------------- Forgetful monoids----------------------------------------------------------------- $forget--- Sometimes we want to be able to \"forget\" some information. We--- define two monoid transformers that allow forgetting information.--- @Forgetful@ introduces special values which cause anything to their--- right to be forgotten. @Deletable@ introduces special \"left and--- right bracket\" elements which cause everything inside them to be--- forgotten.----- | A value of type @Forgetful m@ is either a \"normal\" value of--- type @m@, which combines normally with other normal values, or a--- \"forgetful\" value, which combines normally with other values to--- its left but discards values combined on the right. Also, when--- combining a forgetful value with a normal one the result is--- always forgetful.-data Forgetful m = Normal m- | Forgetful m- deriving Functor---- | Project the wrapped value out of a `Forgetful` value.-unForget :: Forgetful m -> m-unForget (Normal m) = m-unForget (Forgetful m) = m---- | If @m@ is a 'Semigroup', then @Forgetful m@ is a semigroup with two--- sorts of values, \"normal\" and \"forgetful\": the normal ones--- combine normally and the forgetful ones discard anything to the--- right.-instance Semigroup m => Semigroup (Forgetful m) where- (Normal m1) <> (Normal m2) = Normal (m1 <> m2)- (Normal m1) <> (Forgetful m2) = Forgetful (m1 <> m2)- (Forgetful m1) <> _ = Forgetful m1--instance (Semigroup m, Monoid m) => Monoid (Forgetful m) where- mempty = Normal mempty- mappend = (<>)----- | A convenient name for @Forgetful mempty@, so @a \<\> forget \<\>--- b == Forgetful a@.-forget :: Monoid m => Forgetful m-forget = Forgetful mempty--instance Action m n => Action (Forgetful m) n where- act (Normal m) n = act m n- act (Forgetful m) n = act m n--type instance V (Forgetful m) = V m---- | If @m@ is a 'Monoid', then @Deletable m@ (intuitively speaking)--- adds two distinguished new elements @[@ and @]@, such that an--- occurrence of [ \"deletes\" everything from it to the next ]. For--- example,------ > abc[def]gh == abcgh------ This is all you really need to know to /use/ @Deletable m@--- values; to understand the actual implementation, read on.------ To properly deal with nesting and associativity we need to be--- able to assign meanings to things like @[[@, @][@, and so on. (We--- cannot just define, say, @[[ == [@, since then @([[)] == [] ==--- id@ but @[([]) == [id == [@.) Formally, elements of @Deletable--- m@ are triples of the form (r, m, l) representing words @]^r m--- [^l@. When combining two triples (r1, m1, l1) and (r2, m2, l2)--- there are three cases:------ * If l1 == r2 then the [s from the left and ]s from the right--- exactly cancel, and we are left with (r1, m1 \<\> m2, l2).------ * If l1 < r2 then all of the [s cancel with some of the ]s, but--- m1 is still inside the remaining ]s and is deleted, yielding (r1--- + r2 - l1, m2, l2)------ * The remaining case is symmetric with the second.--data Deletable m = Deletable Int m Int- deriving Functor--type instance V (Deletable m) = V m---- | Project the wrapped value out of a `Deletable` value.-unDelete :: Deletable m -> m-unDelete (Deletable _ m _) = m---- | Inject a value into a `Deletable` wrapper. Satisfies the--- property------ > unDelete . toDeletable === id----toDeletable :: m -> Deletable m-toDeletable m = Deletable 0 m 0--instance Semigroup m => Semigroup (Deletable m) where- (Deletable r1 m1 l1) <> (Deletable r2 m2 l2)- | l1 == r2 = Deletable r1 (m1 <> m2) l2- | l1 < r2 = Deletable (r1 + r2 - l1) m2 l2- | otherwise = Deletable r1 m1 (l2 + l1 - r2)--instance (Semigroup m, Monoid m) => Monoid (Deletable m) where- mempty = Deletable 0 mempty 0- mappend = (<>)---- | A \"left bracket\", which causes everything between it and the--- next right bracket to be deleted.-deleteL :: Monoid m => Deletable m-deleteL = Deletable 0 mempty 1---- | A \"right bracket\", denoting the end of the section that should--- be deleted.-deleteR :: Monoid m => Deletable m-deleteR = Deletable 1 mempty 0----------------------------------------------------------------- Applicative monoids----------------------------------------------------------------- | A wrapper for an 'Applicative' structure containing a monoid.--- Such structures have a @Monoid@ instance based on \"idiomatic\"--- application of 'mappend' within the @Applicative@ context.--- @instance Monoid m => Monoid (e -> m)@ is one well-known special--- case. (However, the standard @Monoid@ instance for @Maybe@ is--- /not/ an instance of this pattern; nor is the standard instance--- for lists.)-newtype AM f m = AM (f m)- deriving (Functor, Applicative)---- | Apply a binary function inside an 'AM' newtype wrapper.-inAM2 :: (f m -> f m -> f m) -> AM f m -> AM f m -> AM f m-inAM2 g (AM f1) (AM f2) = AM (g f1 f2)--instance (Applicative f, Semigroup m) => Semigroup (AM f m) where- (<>) = inAM2 (liftA2 (<>))---- | @f1 ``mappend`` f2@ is defined as @'mappend' '<$>' f1 '<*>' f2@.-instance (Applicative f, Monoid m) => Monoid (AM f m) where- mempty = pure mempty- mappend = inAM2 (liftA2 mappend)--{- See Applicative laws here:--http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Applicative.html#t:Applicative--}--{- left identity:-- AM (pure mempty) `mappend` AM f-= { definition }- AM $ fmap mappend (pure mempty) <*> f-= { naturality of pure, fmap f . pure = pure . f }- AM $ pure (mappend mempty) <*> f-= { monoid law (left identity) }- AM $ pure id <*> f-= { applicative law (identity) }- AM f--}--{- right identity:-- AM f `mappend` AM (pure mempty)-= { definition }- AM $ fmap mappend f <*> pure mempty-= { applicative law (interchange) }- AM $ pure ($mempty) <*> fmap mappend f-= { applicative/functor law }- AM $ pure ($mempty) <*> (pure mappend <*> f)-= { applicative law (composition) }- AM $ pure (.) <*> pure ($mempty) <*> pure mappend <*> f-= { applicative law (homomorphism) }- AM $ pure ((.) ($mempty)) <*> pure mappend <*> f-= { applicative law (homomorphism) }- AM $ pure (($mempty) . mappend) <*> f-= { monoid law (right identity) }- AM $ pure id <*> f-= { applicative law (identity) }- AM f--}--{- associativity:-- (AM f1 `mappend` AM f2) `mappend` AM f3-= { definition }- AM $ fmap mappend (AM f1 `mappend` AM f2) <*> f3-= { definition }- AM $ fmap mappend (fmap mappend f1 <*> f2) <*> f3-= { applicative/functor law }- AM $ pure mappend <*> (pure mappend <*> f1 <*> f2) <*> f3-= { applicative law (composition) }- AM $ pure (.) <*> pure mappend <*> (pure mappend <*> f1) <*> f2 <*> f3-= { applicative law (homomorphism) }- AM $ pure (mappend .) <*> (pure mappend <*> f1) <*> f2 <*> f3-= { applicative law (composition) }- AM $ pure (.) <*> pure (mappend .) <*> pure mappend <*> f1 <*> f2 <*> f3-= { applicative law (homomorphism) }- AM $ pure ((mappend .) . mappend) <*> f1 <*> f2 <*> f3-= { monoid law (associativity) }- AM $ pure ((. mappend) . (.) . mappend) <*> f1 <*> f2 <*> f3-=- -- XXX finish this proof (although I have no doubt it goes through)---=- AM f1 `mappend` (AM f2 `mappend` AM f3)--}--{--\x y z -> (x `mappend` y) `mappend` z-\x y -> mappend (mappend x y)-\x -> mappend . (mappend x)-(mappend .) . mappend--}--{--\x y z -> x `mappend` (y `mappend` z)-\x y z -> mappend x (mappend y z)-\x y -> mappend x . mappend y-\x -> ((.) (mappend x)) . mappend-\x -> (.) ((.) (mappend x)) mappend-\x -> (.mappend) ((.) (mappend x))-(. mappend) . (.) . mappend--}----- | An applicative monoid acts on a value of a monoidal type by--- having each element in the structure act on the value--- independently, and then folding the resulting structure.-instance (Action m n, Foldable f, Functor f, Monoid n) => Action (AM f m) n where- act (AM f) n = fold $ fmap (`act` n) f---- XXX need to prove that this satisfies the laws! There are other--- "obvious" instances too.----------------------------------------------------------------- Monoid coproduct----------------------------------------------------------------- | @m :+: n@ is the coproduct of monoids @m@ and @n@. Values of--- type @m :+: n@ consist of alternating lists of @m@ and @n@--- values. The empty list is the identity, and composition is list--- concatenation, with appropriate combining of adjacent elements--- when possible.-newtype m :+: n = MCo { unMCo :: [Either m n] }---- For efficiency and simplicity, we implement it just as [Either m--- n]: of course, this does not preserve the invariant of strictly--- alternating types, but it doesn't really matter as long as we don't--- let anyone inspect the internal representation.---- | Injection from the left monoid into a coproduct.-inL :: m -> m :+: n-inL m = MCo [Left m]---- | Injection from the right monoid into a coproduct.-inR :: n -> m :+: n-inR n = MCo [Right n]---- | Prepend a value from the left monoid.-mappendL :: m -> m :+: n -> m :+: n-mappendL = mappend . inL---- | Prepend a value from the right monoid.-mappendR :: n -> m :+: n -> m :+: n-mappendR = mappend . inR--{--normalize :: (Monoid m, Monoid n) => m :+: n -> m :+: n-normalize (MCo es) = MCo (normalize' es)- where normalize' [] = []- normalize' [e] = [e]- normalize' (Left e1:Left e2 : es) = normalize' (Left (e1 <> e2) : es)- normalize' (Left e1:es) = Left e1 : normalize' es- normalize' (Right e1:Right e2:es) = normalize' (Right (e1 <> e2) : es)- normalize' (Right e1:es) = Right e1 : normalize' es--}--instance Semigroup (m :+: n) where- (MCo es1) <> (MCo es2) = MCo (es1 ++ es2)---- | The coproduct of two monoids is itself a monoid.-instance Monoid (m :+: n) where- mempty = MCo []- mappend = (<>)---- | @killR@ takes a value in a coproduct monoid and sends all the--- values from the right monoid to the identity.-killR :: Monoid m => m :+: n -> m-killR = mconcat . lefts . unMCo---- | @killL@ takes a value in a coproduct monoid and sends all the--- values from the left monoid to the identity.-killL :: Monoid n => m :+: n -> n-killL = mconcat . rights . unMCo---- | Take a value from a coproduct monoid where the left monoid has an--- action on the right, and \"untangle\" it into a pair of values. In--- particular,------ > m1 <> n1 <> m2 <> n2 <> m3 <> n3 <> ...------ is sent to------ > (m1 <> m2 <> m3 <> ..., (act m1 n1) <> (act (m1 <> m2) n2) <> (act (m1 <> m2 <> m3) n3) <> ...)------ That is, before combining @n@ values, every @n@ value is acted on--- by all the @m@ values to its left.-untangle :: (Action m n, Monoid m, Monoid n) => m :+: n -> (m,n)-untangle (MCo elts) = untangle' mempty elts- where untangle' cur [] = cur- untangle' (curM, curN) (Left m : elts') = untangle' (curM `mappend` m, curN) elts'- untangle' (curM, curN) (Right n : elts') = untangle' (curM, curN `mappend` act curM n) elts'---- | Coproducts act on other things by having each of the components--- act individually.-instance (Action m r, Action n r) => Action (m :+: n) r where- act = appEndo . mconcat . map (Endo . either act act) . unMCo
− src/Graphics/Rendering/Diagrams/Names.hs
@@ -1,231 +0,0 @@-{-# LANGUAGE TypeSynonymInstances- , FlexibleInstances- , FlexibleContexts- , TypeFamilies- , GeneralizedNewtypeDeriving- , MultiParamTypeClasses- , OverlappingInstances- , TupleSections- , GADTs- , DeriveDataTypeable- , UndecidableInstances- #-}--------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Names--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ This module defines a type of names which can be used for referring--- to locations within diagrams, and related types.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Names- (-- * Names- -- ** Atomic names- AName(..)-- -- ** Names- , Name(..), IsName(..), (.>)-- -- ** Qualifiable- , Qualifiable(..)-- -- * Name maps-- , NameMap(..)-- -- ** Constructing name maps- , fromNames, fromNamesB- , rememberAs-- -- ** Searching within name maps- , lookupN- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Monoids-import Graphics.Rendering.Diagrams.HasOrigin-import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.Envelope-import Graphics.Rendering.Diagrams.Transform--import Data.VectorSpace--import Data.List (intercalate, isSuffixOf)-import qualified Data.Map as M-import Data.Semigroup-import Control.Arrow ((***))-import Control.Monad (mplus)--import Control.Newtype--import Data.Typeable----------------------------------------------------------------- Names ------------------------------------------------------------------------------------------------------------------ | Class for those types which can be used as names. They must--- support 'Typeable' (to facilitate extracting them from--- existential wrappers), 'Ord' (for comparison and efficient--- storage) and 'Show'.-class (Typeable a, Ord a, Show a) => IsName a where- toName :: a -> Name- toName = Name . (:[]) . AName--instance IsName ()-instance IsName Bool-instance IsName Char-instance IsName Int-instance IsName Float-instance IsName Double-instance IsName Integer-instance IsName String-instance IsName a => IsName [a]-instance (IsName a, IsName b) => IsName (a,b)-instance (IsName a, IsName b, IsName c) => IsName (a,b,c)---- | Atomic names. @AName@ is just an existential wrapper around--- things which are 'Typeable', 'Ord' and 'Show'.-data AName where- AName :: (Typeable a, Ord a, Show a) => a -> AName- deriving (Typeable)--instance IsName AName where- toName = Name . (:[])--instance Eq AName where- (AName a1) == (AName a2) =- case cast a2 of- Nothing -> False- Just a2' -> a1 == a2'--instance Ord AName where- (AName a1) `compare` (AName a2) =- case cast a2 of- Nothing -> show (typeOf a1) `compare` show (typeOf a2)- Just a2' -> a1 `compare` a2'--instance Show AName where- show (AName a) = show a---- | A (qualified) name is a (possibly empty) sequence of atomic names.-newtype Name = Name [AName]- deriving (Eq, Ord, Semigroup, Monoid, Typeable)--instance Show Name where- show (Name ns) = intercalate " .> " $ map show ns--instance IsName Name where- toName = id---- | Convenient operator for writing qualified names with atomic--- components of different types. Instead of writing @toName a1 \<\>--- toName a2 \<\> toName a3@ you can just write @a1 .> a2 .> a3@.-(.>) :: (IsName a1, IsName a2) => a1 -> a2 -> Name-a1 .> a2 = toName a1 <> toName a2---- | Instances of 'Qualifiable' are things which can be qualified by--- prefixing them with a name.-class Qualifiable q where- -- | Qualify with the given name.- (|>) :: IsName a => a -> q -> q---- | Of course, names can be qualified using @(.>)@.-instance Qualifiable Name where- (|>) = (.>)--infixr 5 |>-infixr 5 .>----------------------------------------------------------------- Name maps -------------------------------------------------------------------------------------------------------------- | A 'NameMap' is a map associating names to located envelopes,--- /i.e./ envelopes with concrete locations for their base--- points. There can be multiple associations for any given name.-newtype NameMap v = NameMap (M.Map Name [LocatedEnvelope v])- deriving (Show)--instance Newtype (NameMap v) (M.Map Name [LocatedEnvelope v]) where- pack = NameMap- unpack (NameMap m) = m---- Note, in some sense it would be nicer to use Sets instead of a--- list, but then we would have to put Ord constraints on v--- everywhere. =P---- Note also that we wrap the envelope with TransInv. This is because--- the base point of each envelope should be thought of as the paired--- Point, *not* as the origin of the current vector space. In other--- words, the point gets translated "for both of them".--type instance V (NameMap v) = v--instance Semigroup (NameMap v) where- NameMap s1 <> NameMap s2 = NameMap $ M.unionWith (++) s1 s2---- | 'NameMap's form a monoid with the empty map as the identity, and--- map union as the binary operation. No information is ever lost:--- if two maps have the same name in their domain, the resulting map--- will associate that name to the concatenation of the information--- associated with that name.-instance Monoid (NameMap v) where- mempty = NameMap M.empty- mappend = (<>)--instance (AdditiveGroup (Scalar v), Fractional (Scalar v), InnerSpace v)- => HasOrigin (NameMap v) where- moveOriginTo = over NameMap . moveOriginTo--instance (AdditiveGroup (Scalar v), InnerSpace v, Floating (Scalar v), HasLinearMap v)- => Transformable (NameMap v) where- transform = over NameMap . transform---- | 'NameMap's are qualifiable: if @ns@ is a 'NameMap', then @a |>--- ns@ is the same 'NameMap' except with every name qualified by--- @a@.-instance Qualifiable (NameMap v) where- a |> (NameMap names) = NameMap $ M.mapKeys (a |>) names---- | Construct a 'NameMap' from a list of (name, point) pairs.-fromNames :: (InnerSpace v, AdditiveGroup (Scalar v), Ord (Scalar v), Floating (Scalar v), IsName a)- => [(a, Point v)] -> NameMap v-fromNames = NameMap . M.fromListWith (++) - . map (toName *** ((:[]) . (\p -> locateEnvelope p (getEnvelope p))))---- | Construct a 'NameMap' from a list of associations between names--- and located envelopes.-fromNamesB :: IsName a => [(a, LocatedEnvelope v)] -> NameMap v-fromNamesB = NameMap . M.fromListWith (++) . map (toName *** (:[]))---- | Give a name to a located envelope.-rememberAs :: IsName a => a -> LocatedEnvelope v -> NameMap v -> NameMap v-rememberAs n b = over NameMap $ M.insertWith (++) (toName n) [b]---- | A name acts on a name map by qualifying every name in it.-instance Action Name (NameMap v) where- act = (|>)---- | Names don't act on anything else.-instance Action Name a----- Searching in name maps.---- | Look for the given name in a name map, returning a list of--- located envelopes associated with that name. If no names match--- the given name exactly, return all the points associated with--- names of which the given name is a suffix.-lookupN :: IsName n => n -> NameMap v -> Maybe [LocatedEnvelope v]-lookupN a (NameMap m)- = M.lookup n m `mplus`- (flatten . filter ((n `nameSuffixOf`) . fst) . M.assocs $ m)- where (Name n1) `nameSuffixOf` (Name n2) = n1 `isSuffixOf` n2- flatten [] = Nothing- flatten xs = Just . concatMap snd $ xs- n = toName a
− src/Graphics/Rendering/Diagrams/Points.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE TypeFamilies- #-}--------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Points--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ A type for /points/ (as distinct from vectors).-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Points- ( -- * Points-- Point(..), origin, (*.)-- ) where---- We just import from Data.AffineSpace.Point (defined in the--- vector-space-points package) and re-export. We also define an--- instance of V for Point here.-import Data.AffineSpace.Point--import Graphics.Rendering.Diagrams.V--type instance V (Point v) = v
− src/Graphics/Rendering/Diagrams/Query.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE TypeFamilies- , GeneralizedNewtypeDeriving- #-}--------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Query--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ The @Query@ module defines a type for \"queries\" on diagrams, which--- are functions from points in a vector space to some monoid.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Query- ( Query(..)- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Transform-import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.HasOrigin--import Data.VectorSpace-import Data.AffineSpace--import Data.Semigroup-import Control.Applicative----------------------------------------------------------------- Queries ---------------------------------------------------------------------------------------------------------------- | A query is a function that maps points in a vector space to--- values in some monoid. Queries naturally form a monoid, with--- two queries being combined pointwise.------ The idea for annotating diagrams with monoidal queries came from--- the graphics-drawingcombinators package, <http://hackage.haskell.org/package/graphics-drawingcombinators>.-newtype Query v m = Query { runQuery :: Point v -> m }- deriving (Functor, Applicative, Semigroup, Monoid)--type instance V (Query v m) = v--instance VectorSpace v => HasOrigin (Query v m) where- moveOriginTo (P u) (Query f) = Query $ \p -> f (p .+^ u)--instance HasLinearMap v => Transformable (Query v m) where- transform t (Query f) = Query $ f . papply (inv t)
− src/Graphics/Rendering/Diagrams/Style.hs
@@ -1,239 +0,0 @@-{-# LANGUAGE ScopedTypeVariables- , GADTs- , KindSignatures- , FlexibleInstances- , MultiParamTypeClasses- , TypeFamilies- , UndecidableInstances- #-}---- The UndecidableInstances flag is needed under 6.12.3 for the--- HasStyle (a,b) instance.---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Style--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ A definition of /styles/ for diagrams as extensible, heterogeneous--- collections of attributes.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Style- ( -- * Attributes- -- $attr-- AttributeClass- , Attribute(..)- , mkAttr, mkTAttr, unwrapAttr- , applyAttr, applyTAttr-- -- * Styles- -- $style-- , Style(..)- , attrToStyle, tAttrToStyle- , getAttr, setAttr, addAttr, combineAttr-- , HasStyle(..)-- ) where--import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Transform-import Graphics.Rendering.Diagrams.Monoids--import Data.Typeable--import Control.Arrow ((***))-import Data.Semigroup-import qualified Data.Map as M-import qualified Data.Set as S----------------------------------------------------------------- Attributes ------------------------------------------------------------------------------------------------------------- $attr--- An /attribute/ is anything that determines some aspect of a--- diagram's rendering. The standard diagrams library defines several--- standard attributes (line color, line width, fill color, etc.) but--- additional attributes may easily be created. Additionally, a given--- backend need not handle (or even know about) attributes used in--- diagrams it renders.------ The attribute code is inspired by xmonad's @Message@ type, which--- was in turn based on ideas in:------ Simon Marlow.--- /An Extensible Dynamically-Typed Hierarchy of Exceptions/.--- Proceedings of the 2006 ACM SIGPLAN workshop on--- Haskell. <http://research.microsoft.com/apps/pubs/default.aspx?id=67968>.---- | Every attribute must be an instance of @AttributeClass@, which--- simply guarantees 'Typeable' and 'Semigroup' constraints. The--- 'Semigroup' instance for an attribute determines how it will combine--- with other attributes of the same type.-class (Typeable a, Semigroup a) => AttributeClass a where---- | An existential wrapper type to hold attributes. Some attributes--- are affected by transformations and some are not.-data Attribute v :: * where- Attribute :: AttributeClass a => a -> Attribute v- TAttribute :: (AttributeClass a, Transformable a, V a ~ v) => a -> Attribute v--type instance V (Attribute v) = v---- | Wrap up an attribute.-mkAttr :: AttributeClass a => a -> Attribute v-mkAttr = Attribute---- | Wrap up a transformable attribute.-mkTAttr :: (AttributeClass a, Transformable a, V a ~ v) => a -> Attribute v-mkTAttr = TAttribute---- | Unwrap an unknown 'Attribute' type, performing a dynamic (but--- safe) check on the type of the result. If the required type--- matches the type of the attribute, the attribute value is--- returned wrapped in @Just@; if the types do not match, @Nothing@--- is returned.-unwrapAttr :: AttributeClass a => Attribute v -> Maybe a-unwrapAttr (Attribute a) = cast a-unwrapAttr (TAttribute a) = cast a---- | Attributes form a semigroup, where the semigroup operation simply--- returns the right-hand attribute when the types do not match, and--- otherwise uses the semigroup operation specific to the (matching)--- types.-instance Semigroup (Attribute v) where- (Attribute a1) <> a2 =- case unwrapAttr a2 of- Nothing -> a2- Just a2' -> Attribute (a1 <> a2')- (TAttribute a1) <> a2 =- case unwrapAttr a2 of- Nothing -> a2- Just a2' -> TAttribute (a1 <> a2')--instance HasLinearMap v => Transformable (Attribute v) where- transform _ (Attribute a) = Attribute a- transform t (TAttribute a) = TAttribute (transform t a)----------------------------------------------------------------- Styles ----------------------------------------------------------------------------------------------------------------- $style--- A 'Style' is a heterogeneous collection of attributes, containing--- at most one attribute of any given type. This is also based on--- ideas stolen from xmonad, specifically xmonad's implementation of--- user-extensible state.---- | A @Style@ is a heterogeneous collection of attributes, containing--- at most one attribute of any given type.-newtype Style v = Style (M.Map String (Attribute v))- -- The String keys are serialized TypeRep values, corresponding to- -- the type of the stored attribute.--type instance V (Style v) = v---- | Helper function for operating on styles.-inStyle :: (M.Map String (Attribute v) -> M.Map String (Attribute v))- -> Style v -> Style v-inStyle f (Style s) = Style (f s)---- | Extract an attribute from a style of a particular type. If the--- style contains an attribute of the requested type, it will be--- returned wrapped in @Just@; otherwise, @Nothing@ is returned.-getAttr :: forall a v. AttributeClass a => Style v -> Maybe a-getAttr (Style s) = M.lookup ty s >>= unwrapAttr- where ty = show . typeOf $ (undefined :: a)- -- the unwrapAttr should never fail, since we maintain the invariant- -- that attributes of type T are always stored with the key "T".---- | Create a style from a single attribute.-attrToStyle :: forall a v. AttributeClass a => a -> Style v-attrToStyle a = Style (M.singleton (show . typeOf $ (undefined :: a)) (mkAttr a))---- | Create a style from a single transformable attribute.-tAttrToStyle :: forall a v. (AttributeClass a, Transformable a, V a ~ v) => a -> Style v-tAttrToStyle a = Style (M.singleton (show . typeOf $ (undefined :: a)) (mkTAttr a))---- | Add a new attribute to a style, or replace the old attribute of--- the same type if one exists.-setAttr :: forall a v. AttributeClass a => a -> Style v -> Style v-setAttr a = inStyle $ M.insert (show . typeOf $ (undefined :: a)) (mkAttr a)---- | Attempt to add a new attribute to a style, but if an attribute of--- the same type already exists, do not replace it.-addAttr :: AttributeClass a => a -> Style v -> Style v-addAttr a s = attrToStyle a <> s---- | Add a new attribute to a style that does not already contain an--- attribute of this type, or combine it on the left with an existing--- attribute.-combineAttr :: AttributeClass a => a -> Style v -> Style v-combineAttr a s =- case getAttr s of- Nothing -> setAttr a s- Just a' -> setAttr (a <> a') s--instance Semigroup (Style v) where- Style s1 <> Style s2 = Style $ M.unionWith (<>) s1 s2---- | The empty style contains no attributes; composition of styles is--- a union of attributes; if the two styles have attributes of the--- same type they are combined according to their semigroup--- structure.-instance Monoid (Style v) where- mempty = Style M.empty- mappend = (<>)---instance HasLinearMap v => Transformable (Style v) where- transform t = inStyle $ M.map (transform t)---- | Styles have no action on other monoids.-instance Action (Style v) m---- | Type class for things which have a style.-class HasStyle a where- -- | /Apply/ a style by combining it (on the left) with the- -- existing style.- applyStyle :: Style (V a) -> a -> a--instance HasStyle (Style v) where- applyStyle = mappend--instance (HasStyle a, HasStyle b, V a ~ V b) => HasStyle (a,b) where- applyStyle s = applyStyle s *** applyStyle s--instance HasStyle a => HasStyle [a] where- applyStyle = fmap . applyStyle--instance HasStyle b => HasStyle (a -> b) where- applyStyle = fmap . applyStyle--instance HasStyle a => HasStyle (M.Map k a) where- applyStyle = fmap . applyStyle--instance (HasStyle a, Ord a) => HasStyle (S.Set a) where- applyStyle = S.map . applyStyle---- | Apply an attribute to an instance of 'HasStyle' (such as a--- diagram or a style). If the object already has an attribute of--- the same type, the new attribute is combined on the left with the--- existing attribute, according to their semigroup structure.-applyAttr :: (AttributeClass a, HasStyle d) => a -> d -> d-applyAttr = applyStyle . attrToStyle---- | Apply a transformable attribute to an instance of 'HasStyle'--- (such as a diagram or a style). If the object already has an--- attribute of the same type, the new attribute is combined on the--- left with the existing attribute, according to their semigroup--- structure.-applyTAttr :: (AttributeClass a, Transformable a, V a ~ V d, HasStyle d) => a -> d -> d-applyTAttr = applyStyle . tAttrToStyle
− src/Graphics/Rendering/Diagrams/Transform.hs
@@ -1,278 +0,0 @@-{-# LANGUAGE TypeOperators- , FlexibleContexts- , FlexibleInstances- , UndecidableInstances- , TypeFamilies- , MultiParamTypeClasses- , GeneralizedNewtypeDeriving- , TypeSynonymInstances- #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Transform--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ "Graphics.Rendering.Diagrams" defines the core library of primitives--- forming the basis of an embedded domain-specific language for--- describing and rendering diagrams.------ The @Transform@ module defines generic transformations--- parameterized by any vector space.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Transform- (- -- * Transformations-- -- ** Invertible linear transformations- (:-:)(..), (<->), linv, lapp-- -- ** General transformations- , Transformation(..)- , inv, transp, transl- , apply- , papply- , fromLinear-- -- * The Transformable class-- , HasLinearMap- , Transformable(..)-- -- * Translational invariance-- , TransInv(..)-- -- * Vector space independent transformations- -- | Most transformations are specific to a particular vector- -- space, but a few can be defined generically over any- -- vector space.-- , translation, translate- , scaling, scale-- ) where--import Data.AdditiveGroup-import Data.VectorSpace-import Data.AffineSpace ((.-.))-import Data.LinearMap-import Data.Basis-import Data.MemoTrie--import Data.Semigroup-import qualified Data.Map as M-import qualified Data.Set as S--import Graphics.Rendering.Diagrams.Monoids-import Graphics.Rendering.Diagrams.V-import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.HasOrigin----------------------------------------------------------------- Transformations ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Invertible linear transformations ---------------------------------------------------------------------------- | @(v1 :-: v2)@ is a linear map paired with its inverse.-data (:-:) u v = (u :-* v) :-: (v :-* u)-infixr 7 :-:---- | Create an invertible linear map from two functions which are--- assumed to be linear inverses.-(<->) :: (HasLinearMap u, HasLinearMap v) => (u -> v) -> (v -> u) -> (u :-: v)-f <-> g = linear f :-: linear g--instance HasLinearMap v => Semigroup (v :-: v) where- (f :-: f') <> (g :-: g') = f *.* g :-: g' *.* f'---- | Invertible linear maps from a vector space to itself form a--- monoid under composition.-instance HasLinearMap v => Monoid (v :-: v) where- mempty = idL :-: idL- mappend = (<>)---- | Invert a linear map.-linv :: (u :-: v) -> (v :-: u)-linv (f :-: g) = g :-: f---- | Apply a linear map to a vector.-lapp :: (VectorSpace v, Scalar u ~ Scalar v, HasLinearMap u) => (u :-: v) -> u -> v-lapp (f :-: _) = lapply f------------------------------------------------------- Affine transformations ----------------------------------------------------------------------------- | General (affine) transformations, represented by an invertible--- linear map, its /transpose/, and a vector representing a--- translation component.------ By the /transpose/ of a linear map we mean simply the linear map--- corresponding to the transpose of the map's matrix--- representation. For example, any scale is its own transpose,--- since scales are represented by matrices with zeros everywhere--- except the diagonal. The transpose of a rotation is the same as--- its inverse.------ The reason we need to keep track of transposes is because it--- turns out that when transforming a shape according to some linear--- map L, the shape's /normal vectors/ transform according to L's--- inverse transpose. This is exactly what we need when--- transforming bounding functions, which are defined in terms of--- /perpendicular/ (i.e. normal) hyperplanes.--data Transformation v = Transformation (v :-: v) (v :-: v) v--type instance V (Transformation v) = v---- | Invert a transformation.-inv :: HasLinearMap v => Transformation v -> Transformation v-inv (Transformation t t' v) = Transformation (linv t) (linv t')- (negateV (lapp (linv t) v))---- | Get the transpose of a transformation (ignoring the translation--- component).-transp :: Transformation v -> (v :-: v)-transp (Transformation _ t' _) = t'---- | Get the translational component of a transformation.-transl :: Transformation v -> v-transl (Transformation _ _ v) = v---- | Transformations are closed under composition; @t1 <> t2@ is the--- transformation which performs first @t2@, then @t1@.-instance HasLinearMap v => Semigroup (Transformation v) where- Transformation t1 t1' v1 <> Transformation t2 t2' v2- = Transformation (t1 <> t2) (t2' <> t1') (v1 ^+^ lapp t1 v2)--instance HasLinearMap v => Monoid (Transformation v) where- mempty = Transformation mempty mempty zeroV- mappend = (<>)---- | Transformations can act on transformable things.-instance (HasLinearMap v, v ~ (V a), Transformable a)- => Action (Transformation v) a where- act = transform---- | Apply a transformation to a vector. Note that any translational--- component of the transformation will not affect the vector, since--- vectors are invariant under translation.-apply :: HasLinearMap v => Transformation v -> v -> v-apply (Transformation t _ _) = lapp t---- | Apply a transformation to a point.-papply :: HasLinearMap v => Transformation v -> Point v -> Point v-papply (Transformation t _ v) (P p) = P $ lapp t p ^+^ v---- | Create a general affine transformation from an invertible linear--- transformation and its transpose. The translational component is--- assumed to be zero.-fromLinear :: AdditiveGroup v => (v :-: v) -> (v :-: v) -> Transformation v-fromLinear l1 l2 = Transformation l1 l2 zeroV----------------------------------------------------------------- The Transformable class ------------------------------------------------------------------------------------------------ | 'HasLinearMap' is a poor man's class constraint synonym, just to--- help shorten some of the ridiculously long constraint sets.-class (HasBasis v, HasTrie (Basis v), VectorSpace v) => HasLinearMap v-instance (HasBasis v, HasTrie (Basis v), VectorSpace v) => HasLinearMap v---- | Type class for things @t@ which can be transformed.-class HasLinearMap (V t) => Transformable t where-- -- | Apply a transformation to an object.- transform :: Transformation (V t) -> t -> t--instance HasLinearMap v => Transformable (Transformation v) where- transform t1 t2 = t1 <> t2--instance HasLinearMap v => HasOrigin (Transformation v) where- moveOriginTo p = translate (origin .-. p)--instance Transformable t => Transformable (t,t) where- transform t (x,y) = ( transform t x- , transform t y- )--instance Transformable t => Transformable (t,t,t) where- transform t (x,y,z) = ( transform t x- , transform t y- , transform t z- )--instance Transformable t => Transformable [t] where- transform = map . transform--instance (Transformable t, Ord t) => Transformable (S.Set t) where- transform = S.map . transform--instance Transformable t => Transformable (M.Map k t) where- transform = M.map . transform--instance HasLinearMap v => Transformable (Point v) where- transform = papply--instance Transformable m => Transformable (Forgetful m) where- transform = fmap . transform--instance Transformable m => Transformable (Deletable m) where- transform = fmap . transform--instance Transformable Double where- transform = apply--instance Transformable Rational where- transform = apply----------------------------------------------------------------- Translational invariance ----------------------------------------------------------------------------------------------- | @TransInv@ is a wrapper which makes a transformable type--- translationally invariant; the translational component of--- transformations will no longer affect things wrapped in--- @TransInv@.-newtype TransInv t = TransInv { unTransInv :: t }- deriving (Show, Semigroup, Monoid)--type instance V (TransInv t) = V t--instance VectorSpace (V t) => HasOrigin (TransInv t) where- moveOriginTo = const id--instance Transformable t => Transformable (TransInv t) where- transform tr (TransInv t) = TransInv (translate (negateV (transl tr)) . transform tr $ t)----------------------------------------------------------------- Generic transformations ------------------------------------------------------------------------------------------------ | Create a translation.-translation :: HasLinearMap v => v -> Transformation v-translation = Transformation mempty mempty---- | Translate by a vector.-translate :: (Transformable t, HasLinearMap (V t)) => V t -> t -> t-translate = transform . translation---- | Create a uniform scaling transformation.-scaling :: (HasLinearMap v, Fractional (Scalar v))- => Scalar v -> Transformation v-scaling s = fromLinear lin lin -- scaling is its own transpose- where lin = (s *^) <-> (^/ s)---- | Scale uniformly in every dimension by the given scalar.-scale :: (Transformable t, Fractional (Scalar (V t)), Eq (Scalar (V t)))- => Scalar (V t) -> t -> t-scale 0 = error "scale by zero! Halp!" -- XXX what should be done here?-scale s = transform $ scaling s
− src/Graphics/Rendering/Diagrams/UDTree.hs
@@ -1,161 +0,0 @@-{-# LANGUAGE DeriveFunctor- , TypeOperators- , FlexibleContexts- #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.UDTree--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Rose (n-way) trees with both upwards- and downwards-traveling--- monoidal annotations, used as the basis for representing diagrams.----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.UDTree- (- -- * UD-trees- UDTree(..)-- -- * Constructing UD-trees- , leaf, branchD, branch-- -- * Modifying UD-trees- , applyD, applyUpre, applyUpost, mapU-- -- * Accessors and destructors- , getU, getU', foldUD, flatten-- ) where--import Data.Semigroup--import Graphics.Rendering.Diagrams.Monoids-import Graphics.Rendering.Diagrams.MList---- | Abstractly, a UDTree is a rose (n-way) tree with data at the--- leaves and two types of monoidal annotations, one (called @u@)--- travelling \"up\" the tree and one (called @d@) traveling--- \"down\".------ Specifically, every node (both leaf nodes and internal nodes)--- has two annotations, one of type @d@ and one of type @u@,--- subject to the following constraints:------ * The @d@ annotation at a leaf node is equal to the 'mconcat' of--- all the @d@ annotations along the path from the root to the leaf--- node.------ * The @u@ annotation at an internal node is equal to @v1--- ``mappend`` (mconcat us) ``mappend`` v2@ for some values @v1@--- and @v2@ (possibly 'mempty'), where @us@ is the list (in--- left-right order) of the @u@ annotations on the immediate child--- nodes of the given node. Intuitively, we are \"caching\" the--- @mconcat@ of @u@ annotations from the leaves up, except that at--- any point we may insert \"extra\" information.------ In addition, @d@ may have an /action/ on @u@ (see the 'Action'--- type class, defined in "Graphics.Rendering.Diagrams.Monoids"), in--- which case applying a @d@ annotation to a tree will transform all--- the @u@ annotations by acting on them. The constraints on @u@--- annotations are maintained since the action is required to be a--- monoid homomorphism.--data UDTree u d a- = Leaf u a- | Branch u [d] [UDTree u d a]- deriving (Functor)---- XXX need to sort out all the semigroup/monoid stuff in here!--instance (Action d u, Monoid u, Monoid d) => Semigroup (UDTree u d a) where- t1 <> t2 = branch [t1,t2]---- | @UDTree@s form a monoid where @mappend@ corresponds to adjoining--- two trees under a common parent root. Note that this technically--- does not satisfy associativity, but it does with respect to--- 'flatten' which is what we really care about. @mconcat@ is--- specialized to put all the trees under a single parent.-instance (Action d u, Monoid u, Monoid d) => Monoid (UDTree u d a) where- mempty = Branch mempty mempty []- t1 `mappend` t2 = branch [t1,t2]- mconcat = branch---- | Construct a leaf node from a @u@ annotation and datum.-leaf :: u -> a -> UDTree u d a-leaf = Leaf---- | Construct a branch node with an explicit @d@ annotation.-branchD :: (Action d u, Monoid u) => d -> [UDTree u d a] -> UDTree u d a-branchD d ts = Branch (mconcat . map getU $ ts) [d] ts---- | Construct a branch node with a default (identity) @d@ annotation.-branch :: (Action d u, Monoid u, Monoid d) => [UDTree u d a] -> UDTree u d a-branch ts = Branch (mconcat . map getU $ ts) [] ts---- | Get the @u@ annotation at the root.-getU :: Action d u => UDTree u d a -> u-getU (Leaf u _) = u-getU (Branch u ds _) = foldr act u ds---- | Get a particular component from a the @u@ annotation at the root.--- This method is provided for convenience, since its context only--- requires an action of @d@ on @u'@, rather than on @u@ in its--- entirety.-getU' :: (Action d (u' ::: Nil), u :>: u') => UDTree u d a -> u'-getU' (Leaf u _) = get u-getU' (Branch u ds _) = hd $ foldr act (get u ::: Nil) ds- where hd (u' ::: Nil) = u'- hd (Missing _) = error "Impossible case in UDTree.getU' (hd)"---- | Add a @d@ annotation to the root, combining it (on the left) with--- any pre-existing @d@ annotation, and transforming all @u@--- annotations by the action of @d@.-applyD :: Action d u => d -> UDTree u d a -> UDTree u d a-applyD d l@(Leaf {}) = Branch (getU l) [d] [l]-applyD d (Branch u ds ts) = Branch u (d : ds) ts---- | Add a @u@ annotation to the root, combining it (on the left) with--- the existing @u@ annotation.-applyUpre :: (Semigroup u, Action d u) => u -> UDTree u d a -> UDTree u d a-applyUpre u' (Leaf u a) = Leaf (u' <> u) a-applyUpre u' b = Branch (u' <> getU b) [] [b]---- | Add a @u@ annotation to the root, combining it (on the right) with--- the existing @u@ annotation.-applyUpost :: (Semigroup u, Action d u) => u -> UDTree u d a -> UDTree u d a-applyUpost u' (Leaf u a) = Leaf (u <> u') a-applyUpost u' b = Branch (getU b <> u') [] [b]---- | Map a function over all the @u@ annotations. The function must--- be a monoid homomorphism, and must commute with the action of @d@--- on @u@. That is, to use @mapU f@ safely it must be the case that--- @f (act d u) == act d (f u)@.-mapU :: (u -> u') -> UDTree u d a -> UDTree u' d a-mapU f (Leaf u a) = Leaf (f u) a-mapU f (Branch u ds ts) = Branch (f u) ds (map (mapU f) ts)---- | A fold for UDTrees.-foldUD :: (Monoid r, Semigroup d, Monoid d, Action d u)- => (u -> d -> a -> r) -- ^ Function for processing leaf nodes.- -- Given the u annotation at this node, the- -- 'mconcat' of all d annotations above, and the- -- leaf value.- -> (u -> d -> r -> r) -- ^ Function for processing internal- -- nodes. Given the u and d- -- annotations at this node and the- -- 'mconcat' of the recursive results.- -> UDTree u d a -> r-foldUD = foldUD' mempty -- Pass along accumulated d value- where foldUD' d l _ (Leaf u a)- = l (act d u) d a- foldUD' d l b (Branch u ds ts)- = b (act (d <> d') u) d' (mconcat $ map (foldUD' (d <> d') l b) ts)- where d' = mconcat ds---- | A specialized fold provided for convenience: flatten a tree into--- a list of leaves along with their @d@ annotations.-flatten :: (Semigroup d, Monoid d, Action d u) => UDTree u d a -> [(a,d)]-flatten = foldUD (\_ d a -> [(a,d)]) (\_ _ r -> r)
− src/Graphics/Rendering/Diagrams/Util.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.Util--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Various internal utilities for the diagrams project.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Util- (- -- * Vectors-- withLength-- ) where--import Data.VectorSpace---- | Produce a vector with the specified length in the same direction--- as the given vector.-withLength :: (InnerSpace v, Floating (Scalar v)) => Scalar v -> v -> v-withLength l v = (l / magnitude v) *^ v
− src/Graphics/Rendering/Diagrams/V.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE TypeFamilies #-}---------------------------------------------------------------------------------- |--- Module : Graphics.Rendering.Diagrams.MList--- Copyright : (c) 2011 diagrams-core team (see LICENSE)--- License : BSD-style (see LICENSE)--- Maintainer : diagrams-discuss@googlegroups.com------ Type family for identifying associated vector spaces.-----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.V- ( V-- ) where--import Data.Set-import Data.Map----------------------------------------------------------------- Vector spaces ------------------------------------------------------------------------------------------------------------ | Many sorts of objects have an associated vector space in which--- they live. The type function @V@ maps from objects to their--- associated vector space.-type family V a :: *--type instance V Double = Double-type instance V Rational = Rational---- Note, to use these instances one often needs a constraint of the form--- V a ~ V b, etc.-type instance V (a,b) = V a-type instance V (a,b,c) = V a--type instance V (a -> b) = V b-type instance V [a] = V a-type instance V (Set a) = V a-type instance V (Map k a) = V a