BezierKit icon indicating copy to clipboard operation
BezierKit copied to clipboard

`offset` seems to treat straight & curved segments differently

Open mbutterick opened this issue 3 years ago • 3 comments

All curves

Here’s an example of a capital O showing what happens when offset(10) is applied: each on-curve point is shifted in the offset direction by 10 units.

Screen Shot 2020-12-17 at Dec 17  10 39 30 AM Screen Shot 2020-12-17 at Dec 17  10 39 36 AM

All straights

Here’s an example of the same offset(10) applied to a capital H. In this case, the points are only moving 5 units from their original positions:

Screen Shot 2020-12-17 at Dec 17  10 39 16 AM Screen Shot 2020-12-17 at Dec 17  10 39 20 AM

Mix of curves and straights

Now here’s a capital D with offset(10). Whereas the O was only made of curves, and the H only made of straights, this combines both. The result is that the straight segments are moving only half the distance, so certain segments that should be parallel are not. For instance, the top and bottom edges are no longer horizontal.

Screen Shot 2020-12-17 at Dec 17  10 37 24 AM Screen Shot 2020-12-17 at Dec 17  10 37 30 AM

mbutterick avatar Dec 17 '20 18:12 mbutterick

Hello @mbutterick

Thank you once again for the level of detail you've gone into opening this issue.

I believe that what's going on here is that offset doesn't work properly with corners. I haven't given the offset method the attention it should get to ensure correctness. The behavior you're seeing at 90 degree corners where the point moves 1/2 the expected distance is because the code to compute the corner position is based on taking the average of the point's position if it were moved along one edge (vertically) and moved along the other edge (horizontally). The code needs a better approach.

hfutrell avatar Dec 17 '20 20:12 hfutrell

Instead of using a linear average of the startPoint and endPoint of curves that are noncontiguous after offset, I propose that the better idea is to project the intersection of the two segments, and then move the startPoint and endPoint of the offset curves to that intersection.

Here’s how that looks using the original test cases, still applying offset(10).

All curves

In this case, no change. Just like before, each on-curve point is shifted in the offset direction by 10 units.

Screen Shot 2021-10-20 at 1 56 31 PM Screen Shot 2021-10-20 at 1 56 42 PM

All straights

Previously, with linear averaging, the points were only moving a net 5 units from their original positions. But with projection, they all move 10 points.

Screen Shot 2021-10-20 at 1 56 56 PM Screen Shot 2021-10-20 at 1 57 03 PM

Mix of curves and straights

Previously, with linear averaging, the straight segments were moving only half the distance, but curve points were moving the full distance, resulting in top and bottom edges that were no longer horizontal. With projection, however, every point moves the correct distance, and parallelism is preserved:

Screen Shot 2021-10-20 at 1 57 09 PM Screen Shot 2021-10-20 at 1 57 14 PM

mbutterick avatar Oct 20 '21 21:10 mbutterick

PR #98 shows how I did this, though it is not offered as a fully tested work of art.

mbutterick avatar Oct 20 '21 21:10 mbutterick