Git Product home page Git Product logo

diagrams-lib's Introduction

Build Status

diagrams is a full-featured framework and domain-specific language (embedded in Haskell) for creating declarative vector graphics and animations.

This package is just a convenient wrapper around the diagrams-core, diagrams-lib, diagrams-svg, and diagrams-contrib packages, so they can be installed with a single cabal install --lib diagrams command.

The package also comes with flags to enable six different backends. The native SVG backend is enabled by the -fsvg flag and is enabled by default. If you don't want it, you must explicitly disable it with -f-svg.

The native postscript backend is disabled by default but can be enabled by the -fps flag.

The cairo backend is disabled by default but can be selected with the -fcairo flag. In addition, the GTK backend is based on the cairo backend (but split into a separate package to make installing the cairo backend easier). It can be selected with the fgtk flag.

The native rasterific backend which is disabled by default but can be selected with the -frasterific flag.

The native canvas backend which is disabled by default but can be selected with the -fcanvas flag.

Installation

cabal update && cabal install --lib diagrams

or, to get the postscript backend in addition to the SVG backend:

cabal update && cabal install --lib -fps diagrams

or, to get the cairo backend in addition to the SVG backend:

cabal update && cabal install gtk2hs-buildtools && cabal install --lib -fcairo diagrams

Reporting bugs

Issue trackers for all diagrams-related repositories are hosted under the diagrams organization on github. If you know the specific package containing the bug, report it in the issue tracker specific to that package (for example, diagrams-lib). Otherwise, just report the issue in the issue tracker for the general diagrams repository.

Further reading

For more information, including a gallery of examples, tutorial, and user manual, see the diagrams website. For help, join the #diagrams IRC channel on Freenode or the mailing list.

diagrams-lib's People

Contributors

alexknauth avatar bergey avatar bodigrim avatar byorgey avatar cchalmers avatar deepakjois avatar dfordivam avatar fegu avatar fryguybob avatar ggreif avatar haasn avatar ian-ross avatar jeffreyrosenbluth avatar lrworth avatar mathnerd314 avatar mchav avatar mgsloan avatar mpilgrem avatar ocharles avatar pnutus avatar recursion-ninja avatar robx avatar ryanglscott avatar sattlerc avatar sergv avatar sid-kap avatar taruti avatar twinside avatar vaibhavsagar avatar walck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

diagrams-lib's Issues

Add shearing transformations to standard library

