Paper.js: boolean subtract fails for semi-circle inscribed in rectangle

Created on 23 Sep 2018  路  20Comments  路  Source: paperjs/paper.js

Description/Steps to reproduce

I've reproduced the behavior in the sketch linked below.

I have a rectangle, and then I have a semi-circle that is inscribed within the rectangle.

I am trying to boolean subtract the semi-circle from the rectangle. Example 1: When I do so with {trace: true} the operation returns an empty path (this is wrong - ie not the expected behavior). Example 2: When I do so with {trace: false}, the operation returns a single line, the edge of the rectangle that is shared with the bottom of the semi-circle (I'm not sure if this is wrong, the trace setting is confusing to me but I think it's wrong).

Example 1: Subtract with {trace: true} is supposed to leave me with a path containing the green sections, but it's not doing that.
screen shot 2018-09-23 at 12 24 34 pm

Note: In my sketch example, I take a few steps to get to the Rectangle and Semi-Circle. That is how this issue surfaced in my code.

paper.js sketch

boolean-operations bug

All 20 comments

Hi,

I will try to investigate the problem.
As a workaround for this case, you can use Item.exclude() instead.
See it working in this Sketch.

thanks @sasensi

that workaround is for when the subtract method's trace option is set to true.

When it's set to false, I think this is the workaround needed:
item.exclude(itemToExclude).subtract(itemToExclude, {trace: false})

sketch

If somewone else wants tries to solve this, the problem can be reduced to this case.

I wasn't able to solve it, but I found that it is linked to this call to _getWinding() which seems to return a wrong winding value of 0 at the triangle top point.
https://github.com/paperjs/paper.js/blob/6cbf5292da1551cd870a3ef78e087199d2344738/src/path/PathItem.Boolean.js#L748-L757

Moving any of the points or changing the first offset value here, solve the problem.
https://github.com/paperjs/paper.js/blob/6cbf5292da1551cd870a3ef78e087199d2344738/src/path/PathItem.Boolean.js#L727

Perhaps @iconexperience can help out? He worked a lot on the winding stuff the last time we focused our attention on boolean operations.

Unfortunately I won't find any time soon to look into more boolean operations related edge-cases.

@lehni or @iconexperience, can one of you look at this PR #1515 to see if it is a reasonable solution ?

@sasensi I've just merged #1515, thank you for your contribution! Are you interested in working on more paper.js features?

Also, @renschler could you test if this solves your issue?

You can test with the files here:

https://github.com/paperjs/paper.js/tree/prebuilt/module/dist
https://github.com/paperjs/paper.js/tree/prebuilt/dist

@lehni you're welcome.
Sure, I would be glad to do anything that can help, just tell me what can I do ?

By the way, I'm actually working on an algorithm to produce extrusion effect, you can see a demo here, maybe I could integrate this as a feature or just as an example somewhere ?

@sasensi oh wow, that's super nice! The code looks rather complex!

From working on this, is there any method that you feel should be added to the Path / Curve interface that would simplify the code for this effect? Maybe this is something you could start working on implementing?

As for helping out otherwise, there are a ton of things that need work. Looking after issues, fixing bugs, wrapping up the path to 1.0.0 (not sure what's holding us back actually : )

About this extrusion effect, if you think this is something that could interest other people, sure, I could integrate it.
For example as a path instance method extrude(point) that would return a Group made of: background (Path), sides (Group of Path) and edges (Group of Path).
An example of usage would look something like

var path       = new Path('M4.477,1.992C4.931,1.311,5.702,0,6.648,0c1.336,0,0.655,1.76,0.366,2.424z');
var extrusion  = path.extrude(new Point(50, 50));
var background = extrusion.children[ 0 ];
var sides      = extrusion.children[ 1 ];
var edges      = extrusion.children[ 2 ];

background.strokeColor = 'black';
edges.strokeColor      = 'black';
sides.fillColor        = 'yellow';

What do you think about that ?

About other tasks, I will look at still opened issues and try to resolve them.
I've also seen the discussion about path offsetting which seems to be a difference making feature unfortunately on a pending state. Could I help you finishing its implementation ?

I was more thinking of the more lower-level tools / helper functions needed to make the effect work, and then we show the effect itself as a feature on the site in the examples? Perhaps we could add some out of this that would help making such an effect, and others, simpler?

I'm super interested also in wrapping the offsetting up! The main issue at the moment is my availability, as I got swallowed by a massive project that pays my bills and consumes all my time currently. I'm happy to help where I can and time allows, and things should again get better around March 2019, time-wise.

Progress has stopped around here, when @sapics started looking into some of the edge-cases:
https://github.com/paperjs/paper.js/issues/371#issuecomment-297585655

This would be the right place to pick up work, maybe also together with @sapics who has started helping out more with paper.js stuff, and has become a contributor.

PS: I meant helpers like getCurveTimesAtVectorTangents() and such.

Sorry, I misunderstood your question.
Actually, I think a curve method to get times at tangent to a given vector could help in some other cases.
For my example, I adapted the method mentioned in this comment.

I could integrate it as curve.getTimesAtVectorTangents(point) and path.getTimesAtVectorTangents(point) which would return float[].

For path offsetting, I will look the code in more detail and see with @sapics how I can help to get this done.

Very cool! Yes we could than share this method with the offsetting code, indeed!

@lehni, here is the PR #1530 for Path/Curve#getTimesAtVectorTangent methods.

Let's close this issue here and discuss the PR over there. @renschler feel free to reopen should you still see problems

wonderful thanks @lehni @sasensi. I will give it a test.

This is a beginner question but now that this is merged in, is it included in the latest version on npm? Or are there more steps involved before it becomes available on npm?

@renschler no it's not automatically released, but you can use the prebuilt versions for testing, see here: https://github.com/paperjs/paper.js/issues/1513#issuecomment-425644738

ok gotcha, yes I tested and this resolves my issue. Thanks!

Another beginner question but how often do these changes get incorporated into a release?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sansumbrella picture sansumbrella  路  3Comments

eljefedelrodeodeljefe picture eljefedelrodeodeljefe  路  5Comments

przyb picture przyb  路  5Comments

9oelM picture 9oelM  路  5Comments

techninja picture techninja  路  4Comments