Hi all,
I just added LPE Boolops to SVN. Have fun with it.
What would be very helpful is for you to test it and try to break it (not so hard at the moment). If you have a problem case that fails, please save the SVG and add it to the launchpad bugtracker. Please give the bugreport the "livepatheffects" tag. Because I am not sure who of 2geom development checks the bugtracker (I don't for example), please also send a mail to lib2geom-devel@lists.sourceforge.net with a link to the launchpad bug report.
Thanks!!!
Johan
On Thu, Jul 17, 2008 at 2:08 AM, J.B.C.Engelen wrote:
Hi all,
I just added LPE Boolops to SVN. Have fun with it.
What would be very helpful is for you to test it and try to break it (not so hard at the moment). If you have a problem case that fails, please save the SVG and add it to the launchpad bugtracker. Please give the bugreport the "livepatheffects" tag. Because I am not sure who of 2geom development checks the bugtracker (I don't for example), please also send a mail to lib2geom-devel@lists.sourceforge.net with a link to the launchpad bug report.
Thank you! That was really fast! :)
Currently I see a number of warnings like "lib2geom exception: parameter t out of bounds (./2geom/path.h:300). I also managed to crash Inkscape twice, but not in a reproducible manner yet :)
Alexandre
On Wed, Jul 16, 2008 at 7:08 PM, <J.B.C.Engelen@...1578...> wrote:
Hi all,
I just added LPE Boolops to SVN. Have fun with it.
Cool!
Problems so far: create two open paths with two nodes and a bezier segment each. Do a boolop of them. Problem #1: the result is closed, not open even for union (livarot has the same problem). Problem #2: after converting to path, the points of intersection of the beziers have two nodes at the same place instead of one. Problem #3: too much debug output in the console :)
Thanks, you rock! If these work well and if you can also implement division, cut path, inset/outset, and simplify, then we can switch all path commands to 2geom. After that livarot will only be left in rendering, and after that is cairoified it can be purged entirely.
On Sat, 2008-07-19 at 01:17 -0300, bulia byak wrote:
Problems so far: create two open paths with two nodes and a bezier segment each. Do a boolop of them. Problem #1: the result is closed, not open even for union (livarot has the same problem).
njh and I have been talking about this; the main issue is deciding what interpretation to give an open path which has no area (boolops currently work in terms of area). I think the answer we settled on was to treat the line of open paths as if it were "solid", albeit with zero thickness. For example, intersecting a line with a shape leaves you with just the portions of the line which lie inside the shape.
An interesting question is whether it should really be open versus closed, though... I wonder whether filled versus unfilled ought to be the real distinction for boolops purposes? At least, it might make more sense from an artistic/visual perspective.
Problem #2: after converting to path, the points of intersection of the beziers have two nodes at the same place instead of one.
This has given me some headaches.
Our main goal was, when we cut a path segment in boolops, the point of the cut must lie exactly on the segment, so that the segment's shape is not altered. This saves us from the problems that most boolops implementations like livarot's have, where they can end up with invalid intersection topology because the curves have moved around. Also, even when the topology would have remained valid, exact cuts should eliminate most of the bug reports we get about boolops being visibly inexact.
It turns out, however, that the exact point of intersection of two curves does not always lie in a place which can be represented by rational numbers (let alone floats). In that case we must cut at the nearest representable points which are still actually on each segment, and then join the cuts with a short line segment so that we still have a continuous path without altering the shape of the segments on either side.
As far as I can tell at this point, this seems to be the only way to do exact boolops within the limitations of floats. In these cases it is basically a tradeoff between simple node structure on one hand, and visually+mathematically exact results on the other.
Problem #3: too much debug output in the console :)
That will go. I need to tease mgs some more about removing it. :)
Thanks, you rock! If these work well and if you can also implement division, cut path, inset/outset, and simplify, then we can switch all path commands to 2geom.
Division/cut path should be covered by the same code as boolops support for open/unfilled paths. I believe the rest is already implemented, although it still needs some final work polish.
-mental
On Sat, Jul 19, 2008 at 2:58 AM, MenTaLguY <mental@...3...> wrote:
An interesting question is whether it should really be open versus closed, though... I wonder whether filled versus unfilled ought to be the real distinction for boolops purposes? At least, it might make more sense from an artistic/visual perspective.
I don't think so. I'd say what you need to do is this: treat any open subpath as a closed path where one of the segments (joining the ends) is straight and marked as special. Then, perform the boolop as usual, but preserve the specialness of this segment - that is, if some segment of the result "comes from" a special segment in the source, mark it as special too. And then, when translating the result to a path, convert those special segments to unstroked movetos. This still won't work 100% when the special segments of two source paths intersect _and_ the paths are filled, but in all other cases I think it will give the most useful and intuitively correct result, regardless of whether the source was filled or not.
Problem #2: after converting to path, the points of intersection of the beziers have two nodes at the same place instead of one.
This has given me some headaches.
Our main goal was, when we cut a path segment in boolops, the point of the cut must lie exactly on the segment, so that the segment's shape is not altered. This saves us from the problems that most boolops implementations like livarot's have, where they can end up with invalid intersection topology because the curves have moved around. Also, even when the topology would have remained valid, exact cuts should eliminate most of the bug reports we get about boolops being visibly inexact.
And that is great, I remember how I cursed Xara for its ugly linear segments it inserted at path intersections. So, kudos for the achievement, but please remember we're creating a practical tool, not a mathematical demo :) so I think you should merge any nodes that will end up in the exact same position anyway after serializing to SVG.
On Sat, 2008-07-19 at 03:15 -0300, bulia byak wrote:
And that is great, I remember how I cursed Xara for its ugly linear segments it inserted at path intersections. So, kudos for the achievement, but please remember we're creating a practical tool, not a mathematical demo :) so I think you should merge any nodes that will end up in the exact same position anyway after serializing to SVG.
Hm, wouldn't the merging make sense to do at serialization time then? (since only the fancy optimization code knows exactly what it will keep and what it won't?)
The introduced line segments are marked by having a special curve type Geom::Path::StitchSegment (which is a subclass of Geom::LineSegment), so it is fairly easy to know which to merge.
-mental
On Sat, Jul 19, 2008 at 3:45 AM, MenTaLguY <mental@...3...> wrote:
Hm, wouldn't the merging make sense to do at serialization time then? (since only the fancy optimization code knows exactly what it will keep and what it won't?)
No, because I may have introduced them intentionally, for any number of reasons, and don't want to lose them. It would be a bad kind of surprise if I now have two nodes, save and reopen the file and suddenly there's only one.
More boolop problems:
https://bugs.launchpad.net/inkscape/+bug/250025
https://bugs.launchpad.net/inkscape/+bug/249437
On Sat, 2008-07-19 at 03:57 -0300, bulia byak wrote:
On Sat, Jul 19, 2008 at 3:45 AM, MenTaLguY <mental@...3...> wrote:
Hm, wouldn't the merging make sense to do at serialization time then? (since only the fancy optimization code knows exactly what it will keep and what it won't?)
No, because I may have introduced them intentionally, for any number of reasons, and don't want to lose them. It would be a bad kind of surprise if I now have two nodes, save and reopen the file and suddenly there's only one.
As I said, these 'stitches' introduced at intersections by boolops are a distinct 2geom curve/segment type; they are distinguishable from regular line segments. I wasn't suggesting indiscriminately collapsing all short line segments.
Pretty much all which would need to be done is to simply skip outputting segments of type Geom::Path::StitchSegment to SVG.
-mental
On Sat, Jul 19, 2008 at 2:10 PM, MenTaLguY <mental@...3...> wrote:
As I said, these 'stitches' introduced at intersections by boolops are a distinct 2geom curve/segment type; they are distinguishable from regular line segments. I wasn't suggesting indiscriminately collapsing all short line segments.
But I still see them as two nodes in Node tool, before they are merged. Or are you saying we should teach Node tool to ignore them as well? And maybe some other places too? Why all this complexity when we can just suppress them at the source?
On Sat, 2008-07-19 at 14:33 -0300, bulia byak wrote:
On Sat, Jul 19, 2008 at 2:10 PM, MenTaLguY <mental@...3...> wrote:
As I said, these 'stitches' introduced at intersections by boolops are a distinct 2geom curve/segment type; they are distinguishable from regular line segments. I wasn't suggesting indiscriminately collapsing all short line segments.
But I still see them as two nodes in Node tool, before they are merged.
I was under the impression that boolops output did a roundtrip through the d= attribute; is that actually the case? If not, maybe we should; I think that is the easiest way to flatten what roundtripping would flatten.
Or are you saying we should teach Node tool to ignore them as well?
No, definitely not.
-mental
On Sat, Jul 19, 2008 at 8:05 PM, MenTaLguY <mental@...3...> wrote:
I was under the impression that boolops output did a roundtrip through the d= attribute; is that actually the case?
I'm not too sure - this has been a focus of much change recently. Johan, can you clarify?
If not, maybe we should; I think that is the easiest way to flatten what roundtripping would flatten.
I would like to avoid such roundtripping if at all possible, for the simple reason of performance. Writing to d= and reading from it are very slow (even though Jasper made them much faster yesterday). Remember that the entire system separating SPObjects from reprs was done in order to minimize writing to repr - I don't want to lose this speed boost for LPE paths which are slower than regular paths anyway.
-----Original Message----- From: bulia byak [mailto:buliabyak@...400...] Sent: zondag 20 juli 2008 18:50 To: MenTaLguY Cc: inkscape-devel@lists.sourceforge.net; Engelen, J.B.C. (Johan); lib2geom-devel@lists.sourceforge.net Subject: Re: [Inkscape-devel] NEW: LPE Boolops
On Sat, Jul 19, 2008 at 8:05 PM, MenTaLguY <mental@...3...> wrote:
I was under the impression that boolops output did a
roundtrip through
the d= attribute; is that actually the case?
I'm not too sure - this has been a focus of much change recently. Johan, can you clarify?
If not, maybe we should; I think that is the easiest way to flatten what roundtripping would flatten.
I would like to avoid such roundtripping if at all possible, for the simple reason of performance. Writing to d= and reading from it are very slow (even though Jasper made them much faster yesterday). Remember that the entire system separating SPObjects from reprs was done in order to minimize writing to repr - I don't want to lose this speed boost for LPE paths which are slower than regular paths anyway.
I just checked LPE behavior; sorry I've forgotten some details :( When dragging the original path with the node tool, there is no roundtripping through d=. Only when the mousebutton is released, the new original path is written to svg and everything is updated in svg. However, when editing a path parameter (so the second path in the LPE Boolops case), d= is updated while dragging, indicating that there might be roundtripping through it, but I am not sure. Actually I think that SPPath notices the change in pathparam, recalculates the LPE and writes the result to d=. (so no roundtripping, more outputting to d=). (see sp-path: sp_path_udate_patheffect and notice the "bool write" argument). I think this is sort of a bug, so I'll try to look into it.
On Sat, 2008-07-19 at 01:17 -0300, bulia byak wrote:
Thanks, you rock!
Credits should go to Michael Sloan and MenTaLguY. I only wrote a couple of lines in the LPE that call 2geom.
On Sun, Jul 20, 2008 at 2:51 PM, <J.B.C.Engelen@...1578...> wrote:
I just checked LPE behavior; sorry I've forgotten some details :( When dragging the original path with the node tool, there is no roundtripping through d=. Only when the mousebutton is released, the new original path is written to svg and everything is updated in svg.
Yes, that's the way it must be. Thanks for confirmation.
However, when editing a path parameter (so the second path in the LPE Boolops case), d= is updated while dragging, indicating that there might be roundtripping through it, but I am not sure. Actually I think that SPPath notices the change in pathparam, recalculates the LPE and writes the result to d=. (so no roundtripping, more outputting to d=). (see sp-path: sp_path_udate_patheffect and notice the "bool write" argument). I think this is sort of a bug, so I'll try to look into it.
Yes, ideally write must be false while dragging but true when you release mouse.
Let's try introducing stitch-stripping to path writing first, and see if that gets us what we want. Correct me if I'm wrong, but I think people do not normally manipulate LPE output directly without converting to path first? In that case (convert-to-path), there should definitely be a roundtrip through svgd.
-mental
On Sun, Jul 20, 2008 at 3:07 PM, MenTaLguY <mental@...3...> wrote:
Let's try introducing stitch-stripping to path writing first, and see if that gets us what we want. Correct me if I'm wrong, but I think people do not normally manipulate LPE output directly without converting to path first? In that case (convert-to-path), there should definitely be a roundtrip through svgd.
Not a roundtrip - just a one-way trip from the curve to d=.
Your change in svg-path didn't fix the double nodes but broke something else :(
load this file, select red path and convert to path - two nodes are lost, but the bottom intersection is still 2 nodes in the same place
By the way, the same file shows how the Union boolop (at least) fails in many configurations. Select the red shape and start pressing Shift+right arrow:
4 keypresses: there appears a hole at the tip of blue curve
7 keypresses: the result degrades to a single point
8 and more keypresses: blue curve is just ignored in the union
18 keypresses: all is correct again
On Sun, 2008-07-20 at 15:32 -0300, bulia byak wrote:
Your change in svg-path didn't fix the double nodes but broke something else :(
Well, not exactly. It's more that it's showing up an existing problem in 2geom. Boolops is evidently turning the closing segment of unclosed paths into a giant continuity stitch, which is very wrong. (It should instead be using the existing final closing segment provided for the purpose of treating unclosed paths as closed.)
-mental
-----Original Message----- From: MenTaLguY [mailto:mental@...3...] Sent: zondag 20 juli 2008 20:07 To: bulia byak Cc: inkscape-devel@lists.sourceforge.net; Engelen, J.B.C. (Johan); lib2geom-devel@lists.sourceforge.net Subject: Re: [Inkscape-devel] NEW: LPE Boolops
Let's try introducing stitch-stripping to path writing first, and see if that gets us what we want. Correct me if I'm wrong, but I think people do not normally manipulate LPE output directly without converting to path first? In that case (convert-to-path), there should definitely be a roundtrip through svgd.
It is not possible to manipulate LPE output. When d= is changed for a shape with a LPE applied, it is discarded and replaced with the d= output from the LPE calculation using original-d= or other shape parameters. convert-to-path is done by deleting the path effect, the d= attribute is kept the same (the LPE stack's result is not even recalculated); so this operation does not do much actually. (I remember it was this way, it should work in this way)
On Sat, Jul 19, 2008 at 8:05 PM, MenTaLguY <mental@...3...> wrote:
I was under the impression that boolops output did a roundtrip through the d= attribute; is that actually the case?
Actually, the two nodes at intersections are visible and editable only after you convert a boolop LPE to path, at which point it takes the path's curve, which is presumed to be up to date, and converts it to d=. This way it works the same for LPE paths and shapes.
participants (4)
-
unknown@example.com
-
Alexandre Prokoudine
-
bulia byak
-
MenTaLguY