(Imported from http://code.google.com/p/diagrams/issues/detail?id=40. Original issue from [email protected] on August 16, 2011, 08:24:59 PM UTC)

Diagrams.TwoD.Transform ought to include some functions to perform shears. I suppose something like

{{{
-- | @shearx d@ is the linear transformation which is the identity on
-- y coordinates and sends @(0,1)@ to @(d,1)@.
shearX :: (Transformable t, V t ~ R2) => Double -> t -> t
}}}

etc., should do nicely.

Unfortunately we run into linguistic trouble here with the noun/verb scheme for naming transformation combinators: "shear" is both noun and verb. I suppose we could get away with "shearing".

Allow the user to choose the fill rule used for paths when stroking

(Imported from http://code.google.com/p/diagrams/issues/detail?id=28. Original issue from [email protected] on May 4, 2011, 08:00:07 PM UTC)

The stroke and strokeT functions should take an extra argument (actually, we should make functions stroke' and strokeT' that take a record of optional arguments, like e.g. cat) specifying the "fill rule" (winding rule or even/odd; default should probably be winding). This should have two effects: 1. use the appropriate testing function for constructing the stroked diagram's Query; 2. set an attribute on the stroked diagram informing the backend which fill rule to use. The Cairo backend should also be updated to take this attribute into account.

Add support for path-oriented diagrams.

(Imported from http://code.google.com/p/diagrams/issues/detail?id=26. Original issue from [email protected] on April 30, 2011, 03:07:20 PM UTC)

I don't know if path-oriented is the best name or not but on the simple end of things this is arrows at the end of paths. On the more complex end of things is custom stroking. Common to both of these ends is orientation at any point of the path (first derivative with respect to the parameter in the case of a segment).

Independently control origin placement and stacking order when using `beside`

If you use beside v d1 d2 to create a compound diagram (or anything based on beside, like (|||) or (===)), you get

  • the local origin at the local origin of d1
  • d1 on top of d2

but sometimes you might want something different. If you want d2's local origin to be used, you can do beside (negateV v) d2 d1. But if you want to independently control the stacking order as well it gets hairy quickly. (The stacking order can certainly matter, e.g. when working with a diagram whose visual representation extends outside its envelope. Even for diagrams with default envelopes, their bounding lines overlap, which is noticeable if the lines are thick enough.)

We should add a function beside' which extends beside with a record of options to allow independent control of these things. (And perhaps allow for adding spacing between diagrams, much like cat' already does, while we are at it.) I haven't yet thought about what the API for those options should look like.

A further enhancement would be to add similar options for cat' and friends: to be able to specify which of the n local origins should be used, and somehow specify an arbitrary stacking order for the list of diagrams as well.

reverseTrail should not generate extra segments for closed trails

(Imported from http://code.google.com/p/diagrams/issues/detail?id=50. Original issue from [email protected] on September 6, 2011, 08:53:32 PM UTC)

For reference, see this darcs log message:

Fri Aug 19 10:05:25 EDT 2011 Brent Yorgey <[email protected]>

  • fix bug in reverseTrail: should not delete first segment, it might be a Bezier!
    reverseTrail has the unfortunate property that it adds a segment every time it is called,
    since it must insert the "implicit" segment at the end, even if it is essentially Linear (0,0)
    (or, more likely, Linear with two very small nonzero values, due to imprecision). This means
    that reverseTrail is not actually self-inverse, although it will probably LOOK like it is.
    I wonder whether we ought to explicitly store the final segment of a closed trail.

I think it would actually be better to stop trying so hard to maintain the same "base point" for closed trails. That is, when reversing a closed trail, the new base point should be the endpoint of the last explicit segment, exactly the same as if we were reversing an open trail. This might be a bit unintuitive but given that we store the closing segment implicitly it's really the only way to do things properly, so that we get laws such as reverseTrail . reverseTrail = id.

Perhaps we should also add a function 'completeTrail' (or something to that effect) which turns the implicit segment of a closed trail into an explicit segment. That way you could always get the behavior you might otherwise expect from reverseTrail on a closed trail by first calling completeTrail. Of course, it seems like completeTrail ought to be idempotent but that would not be the case for the obvious implementation.

Perhaps instead of a Boolean indicating an implicit closure we ought to have something like

data Closed v = Open | LClosed | BClosed v v

where (BClosed c1 c2) indicates closing the path with a Bezier segment with control points c1 and c2, and an implicit endpoint.

Enhancements for `arc`s.

The documentation for arc states that the output is always CCW. The implementation however will give CW arcs. See this example, current output, and correct output.

Only giving one direction is likely to be the more consistent option. I think we should change the implementation to always output CCW but also give some guidance and more functions for common situations. In fact there are many other common arc creation scenarios that we should handle.

As far as I know only roundedRect' will have to be fixed with this change, but we should grep for other uses of arc.

Path expansion.

The expandPath function should be called scalePath. In its place should be real path expansion. For a non-closed path this is essentially stroking with a constant brush. For a closed path we can either give a path that has both the outside expansion and a negative inside expansion or just give the outside or inside (probably based on positive or negative radius). There are many options for what to do here and we should support several of them. Bezier curves have no closed form expansion with a single segment and as far as I know multiple segments can only approximate. There are lots of weird corner case, but if the end goal is to just fill it isn't very hard to get it right with a winding fill mode. For a cleaner path most of the corner cases can be handled by just considering adjacent segments.

I've got most of the work done for a few styles of corners for non-closed paths at this point. The rounded corner paths and polygons #36 is related to this issue.

Limited pure font support

It would be nice to have at least one "pure" font that would render on any backend and can be measured as a pure computation. Encoding the font glyphs as diagrams only gets us part of the way to this goal as the space taken up by the rendering of a word is not simply the horizontal concatenation of the glyphs but involves lots of nice typesetting details. The thought is that we might be able to get close to having horizaontal concatenation work by comparing output if all pairs of letters with correct font rendering and some simple rules for horizontal spacing involving envelope and trace (the parameters to these rules would be discovered in an automated way).

Given this pure font that is close we can render that font directly or use it as a stand-in for measuring fonts and let the backend use either the same font with its own engine or a different font and hope that it is close.

Function to convert angles into 2D unit vectors

(Imported from http://code.google.com/p/diagrams/issues/detail?id=49. Original issue from [email protected] on September 6, 2011, 04:54:01 PM UTC)

Suggested by Anton Kholomiov <[email protected]>:

> - I'm using it with function e (like complex vector representation e^ix)
>
> e a = (cos $ tau_a, sin $ tau * a)
>
> And we can define rectangle point-chain like this:
>
> [e 0, 4 ^_ e 0.25, e 0.5, 4 ^* e 0.75]
>
> With e you can define
>
> unitX = e 0
> unitY = e 0.25
> unit_X = -1 ^* e 0

I don't think 'e' is the best name since it is not very self-documenting (although it is suggestive of the polar form of complex numbers). Also, it should take any Angle instance rather than being limited to CircleFrac. But the idea is good, and we ought to add such a function to Diagrams.TwoD.Util (well... 'direction' is already in that module, and this new function should go in the same module as direction, since they are dual, but perhaps both should be moved to a new module like Diagrams.TwoD.Vector).

Reimplement Diagrams.TwoD.Ellipse in terms of Diagrams.TwoD.Arc

(Imported from http://code.google.com/p/diagrams/issues/detail?id=53. Original issue from [email protected] on September 8, 2011, 08:26:47 PM UTC)

We are currently in the awkward situation that almost every shape function in the standard library returns any instance of PathLike, EXCEPT 'circle' and friends, which can only return Diagrams. This is because circle is implemented in terms of an Ellipse primitive rather than a path. However, now that we can generate approximate circular paths using the Arc module, there's no particular reason to keep doing this. The benefit of switching is that 'circle' and the other functions in Ellipse would now work just like all the other shape primitives, as users would expect. I don't see any downside (other than throwing away all the nice work in the Ellipse module, but that's life).

To clarify, the API of the Ellipse module should stay exactly the same, except that Diagram return types should be generalized to PathLike p => p.

Grid layout module

(Imported from http://code.google.com/p/diagrams/issues/detail?id=70. Original issue from [email protected] on March 9, 2012, 10:42:48 PM UTC)

There should be a diagrams-lib module with tools for laying out items in a grid/lattice. Not sure exactly what the API should look like, but ideally it would have features like:

  • ability to specify arbitrary basis vectors in order to get non-axis aligned grids, or even "parallelogram-shaped" grids
  • (optional) automatic calculation of grid spacing based on max size of items in the grid
  • it can probably be made vector-space-agnostic, e.g. there's no particular reason we can't have 3D grids

Text alignment should be with respect to descent and ascent lines rather than text bounding box

(Imported from http://code.google.com/p/diagrams/issues/detail?id=33. Original issue from [email protected] on June 8, 2011, 05:14:26 PM UTC)

Currently text is aligned with respect to its actual bounding box; instead, it ought to be aligned with respect to a box with left and right edges given by the bounding box and top and bottom edges given by the ascent and descent line of the font. (See
http://cairographics.org/tutorial/#L1understandingtext). The current approach means that different text elements placed next to each other are not vertically aligned. For example, this looks really bad:

{{{
letterBlock c = square # scale 1.5 <> text [c]

example = hcat $ map letterBlock ['a'..'z']
}}}

Also, the code for accomplishing this ought to be factored out of the cairo backend into diagrams-lib so other backends can make use of it.

align and friends should be in terms of a new 'Alignable' class instead of 'Boundable'

(Imported from http://code.google.com/p/diagrams/issues/detail?id=64. Original issue from [email protected] on January 22, 2012, 06:22:36 PM UTC)

The fact that 'align' and friends currently require a Boundable constraint is an implementation detail. Things that are Boundable can certainly be aligned using the current code. However, there are other things which are not Boundable but which it makes sense to align: the particular motivating example being animations.

Just as was already done with the new Juxtaposable class, aligning ought to be done in terms of a new class, something like

class Alignable a where
alignBy :: V a -> Scalar (V a) -> a -> a

with a function 'alignByDefault' provided which gives the current implementation in terms of Boundable etc. Then we can also make an Alignable instance for animations, which simply does the alignment pointwise over time.

'image' should be in IO

(Imported from http://code.google.com/p/diagrams/issues/detail?id=59. Original issue from [email protected] on November 6, 2011, 06:06:54 PM UTC)

Currently we have on the user side

image :: Renderable Image b => FilePath -> Double -> Double -> Diagram b R2

and on the backend side

data Image = Image { imgFile :: FilePath
, imgSize :: SizeSpec2D
, imgTransf :: T2
}

However, there are some problems with this approach. First of all, we are forcing every backend that supports Image to be inside IO -- diagrams-cairo is already in IO, but diagrams-svg isn't.

Another problem is that the user can't do anything if the image loading process fails. If 'image' was in IO, the user would be able to catch an exception and do something else (like drawing something instead of showing the image).

Yet another problem is that the diagrams library isn't able to do anything about the image's size, since it doesn't know anything about it.

So, what we need is something like

class SupportsImage b where
image :: SupportsImage b => FilePath -> IO (Diagram b R2)

Each backend may do whatever it wants to load the image. Note that it returns a Diagram, so the backend is free to choose its internal representation of an image. For example, if the user gives an SVG image, 'diagrams-svg' may choose to just inline it on the <defs> of the output.

On the user side, this API also has advantages. First of all, 'image' is now in IO and the user is back in control. Also, the user doesn't need to supply the dimensions: the backend is able to load the image and get the correct dimensions.

Tools for more accurate boundary calculations in common cases

(Imported from http://code.google.com/p/diagrams/issues/detail?id=60. Original issue from [email protected] on November 11, 2011, 03:07:56 PM UTC)

(09:46) < Taejo> are the bounds functions for polygons exact?
(09:47) < byorgey> Taejo: they are exactly what they are defined to be =)
(09:47) < byorgey> Taejo: the bounding function tells you how far you have to go to reach a line which completely encloses the polygon
(09:48) < byorgey> Taejo: so placing two things next to each other means there will be a perpendicular line with one on one side and one on the other
(09:48) < Taejo> byorgey, but they are approximations, in general?
(09:48) < byorgey> Taejo: no
(09:49) < fryguybob> For anything convex the union of bounds calls on all "angles" would be the exact complement of the shape.
(09:49) < byorgey> Taejo: they are exact. Sorry, I wasn't sure what you were asking at first.
(09:50) < Taejo> no problem. let me upload a picture to show what's going on
(09:50) < Taejo> http://i.imgur.com/EtmX8.png
(09:51) < byorgey> Taejo: ah, yeah, I see what's going on
(09:51) < byorgey> Taejo: it follows from what I said if you think about it carefully
(09:52) < Taejo> ah, you're right
(09:52) < Taejo> I see now
(09:52) < byorgey> if you ask for the "boundary" of a polygon in a direction not perpendicular to one of its edges...
(09:52) < byorgey> it is a bit annoying though. I'm trying to think of the best way to do what you want to do.
(09:53) < byorgey> Taejo: well, one easy solution would be to draw the lines between the centers of the polygons
(09:53) < byorgey> and just draw the polygons on top of them
(09:54) < Taejo> byorgey, yeah, that works... until I add arrowheads :(
(09:54) < byorgey> ah, hmm
(09:54) < Taejo> I think in that case I'll just have to live with the gaps
(09:56) < fryguybob> I think we could make an approximate solution that gave any desired accuracy.
(09:56) < byorgey> yeah, I've thought about things like that before
(09:57) < fryguybob> Not for bounds in general, but for this specific kind of case.
(09:57) < byorgey> you can automatically vary the angle at which you query the bounding function to try to find a local minimum
(09:57) < byorgey> we could also put in a special case for polygons which would work exactly
(09:57) < fryguybob> true
(09:58) < byorgey> well, for arbitrary paths really
(09:58) < Taejo> byorgey, I'm working on a library to draw graphs with arbitrary diagrams as nodes
(09:58) < byorgey> Taejo: cool!
(09:58) < Taejo> I could have a special case for when the nodes are described by a path
(10:00) < byorgey> Taejo: I don't think this is something your graph library ought to have special cases for
(10:00) < byorgey> we ought to put tools in the diagrams standard library to help deal with such situations
(10:01) < byorgey> hmm, rather than special-casing the bounding function code, we could have something which extends a path right up to a diagram
(10:01) < byorgey> since we do have more exact coverage information from the query
(10:02) < byorgey> you could specify an extension length which is long enough and then it would do a binary search
(10:02) < fryguybob> Something like binary search between the center and the bounds?
(10:02) < byorgey> exactly
(10:02) < byorgey> oh! even better.
(10:03) < fryguybob> I think that will only work if you are convex.
(10:03) < byorgey> true
(10:03) < byorgey> I actually meant a binary search between the end of the path and some specified distance beyond it
(10:04) < fryguybob> Yeah, holes are a problem
(10:04) < byorgey> but exact boundary points for convex shapes via binary search would be good too
(10:04) < fryguybob> Most of the time it would probably work well though.
(10:05) < byorgey> yup

Add 3D-specific primitives, transformations, etc. to the standard library

(Imported from http://code.google.com/p/diagrams/issues/detail?id=31. Original issue from [email protected] on May 16, 2011, 08:24:23 PM UTC)

Design and implement a ThreeD.* set of modules, parallel to the 2D-specific TwoD.* modules.

  • 3D primitive shapes
  • 3D transformations
  • 3D alignment
  • etc.

This is technically separate from actually making a 3D backend although of course working on this ticket will probably not be much fun without a 3D backend.

More combinators in D.Combinators

(Imported from http://code.google.com/p/diagrams/issues/detail?id=3. Original issue from [email protected] on December 23, 2010, 10:17:59 PM UTC)

Fill out the Combinators module with lots of combinators for putting diagrams together. Use the original diagrams library for inspiration. However, I think we should use a record-passing style where each function takes a record of arguments, which has a default instance implemented via a Data.Default instance. Then users get to do named argument passing by passing the default record and overriding selected arguments.

An (incomplete) list of the sort of combinators we will need:

  • union = mconcat (put a bunch of diagrams on top of one another) * cat (lay out a bunch of diagrams next to each other)

    this one should have lots of arguments in its record, e.g. direction along which to lay out the diagrams; separation between diagrams; alignment; distribution method (see e.g. inkscape's align/distribute panel for inspiration)

It may be worth predefining a few aliases for cat with one or two arguments filled in, e.g. hcat and vcat for the common cases of laying out diagrams horizontally or vertically, and so on.

  • along (lay out diagrams along a path)

    not sure of the right API for this, but there might be options for spacing, distribution, that sort of thing. In fact, 'cat' could (and probably should) be implemented in terms of 'along', by first creating an appropriate (straight) path and then calling 'along'. Perhaps 'cat' and 'along' really ought to be unified into one primitive.

Generalize showOrigin function

(Imported from http://code.google.com/p/diagrams/issues/detail?id=46. Original issue from [email protected] on September 3, 2011, 07:05:03 PM UTC)

The showOrigin function (in Diagrams.TwoD.Model) ought to be generalized to take a few more options to control things like the size and color of the dot. No need to go overboard -- after all, it's quite easy to just use atop if you want something more general -- but it would be nice if, say, showOrigin didn't become useless when trying to visualize the origin of something red.

clipTo function

(Imported from http://code.google.com/p/diagrams/issues/detail?id=76. Original issue from [email protected] on March 15, 2012, 12:17:22 AM UTC)

Diagrams.TwoD.Path defines a function

clipBy :: (HasStyle a, V a ~ R2) => Path R2 -> a -> a

which applies a clipping path attribute to a diagram, but does not alter its envelope. We should also define a function 'clipTo' which does 'clipBy' and also clips the diagram's envelope. This should be possible, but is not entirely straightforward since it requires taking a pointwise minimum of the two envelopes, whereas the monoid instance for Envelope uses a pointwise maximum. But it should not be too hard to take a look at how the actual Monoid instance for Envelope is implemented, and imitate it.

stroke sets the fill rule attribute to a default value, so it can't be changed later

(Imported from http://code.google.com/p/diagrams/issues/detail?id=52. Original issue from [email protected] on September 8, 2011, 12:37:25 AM UTC)

One might expect to be able to say something like

stroke p # fillRule EvenOdd

but currently this does not work, since stroke is defined as stroke' def, and stroke' takes a record of options including a fill rule, which it uses to create the proper Query as well as set a FillRule attribute. So (stroke p) results in the FillRule attribute being implicitly set to the default fill rule, and subsequent calls to fillRule do not affect it.

The problem is that if we want the fill rule to affect the Query, it must be done at the time that stroke' is called. I can think of several options:

  • stroke' uses the provided FillRule to create the Query only, and does not call fillRule to set a FillRule attribute. However, this leads to unintuitive behavior: calling stroke' with a FillRule won't cause it to be drawn using that FillRule, and conversely using (# fillRule blah) won't affect the Query.
  • make the type of the stroke' record field (Maybe FillRule) and have Nothing be the default. But this is also somewhat unintuitive, since the Query has to be created (using some default) anyway.
  • another possibility is to make the fill rule an inherent property of the Path type itself. But it would be strange to have this particular attribute singled out; and abstractly, Paths have nothing to do with fill rules. Fill rules don't even make sense for paths in dimensions other than 2 anyway.

Other suggestions welcome...

Split PathLike, Trail, and Path into separate modules

(Imported from http://code.google.com/p/diagrams/issues/detail?id=51. Original issue from [email protected] on September 6, 2011, 09:03:59 PM UTC)

Currently they are all in Diagrams.Path, but it's gotten big enough that it really makes sense to split them out. In fact, perhaps we should have Diagrams.Path.Segment, Diagrams.Path.Trail, Diagrams.Path.Path, and Diagrams.Path.PathLike? This is not too hard in principle, but note that it also requires updating

  • any modules that import them, including examples
  • the diagrams manual, where it refers to the Diagrams.Path module

Parametric paths with active + cubicSpline

It just occurred to me today that we have a lovely way to create arbitrary parametric paths: just create a value of type Active P2, sample it finely enough, and pass the sampled points through cubicSpline. Someone should make a module putting this together with a nice API.

Add generic 'extent' and 'breadth' ? functions

(Imported from http://code.google.com/p/diagrams/issues/detail?id=45. Original issue from [email protected] on September 3, 2011, 04:42:54 PM UTC)

Diagrams.TwoD.Util has function like extentX, extentY, height, and width; there ought to be generic (vector-space polymorphic) variants which take as an extra argument a vector specifying the direction in which to measure the extent/width. Then extentX etc. can just be specialized variants of the more generic function.

Generalization of color space used in rendering

Instead of the Color instance itself being in charge of the color space to render it to, this would ideally be the backend's job.

Otherwise, inconsistent Color instances could result in an inconsistent diagram, since the user may want to use color spaces other than sRGB.

The proposed solution would be to either parametrize toRGBA over the RGBSpace to use; or ideally, don't provide toRGBA at all and simply provide toColour :: a -> Colour Double and toAlpha :: a -> Double.

text on zero width rect leads to nans

(Reported by tad.doxsee at gmail; imported from http://code.google.com/p/diagrams/issues/detail?id=90)

text "junk" # fontSize 10 <> rect 0 20 

results in nans in the svg file and the entire svg is blank in a browser. If the rect has nonzero width

text "junk" # fontSize 10 <> rect 50 20

then everything is OK.

What version of the product are you using? 0.5
On what operating system? Ubuntu 12.04
Using the Cairo backend.

More problems with beside + mempty

(Imported from http://code.google.com/p/diagrams/issues/detail?id=82. Original issue from [email protected] on May 24, 2012, 08:10:44 PM UTC)

Consider these example definitions:

b = hcat' with { sep = 0.2 } [circle 1, mempty, mempty, mempty, circle 1]
d = b <> square 1

b = mempty ||| circle 1
d = b <> square 1

In both cases the output is not what I would expect. Either diagrams or my expectations need to be fixed, and the results thoroughly documented in either case.

Turn R2 into D2 (Generalize R2 to any numeric type)

Imported from diagrams/diagrams-core#20, since it actually affects the diagrams-lib repo. See the discussion there for more information. The basic idea is to create a new type

newtype D2 a = D2 { unD2 :: (a,a) }

and to define

type R2 = D2 Double
type Q2 = D2 Rational -- while we're at it

and to then generalize type signatures mentioning R2 to be generic over any D2 a where a is a type with the required properties. For example, we would generalize

(===) :: (Juxtaposable a, V a ~ R2, Semigroup a) => a -> a -> a

to

(===) :: (Juxtaposable a, V a ~ D2 b, Floating b, Semigroup a) => a -> a -> a

or something similar.

This process should be mostly mechanical, except that some care will be needed in coming up with the right (minimal) constraints. For example, I don't actually know whether Floating is required for (===), or if something like Fractional (or something else entirely) will do.

This will pave the way for doing various fun things with 2D diagrams over generalized numeric types, such as

  • doing optimal layout with automatic differentiation
  • positioning diagrams via constraints instead of absolutely, and solving the constraints later
  • reifying diagrams in order to compile them to javascript or some other language

Of course, the same should also be done for 3D diagrams but that can wait a bit.

Bitmap support

(Imported from http://code.google.com/p/diagrams/issues/detail?id=75. Original issue from [email protected] on March 14, 2012, 11:51:41 PM UTC)

Sometimes users want to render some sort of grid of a large number of pixels as part of a diagram; creating a grid of squares (e.g. using hcat and vcat) is not a very efficient way to this, for those backends which can support bitmaps more directly. The idea would be to add some sort of new "bitmap" primitive to diagrams-lib, which is stored in a memory-efficient way and can be rendered more directly by some backends. Perhaps a fallback method could also be provided to convert a bitmap into a grid of squares, for use by those backends which cannot directly support bitmaps.

Merge polygon code from Dmitry Olshansky

(Imported from http://code.google.com/p/diagrams/issues/detail?id=2. Original issue from [email protected] on December 23, 2010, 10:17:07 PM UTC)

Need a collection of standard shapes. Try to use the existing path mechanisms whenever possible (the existing Box type is a bad example of the sort of thing that should be done, and should be removed and replaced with a path-based version).

An (inexhaustive) list of the shapes that should be available: regular polygons of any number of sides; 45-45-90 triangle; 30-60-90 triangle; stars parameterized by number of points and perhaps other size/shape parameters; rounded rectangles; rounded polygons in general.

Control over boundary conditions on cubic splines.

(Imported from http://code.google.com/p/diagrams/issues/detail?id=66. Original issue from [email protected] on February 16, 2012, 01:36:31 PM UTC)

In some cases it would be nice to combine cubic splines with other shapes and retain some degree of smoothness. For instance, you might want a specific segment to be straight. Metapost, NURBS, and Spiro, all allow for building curves like this, but I think that cubic splines could also be formulated with boundary conditions much like how the join in a closed cubic spline is solved with a fully symmetric tri-diagonal matrix.

hcat is really *terrible* performance-wise

(Imported from http://code.google.com/p/diagrams/issues/detail?id=57. Original issue from [email protected] on November 2, 2011, 06:27:13 PM UTC)

Hello!

I'm sorry that I didn't do my homework to investigate the "why", but I've included a very simple test case. You may compile and run the test as follows:

$ ghc -O --make -fforce-recomp -rtsopts bug.hs
$ ./bug -o t.png --selection=??? +RTS -s

where ??? may be "hcat", "foldl1", "foldr1" or "foldTree". The program just concatenates 1,000 (rect 1 1)s. On my computer, I get the following:

hcat: 23s, 130 MiB
foldr1: 30s, 69 MiB
foldl1: 27s, 62 MiB
foldTree: 1s, 7 MiB

Concatenating one thousand unit squares shouldn't take more than 20 seconds =). This is a showstopper for me, so I've reimplemented hcat (see hcatB at the end of [1])

Cheers!

[1] https://patch-tag.com/r/felipe/hierarchical-clustering-diagrams/snapshot/hash/20111102171621-0b5ec-1f98cd6a796d46b46f54dc2e168e826f459572ea/content/pretty/src/Diagrams/Dendrogram.hs

Typeclasses for parametric paths

I got diverted doing something that I've had a swing at a few times before - making type classes for parametric functions. This time I'm just shooting for what's already there.

Main important file:
https://github.com/mgsloan/diagrams-lib/blob/a40811130e33248ede38b1320caa4e84133ad8d6/src/Diagrams/Parametric.hs

A few things need to change, but not /too/ much:

mgsloan@82ad2d4

The design space here is a bit funky - I'm not exactly happy with my usage of default method implementations, but they do give nice defaults while avoiding superfluous constraints. Otherwise, the other tricky design decisions are:

  • Have two classes, one for fixed parametric (point codomain), and one for vector codomain? Currently I have a type family for the Codomain.
  • How do we implement this for Path? In previous incarnations of this, I chose to have the domain be (0, segCount). Should the domain loop cyclically?
  • If the domain of Paths are (0, segCount), then the semantics of "section" / splitAtParam / etc are weird (they're linear transformations on the domain). But then iterating the transition between trails / segments is tricky, adding segments changes the whole parameterization, and length needs to be computed to evaluate..

I think it makes some good sense to typeclassify these, because:

  • There are properties, even if they are inter-instance. I don't think that properties are really much weaker given lack of superclass constraints (I don't like them usually).
  • There might eventually be more varieties of parametric functions / more manipulations on them. Currently there's just "adjust".
  • Could allow for path to be generic on segment type.

I'm not too set on it, though - not everything belongs in typeclasses!

Separate naming points from stroke'

Currently the stroke' function can do naming of vertices, but this seems to be conflating two separate things. In particular stroke' only works for 2D diagrams but naming a bunch of points is not 2D specific. Somehow they should be separated. But I'm not sure what the right API is.

Path+trail editing, with zippers!

Use edwardk's lens library to make some zippers over paths/trails, to make it easy to edit them.

  • A simple zipper would just allow editing trails directly.
  • Slightly more fancy would be to make a view of trails as lists of FixedSegments. The trick would be updating adjoining segments appropriately when adjusting an endpoint.
  • Even more fancy would be a view of trails as nested things, where each node can be either a segment or another trail. This would allow splicing trails together in fun ways.

There are probably lots of other cool things that could be done along these same ideas (not necessarily all involving lens).

Generalize Angle class?

(Imported from http://code.google.com/p/diagrams/issues/detail?id=84. Original issue from [email protected] on June 10, 2012, 06:29:18 PM UTC)

We could associate instances of the Angle class with
vector spaces, by also moving the 'direction' and 'e' functions into
the Angle class. That is, an angle is anything which can be obtained
from a vector, and converted back to a unit vector, subject to the
laws

(1) forall a, magnitude (e a) == 1

  (e always produces unit vectors)

(2) direction . e === id

  (converting from an angle to a vector and back is the identity)

(3) forall v,
exists k >= 0, v == k *^ (e . direction) v

  (converting from a vector to an angle and back results in a
  positive scalar multiple of the original vector)

Perhaps the class should be called Direction instead of Angle.

In any case, it's not clear to me whether this would be cool or whether it would just make things too complicated. It would be nice to be able to directly provide a vector when a direction is wanted, and to be able to talk about directions in dimensions other than two; but the downsides aren't (yet) clear to me.

The first step is probably just to do a thorough analysis of what would be affected by such a change, along with some examples of its utility.

Handle `rect` with zero arguments.

Right now rect is implemented by scaling a unitSquare, but if given zero as an argument that scaling will not have a valid inverse. This shows up later as a NaN with doubles. Semantically a rect with zero is fine, however, as a line or four lines, depending on how we want to go about it.

Ryan

Sönke Hahn wrote:

Hi!

Is this wanted behaviour?

Prelude> import Diagrams.Prelude
Prelude Diagrams.Prelude> import Diagrams.Backend.Cairo
Prelude Diagrams.Prelude Diagrams.Backend.Cairo> size2D (rect 0 10 ::
QDiagram Cairo R2 Any)
[snip]
Loading package diagrams-cairo-0.5.0.2 ... linking ... done.
(NaN,NaN)

I would have expected (0, 10).

Thanks,
Sönke

Context reduction stack overflow when using stroke or strokeT

(Imported from http://code.google.com/p/diagrams/issues/detail?id=24. Original issue from [email protected] on April 19, 2011, 02:37:55 PM UTC)

See attached file, which generates the error below. Adding a type signature to 'line' fixes the problem. This isn't necessarily a bug per se, but it would be nice if this didn't happen...

Context reduction stack overflow; size = 21
Use -fcontext-stack=N to increase stack size to N
  co :: v ~ uf6
  co :: V (Path v) ~ uf6
  $dRenderable :: Renderable (Path uf5) b
  co :: v ~ uf5
  co :: V (Path v) ~ uf5
  $dRenderable :: Renderable (Path uf4) b
  co :: v ~ uf4
  co :: V (Path v) ~ uf4
  $dRenderable :: Renderable (Path uf3) b
  co :: v ~ uf3
  co :: V (Path v) ~ uf3
  $dRenderable :: Renderable (Path uf2) b
  co :: v ~ uf2
  co :: V (Path v) ~ uf2
  $dRenderable :: Renderable (Path uf1) b
  co :: v ~ uf1
  co :: V (Path v) ~ uf1
  $dRenderable :: Renderable (Path uf) b
  co :: v ~ uf
  co :: V (Path v) ~ uf
  $dRenderable :: Renderable (Path v) b
In the expression: strokeT
In the expression: strokeT $ fromOffsets [(1, 0)]
In an equation for `line': line = strokeT $ fromOffsets [(1, 0)]

boundingBox computes incorrect bounding box for transformed diagrams

(Imported from http://code.google.com/p/diagrams/issues/detail?id=87. Original issue from [email protected] on July 25, 2012, 09:03:51 PM UTC)

What steps will reproduce the problem?

  1. The expression
    boundingBox (translate (r2 (10,10)) unitSquare :: D R2) calculates a bounding box of size 10.5 times 10.5 (instead of 1 times 1).

So the result is:
BoundingBox (P (R2 {unR2 = (0.0,0.0)})) (P (R2 {unR2 = (10.5,10.5)}))

instead of the expected output:
BoundingBox (P (R2 {unR2 = (9.5,9.5)})) (P (R2 {unR2 = (10.5,10.5)}))

I tested this with version 0.5.0.1 diagrams-lib

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.