Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blank image or out of memory when using a square or circle shaft with an arrow #282

Open
harendra-kumar opened this issue Aug 25, 2016 · 10 comments

Comments

@harendra-kumar
Copy link

If the shaft is a circle or square then the generated SVG does not render correctly, it just shows a blank image even if the image has a lot more things other than the misbehaving arrow.

With the rasterific backend the program just crashes (gets killed on Linux and freezes OS X) due to getting out of memory.

arrowAt' (with & arrowShaft .~ (square 1)) (p2 (0, 0)) (r2 (1, 1))

Are shafts like circle or square supposed to work? In any case the program should not misbehave if it compiles. I tried on Linux as well as Mac OS X with same results on both.

@jeffreyrosenbluth
Copy link
Member

I'll look into this in more detail when i get some time, but what I think is going on is the following. Arrows are scaled by dividing the distance from tail to head by the length (defined as the distance from the start to the end) of the shaft. Since a circle or square starts and ends at the same point it has no length.

@jeffreyrosenbluth
Copy link
Member

jeffreyrosenbluth commented Aug 25, 2016

I'm having trouble replicating the bug (at least with the svg backend).
My code:

{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts, TypeFamilies #-}

import Diagrams.Prelude
import Diagrams.Backend.SVG.CmdLine

diagram :: Diagram B
diagram = arr <> square 1.5 # alignR # lw none
              <> square 2 # lw none
  where
    arr = arrowAt' (with & arrowShaft .~ (square 1)) (p2 (0, 0)) (r2 (1, 1))

main = mainWith diagram

works as expected?

Can you post your entire program somewhere like paste?

@jeffreyrosenbluth
Copy link
Member

sqarr

@byorgey
Copy link
Member

byorgey commented Aug 26, 2016

@jeffreyrosenbluth , maybe the difference is that you are composing it with some other squares which are taking up space. @harendra-kumar , can you paste the complete code you are using which exhibits this problem?

@harendra-kumar
Copy link
Author

@jeffreyrosenbluth even I can draw the nice arrow with a square using your program. But my version does not work. What I earlier pasted is the whole program except main, here it is again:

{-# LANGUAGE NoMonomorphismRestriction #-}

import Diagrams.Prelude
import Diagrams.Backend.SVG.CmdLine

main = mainWith (arr :: Diagram B)

arr :: Diagram B
arr = arrowAt' (with & arrowShaft .~ (square 1)) (p2 (0, 0)) (r2 (1, 1))

As @byorgey said the difference could be due to composing with other squares.

@byorgey
Copy link
Member

byorgey commented Aug 27, 2016

Well, since arrows take up no space (except maybe their heads? I forget)
drawing one by itself is unlikely to work well regardless of the shaft.
But Jeff is right that using a circle or square as a shaft is not supported
since they begin and end in the same place.

On 12:57am, Fri, Aug 26, 2016 Harendra Kumar notifications@github.com
wrote:

@jeffreyrosenbluth https://github.com/jeffreyrosenbluth even I can draw
the nice arrow with a square using your program. But my version does not
work. What I earlier pasted is the whole program except main, here it is
again:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Diagrams.Preludeimport Diagrams.Backend.SVG.CmdLine

main = mainWith (arr :: Diagram B)
arr :: Diagram B
arr = arrowAt' (with & arrowShaft .~ (square 1)) (p2 (0, 0)) (r2 (1, 1))

As @byorgey https://github.com/byorgey said the difference could be due
to composing with other squares.


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#282 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAglYwL08wUVFcooG8FDXCZjYbheRQeiks5qjoBigaJpZM4JtINN
.

@harendra-kumar
Copy link
Author

drawing one by itself is unlikely to work well regardless of the shaft.

That does not seem to be true, as this one below shows the arrow perfectly:

arr = arrowAt' (with & arrowShaft .~ (trailFromOffsets [unitX])) (p2 (0, 0)) (r2 (1, 1)) 

It seems to be working in Jeff's version. But with my version in one of the programs the whole thing went blank (there were other components in the diagram but nothing displayed because of this). Maybe nothing was rendered or maybe it did not generate a well formed svg. With rasterific backend it just crashes with out of memory.

Its ok if it is not supported but the program should not misbehave. Its ok if just the arrow does not show up. It will be great if the program does not compile in the unsupported case.

@byorgey
Copy link
Member

byorgey commented Aug 27, 2016

Ah, right, now I remember, we try to approximate the envelope of arrows as best we can, but when the start and end of an arrow shaft are very close to each other it is basically impossible to do a good job with this (because the arrow is infinitely short). You have to keep in mind that the arrow shaft is a path from point A to point B, not a shape. Though it occurs to me we could probably add an option to specify both a trail to be used to delineate the endpoints of the arrow as well as a shape to be drawn instead.

It is not possible to make the program not compile, because there is nothing wrong with the types, it is just a strange edge case from a numeric point of view. And with edge cases it is very hard to tell the difference between something that is "wrong" and something that is actually what the user intended. In this case I really have no idea what "should" be drawn because it is impossible to scale a square trail so that its starting point is at (0,0) and its endpoint is at (1,1), since the start and endpoints are the same.

In any case, I agree it would be good if the rasterific backend did not blow up with out-of-memory. Would you be willing to file a ticket on the diagrams-rasterific repo with this program as an example?

@jeffreyrosenbluth
Copy link
Member

@byorgey Thanks for refreshing my memory. We approximate the size of the envelope using the norm of the trailOffset of the shaft. We could check to see if this norm is zero, but then do what? ... default to some value, provide a better error message?. And that still won't help with overflow for shafts that are almost loops.

@harendra-kumar
Copy link
Author

@byorgey I will raise an issue for rasterific. I have a couple more questions on this issue:

  1. An arrow is a path from point A to point B. If point A and B are not the same then a closed path can never connect them. If the path specified starts and ends at the same point, can we detect it and issue a warning at runtime? Also, we cannot use a path which does not have a defined start or end point i.e. a closed shape.

The arrow that we see in Jeff's program (after composing it with some other shapes) is actually wrong since it does not connect the two points we specified. It is drawn at just one of the points, we can see that clearly by drawing the start and end points.

  1. What do we do when a diagram becomes too big? I am not sure how to define too big. Consider an example of drawing an arrow of arc shape between two points which are a unit distance apart. As the arc starts getting close to 1 turn the size of the arc will start tending to infinity. Using the svg backend I see it getting clipped after 0.92 turns. Is that the right behavior? It will be good if we can issue a warning in such cases. You can try this to see this:
arr = frame 1.1 $ arrowAt' (with & arrowShaft .~ (arc xDir (0.92 @@ turn)))
                           (p2 (0, 0)) (r2 (1, 1))
                  <> start <> end
    where dot :: Diagram B
          dot = circle 0.2
          start = moveTo (p2 (0, 0)) dot
          end = moveTo (p2 (1, 1)) dot
  1. As you suggested, as an enhancement perhaps we can use a shape along the path of the arrow. In the special case of a straight line path this should not be too difficult as we just need to specify how to align the shape along the straight line. But in a general case, if the path is zig-zag then we will have to somehow transform the shape along that path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants