Skip to content
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

Curve.evaluate() should handle straight curves separately #838

Closed
iconexperience opened this issue Nov 30, 2015 · 7 comments
Closed

Curve.evaluate() should handle straight curves separately #838

iconexperience opened this issue Nov 30, 2015 · 7 comments

Comments

@iconexperience
Copy link
Contributor

While working on path offsetting I ran into a very strange behaviour of straight curves in some cases.

Here is a simple boolean example that creates a path consisting of straight curves:

var p1 = new Path.Rectangle(100, 100, 200, 70);
var p2 = new Path.Rectangle(50, 150, 300, 80);
var result = p1.unite(p2);

This is how it looks:
image

As you can see in this sketch, isStraight() returns true for all curves in the path (which means the curves are lines), so everything looks alright.

But the full truth is that two curves in the path actually have tiny handles. isStraight() sees them within tolerance, which is the correct behaviour. Here are the values for the last curve:

[ 50, 150, 49.99999999999999, 150, 100.00000000000001, 150.00000000000003, 100.00000000000001, 150.00000000000003 ]

As you can see from the values, there is a tiny handle at the left with length 1e-14. This handle is pointing to the left, while to whole curve (or line) runs from left to right.

The strange thing happens if you call getNormalAt() for the start and the end point of the curve. Since isStraight() returns true, one would expect that getNormalAt() returns the same value for all parameters on the curve, but this is not what happens. Insteat getNormalAt(0, true) returns {x:0, y:1} and getNormalAt(1, true) returns {x:0, y:-1}. Here is the sketch.

The reason for this behaviour is that getNormalAt (or evaluate()) does not distinguish between straight and non-straight curves and always uses the direction of the handle at the end point for the tangent, if a handle exists. Since we have tiny handle at the start point which is pointing to the opposite direction of the curve, the normal suddenly becomes inverted.

For path offsetting this is a real problem, because the offset curve of a straight line changes side, while we would expect it to simply be a parallel line.

While we are at this we should also look why the curves grow tiny handles in the boolean operation. Maybe this is unavoidable, but of course it would be better if a line stays a line in boolean operations.

@lehni lehni self-assigned this Dec 20, 2015
@lehni
Copy link
Member

lehni commented Dec 20, 2015

I completely agree, this is far from ideal. I'll have to do a proper analysis of this soon!

@lehni
Copy link
Member

lehni commented Dec 30, 2015

I closed this issue too early, since my fix addresses the problem of tiny handles after boolean operations, but now how Curve.evaluate() handles them. Reopening.

@lehni lehni reopened this Dec 30, 2015
@lehni lehni closed this as completed in a20b046 Dec 30, 2015
@lehni lehni reopened this Jan 5, 2016
@lehni
Copy link
Member

lehni commented Jan 5, 2016

Looks like my merging mess closed this one again...

@lehni
Copy link
Member

lehni commented Jan 6, 2016

Here a simple sketch illustrating the issue.

@lehni
Copy link
Member

lehni commented Jan 6, 2016

Hmmm... Since this handle is pointing to the left, do you think it's actually right that this is considered a straight curve? I'm not quite sure yet what's the right way to deal with this issue...

@lehni lehni closed this as completed in 8cec4f9 Jan 6, 2016
@lehni
Copy link
Member

lehni commented Jan 6, 2016

Let me know if this works for you @iconexperience

@iconexperience
Copy link
Contributor Author

Yep, that seems to work. It's consistent with isStraight() and it's a very simple and elegant solution. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants