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
contains() returns false for interior point #884
Comments
No, the removal of |
The reason why it fails is fairly simple. In This works quite well, but it fails if two curves are too close together. For any point in the darker blue area below no intersection of the horizontal ray is counted, therefore winding is zero, which means the point is outside the path. I do not have a solution, but at least we understand now why the problem occurs. |
Yes that makes a lot of sense! We could calculate a path's area in |
This si difficult. And it seems like it is not very important, because although we have a problem in theory, we have not encountered a real world scenario where this has any consequences. Of course the most simple solution would be to have |
That's a good thought! And that would be easy to add to your code? |
It's quite a hack, although it should work. Actually, I do not like this, it's a really dirty hack. |
Right after |
I was thinking the same just now about compound paths... didn't see that before. Yeah, I'm reluctant as well :) |
Here is a test case that currently works, but any solution that solves the initial example in this issue should be tested agains this test case. The difference to the initial test case is that the two close curves are inside the rest of the path, which means the horizontal ray starting from the point crosses the path one more time in each direction. var path = new Path({segments: [
[100, 100],
[150, 100],
[150, 150],
[150.000000005, 150],
[150.000000005, 100],
[200, 100],
[200, 200],
[100, 200]
], closed: true, strokeColor: "OliveDrab"});
var point = new Point(150.000000003, 120);
new Path.Circle({center: point, radius: 2, fillColor: "FireBrick"});
console.log("contains = " + path.contains(point)); |
Yes that makes perfect sense. I guess one would have to compare the x coordinates of the intercepts to distinguish the two? |
That could work, but it requires to compare each intersection of the ray with each other intersection. I just had another idea. We could have a flag |
In order to solve this issue we should first decide when |
That's a good question. I tend to think yes, it should be false (e.g. since we're also discarding such parts in the boolean ops), except for one doubt: We do consider the line as part of the inside of the paths, don't we? So wouldn't we have to do the same here then? |
I would make things much easier to have these points part of the path. And there is another weirdness in the way we currently handle these points: If they are on a vertical tip of two vertical lines, |
@lehni Actually my proposal is very simple. If the point at I will check how this works in theory with compound paths and if I am confident enough, I will create a pull request. No action from your side required. |
My proposals fails with intersect boolean operations. Unfortunately it's not as easy as expected. |
Here is another promising approach. The first time we encounter an intersection very close to the point ( This seems to work quite well so far. |
Sounds promising! Define "quite"? : ) |
Maybe not worth fixing? |
Maybe you are right, but I will try a little more. Here is another approach that so far passes all tests:
That's all. I need to test this with some compound paths. |
I had a hunch that by telling you to give up, you'd dig in deeper and find a solution :P |
My weak spot :) |
Do you still want to tackle this or shall we close the issue? |
If you accept my pull request, you can close the issue 😄 |
Very cool! I'm on a train in Germany with very spotty reception, but am trying my best at pulling : ) |
This can finally be closed after the |
👍 |
In some cases
path.contains()
returnsfalse
for points that are actually inside a path. Here is an example:Visual debuggind indicates that the point is inside the path:
The reason for this behaviour is probably that
getWinding()
uses a tolerance to exclude points directly on a curve. This should not be done when checking if a point is contained by a path.Until recently there was a
testContains
parameter in thegetWinding()
function. Maybe the purpose of this was to distinguish between winding calculations for 'contains' tests and 'winding propagation'?The text was updated successfully, but these errors were encountered: