paperjs / paper.js

The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey
http://paperjs.org
Other
14.45k stars 1.22k forks source link

path.subtract() fails if lines are very close #865

Closed iconexperience closed 8 years ago

iconexperience commented 8 years ago

Here is an example that produces the wrong result on path.result(). Note that the x-values of the vertical lines in the middle are very close, but not identical. The difference is .00000000000006. If the right side of the rectangle is moved slightly in either direction, everything works fine. But at this x distance, the subtraction fails to remove the little triangle.

As far as I can see the intersections are found correctly.

image

var p1 = new Path({segments:[
    [300, 100],
    [300, 350],
    [256.00000000000006, 350],
    [256.00000000000006, 250],
    [230, 224],
    [256.00000000000006, 200],
    [256.00000000000006, 100]
    ], closed:true});
var p2 = new Path({segments:[
    [256, 150],
    [256, 300],
    [200, 300],
    [200, 150]
    ], closed:true});

var r = p1.subtract(p2);

p1.strokeColor = "green";
p2.strokeColor = "red";
r.fillColor = "rgba(0, 255, 0, 0.1)";

Here is the sketch

lehni commented 8 years ago

Uh oh! Have you done any analysis yet as to where this is going wrong?

iconexperience commented 8 years ago

No, only the obvious, like the intersections. They seem to be correct.

lehni commented 8 years ago

It seems that while two intersections are found, only one actual crossing is found. The other one must be filtered out...

iconexperience commented 8 years ago

Very nice, so far my testing does not show any negative side effects. Now we need to get last glitches out of fat line clipping (which is my job). I desperately want to finish this until Thursday.

lehni commented 8 years ago

@iconexperience sounds great, really looking forward to merging it all in! Yes I could also not find any side-effects. At least after hours of testing and refining the current code. It was quite the challenge, really :)

iconexperience commented 8 years ago

But to be honest, you do not seem to suffer from taking a challenge from time to time :)

lehni commented 8 years ago

@iconexperience well! Only if it solves so nicely after putting an acceptable amount of time into it :) I think I was reaching my limits when we were pushing the boundaries of the boolean operations code earlier this year. Super glad we got that almost done now though!

iconexperience commented 8 years ago

@lehni Yes, that was intense and just imagine if we had found out midway that we are on a dead end. I even started worrying when I found this bug.

BTW, all the issues that I am posting at the moment come from using a simple path offset implementation in a small test case where path offsetting and subsequent subtraction is done in real time while dragging (in other words, from a real world scenario). This is very impressive and there are only very few issues remaining (I guess there is one left that I have not posted, because I found no time to simplify it), so the whole boolean code appears super robust. The path offsetting is based on my initial code (http://embed.plnkr.co/jkNGoe8fD0li9DmY7u76/), but I simplified it a lot. How should we proceed with this code? Should I first create a separate repository on Github?

lehni commented 8 years ago

@iconexperience that sounds great, can't wait to see it! I wouldn't spend too much time worrying about integration in the library yet,as I'd like to first look at what's there and then come up with a plan. Sharing as plnkr.co or even a ZIP file is also fine as a first step!

iconexperience commented 8 years ago

Alright, will do. I have to rework it a bit, because it is only using the outer offset at the moment, but that should not be a problem.

lehni commented 8 years ago

Don't spend too much time wrapping that all up, as I have some ideas about merging stroking outlining and path offsetting code in the API, and might have to rip it apart again : )