-
Notifications
You must be signed in to change notification settings - Fork 26
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
union
with nonzero winding rule
#64
Comments
Hi @mbutterick. Thanks for the helpful diagram in describing your issue. In the case of the Q the inner contour is removed in your example because when its components are union'd individually the inner contour is treated like a solid oval instead of a hole. Since the inner contour falls completely inside the outer contour, the union of the two is just the outer contour. I believe that
Right now all boolean operations (union, subtraction, intersection) assume the path can be filled using the even-odd rule. But as a workaround
The closest public method is
You can do |
Thanks — that’s helpful. I got my examples to work by creating a One case that still behaves oddly is shown below, where opposite-direction paths cross each other, as in the first pic. When I apply |
(To be clear, in the third pic I have taken the contours in #2 and pulled apart the points at the intersection just to reveal how the contours cross) |
@mbutterick these diagrams are really helpful to illuminate a case where Some context: for |
…d of prioritizing forward edges we prioritize edges that wind using the same convention as the path. Further work may be necessary to choose the edge that makes the largest clockwise vs counter-clockwise turn but perhaps OK for now?
@mbutterick could you do me a favor and try out a branch I've created called I would like to verify that this fix resolves your issue with the "O" where opposite direction paths cross each other. |
Yes, the fix does seem to work, thank you. The first pic is another overlap. The second pic shows the immediate result of The only little glitch is that the right side of the upper contour ends up with two points in that corner instead of one, whereas on the left it only has one. (In some quick tests, the same double-point glitch happens on every curved-segment crossing that results in a new contour; it does not happen when straight segments cross.) Usually a double point like that is a sign of an off-by-one error in closing the path. From the perspective of rendering it's benign, however. |
@mbutterick I've written a unit test using two ellipses to try to reproduce your issue with the "O", but I'm not seeing a double point. To help me figure out where the double-point is coming from it would be helpful to know exactly what your path looks like both before and after
The |
Sorry, my bad — on closer inspection the extra point is my fault. Your revised code is doing the right thing. |
No problem! I appreciate your help improving the behavior of the API. For the time being I'd recommend you use the |
…t instead of prioritizing forward edges we prioritize edges that wind using the same convention as the path. Further work may be necessary to choose the edge that makes the largest clockwise vs counter-clockwise turn but perhaps OK for now?
Suppose I’d like to
reduce
a list ofPath
objects into a singlePath
with overlaps removed, but winding preserved.In example
A
, the crossbar overlaps the sides. If I convert this to an array ofPath
andreduce
into a newPath
usingunion
, I get the right result.In example
Q
, however, the same approach doesn’t work:union
will remove the overlap correctly from theQ
tail, but it will also remove the inner contour entirely.union
so that it takes account of nonzero winding?Path
? (I see there is an internalwindingCount
property)Path
objects into a newPath
without applying any Boolean processing?The text was updated successfully, but these errors were encountered: