Fix two problems when handling orthogonal lines

This commit is contained in:
Simon Cozens 2021-09-22 16:28:10 +01:00
parent 3a7c91602c
commit 1cc8bf0827
2 changed files with 25 additions and 7 deletions

View File

@ -879,12 +879,14 @@ def _line_t_of_pt(s, e, pt):
sx, sy = s sx, sy = s
ex, ey = e ex, ey = e
px, py = pt px, py = pt
if not math.isclose(sx, ex): if abs(sx - ex) < epsilon and abs(sy - ey) < epsilon:
# Line is a point!
return -1
# Use the largest
if abs(sx - ex) > abs(sy - ex):
return (px - sx) / (ex - sx) return (px - sx) / (ex - sx)
if not math.isclose(sy, ey): else:
return (py - sy) / (ey - sy) return (py - sy) / (ey - sy)
# Line is a point!
return -1
def _both_points_are_on_same_side_of_origin(a, b, origin): def _both_points_are_on_same_side_of_origin(a, b, origin):
@ -1024,7 +1026,11 @@ def curveLineIntersections(curve, line):
intersections = [] intersections = []
for t in _curve_line_intersections_t(curve, line): for t in _curve_line_intersections_t(curve, line):
pt = pointFinder(*curve, t) pt = pointFinder(*curve, t)
intersections.append(Intersection(pt=pt, t1=t, t2=_line_t_of_pt(*line, pt))) # Back-project the point onto the line, to avoid problems with
# numerical accuracy in the case of vertical and horizontal lines
line_t = _line_t_of_pt(*line, pt)
pt = linePointAtT(*line, line_t)
intersections.append(Intersection(pt=pt, t1=t, t2=line_t))
return intersections return intersections

View File

@ -1,6 +1,8 @@
import fontTools.misc.bezierTools as bezierTools
from fontTools.misc.bezierTools import ( from fontTools.misc.bezierTools import (
calcQuadraticBounds, calcCubicBounds, segmentPointAtT, splitLine, splitQuadratic, calcQuadraticBounds, calcCubicBounds, curveLineIntersections,
splitCubic, splitQuadraticAtT, splitCubicAtT, solveCubic) segmentPointAtT, splitLine, splitQuadratic, splitCubic, splitQuadraticAtT,
splitCubicAtT, solveCubic)
import pytest import pytest
@ -148,3 +150,13 @@ _segmentPointAtT_testData = [
def test_segmentPointAtT(segment, t, expectedPoint): def test_segmentPointAtT(segment, t, expectedPoint):
point = segmentPointAtT(segment, t) point = segmentPointAtT(segment, t)
assert expectedPoint == point assert expectedPoint == point
def test_intersections_straight_line():
curve = ((548, 183), (548, 289), (450, 366), (315, 366))
line1 = ((330, 376), (330, 286))
pt = curveLineIntersections(curve, line1)[0][0]
assert pt[0] == 330
line = (pt, (330, 286))
pt2 = (330.0001018806911, 295.5635754579425)
assert bezierTools._line_t_of_pt(*line, pt2) > 0