parent
9c037fc826
commit
81d84e6f85
@ -18,8 +18,8 @@ __all__ = [
|
||||
|
||||
from fontTools.misc.arrayTools import calcBounds
|
||||
|
||||
epsilonDigits = 12
|
||||
epsilon = 1e-12
|
||||
epsilonDigits = 6
|
||||
epsilon = 1e-10
|
||||
|
||||
|
||||
def calcQuadraticBounds(pt1, pt2, pt3):
|
||||
|
@ -11,12 +11,6 @@ from fontTools.misc.bezierTools import solveQuadratic, solveCubic
|
||||
__all__ = ["PointInsidePen"]
|
||||
|
||||
|
||||
# working around floating point errors
|
||||
EPSILON = 1e-10
|
||||
ONE_PLUS_EPSILON = 1 + EPSILON
|
||||
ZERO_MINUS_EPSILON = 0 - EPSILON
|
||||
|
||||
|
||||
class PointInsidePen(BasePen):
|
||||
|
||||
"""This pen implements "point inside" testing: to test whether
|
||||
@ -123,7 +117,7 @@ class PointInsidePen(BasePen):
|
||||
by = (y3 - y2) * 3.0 - cy
|
||||
ay = y4 - dy - cy - by
|
||||
solutions = sorted(solveCubic(ay, by, cy, dy - y))
|
||||
solutions = [t for t in solutions if ZERO_MINUS_EPSILON <= t <= ONE_PLUS_EPSILON]
|
||||
solutions = [t for t in solutions if -0. <= t <= 1.]
|
||||
if not solutions:
|
||||
return
|
||||
|
||||
@ -142,29 +136,30 @@ class PointInsidePen(BasePen):
|
||||
t3 = t2 * t
|
||||
|
||||
direction = 3*ay*t2 + 2*by*t + cy
|
||||
incomingGoingUp = outgoingGoingUp = direction > 0.0
|
||||
if direction == 0.0:
|
||||
direction = 6*ay*t + 2*by
|
||||
outgoingGoingUp = direction > 0.0
|
||||
incomingGoingUp = not outgoingGoingUp
|
||||
if direction == 0.0:
|
||||
direction = ay
|
||||
goingUp = direction > 0.0
|
||||
incomingGoingUp = outgoingGoingUp = direction > 0.0
|
||||
|
||||
xt = ax*t3 + bx*t2 + cx*t + dx
|
||||
if xt < x:
|
||||
above = goingUp
|
||||
continue
|
||||
|
||||
if t == 0.0:
|
||||
if not goingUp:
|
||||
self._addIntersection(goingUp)
|
||||
if t in (0.0, -0.0):
|
||||
if not outgoingGoingUp:
|
||||
self._addIntersection(outgoingGoingUp)
|
||||
elif t == 1.0:
|
||||
if not above:
|
||||
self._addIntersection(goingUp)
|
||||
if incomingGoingUp:
|
||||
self._addIntersection(incomingGoingUp)
|
||||
else:
|
||||
if above != goingUp:
|
||||
self._addIntersection(goingUp)
|
||||
if incomingGoingUp == outgoingGoingUp:
|
||||
self._addIntersection(outgoingGoingUp)
|
||||
#else:
|
||||
# we're not really intersecting, merely touching the 'top'
|
||||
above = goingUp
|
||||
# we're not really intersecting, merely touching
|
||||
|
||||
def _qCurveToOne_unfinished(self, bcp, point):
|
||||
# XXX need to finish this, for now doing it through a cubic
|
||||
|
@ -71,34 +71,6 @@ class PointInsidePenTest(unittest.TestCase):
|
||||
"** ***",
|
||||
self.render(draw_qCurves, even_odd=False))
|
||||
|
||||
def test_contour_integers(self):
|
||||
def draw_contour(pen):
|
||||
pen.moveTo( (728, 697) )
|
||||
pen.curveTo( (723, 698) , (718, 699) , (713, 699) )
|
||||
pen.lineTo( (504, 699) )
|
||||
pen.curveTo( (487, 719) , (508, 783) , (556, 783) )
|
||||
pen.lineTo( (718, 783) )
|
||||
pen.curveTo( (739, 783) , (749, 712) , (728, 697) )
|
||||
pen.closePath()
|
||||
|
||||
piPen = PointInsidePen(None, (416, 783)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.getResult(), False)
|
||||
|
||||
def test_contour_decimals(self):
|
||||
def draw_contour(pen):
|
||||
pen.moveTo( (727.546875, 697.0) )
|
||||
pen.curveTo( (722.953125, 697.953125), (718.109375, 698.515625), (712.9375, 698.515625) )
|
||||
pen.lineTo( (504.375, 698.515625) )
|
||||
pen.curveTo( (487.328125, 719.359375), (507.84375, 783.140625), (555.796875, 783.140625) )
|
||||
pen.lineTo( (717.96875, 783.140625) )
|
||||
pen.curveTo( (738.890625, 783.140625), (748.796875, 711.5), (727.546875, 697.0) )
|
||||
pen.closePath()
|
||||
|
||||
piPen = PointInsidePen(None, (416.625, 783.140625)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.getResult(), False)
|
||||
|
||||
@staticmethod
|
||||
def render(draw_function, even_odd):
|
||||
result = BytesIO()
|
||||
@ -113,6 +85,56 @@ class PointInsidePenTest(unittest.TestCase):
|
||||
return tounicode(result.getvalue())
|
||||
|
||||
|
||||
def test_contour_diamond(self):
|
||||
def draw_contour(pen):
|
||||
pen.moveTo( (0, 100) )
|
||||
pen.lineTo( (100, 0) )
|
||||
pen.lineTo( (0, -100) )
|
||||
pen.lineTo( (-100, 0) )
|
||||
pen.closePath()
|
||||
|
||||
piPen = PointInsidePen(None, (-200, 0)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.intersectionCount, 0)
|
||||
|
||||
piPen = PointInsidePen(None, (-200, 100)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.intersectionCount, 0)
|
||||
|
||||
piPen = PointInsidePen(None, (-200, -100)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.intersectionCount, 0)
|
||||
|
||||
piPen = PointInsidePen(None, (-200, 50)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.intersectionCount, 0)
|
||||
|
||||
def test_contour_integers(self):
|
||||
def draw_contour(pen):
|
||||
pen.moveTo( (728, 697) )
|
||||
pen.lineTo( (504, 699) )
|
||||
pen.curveTo( (487, 719) , (508, 783) , (556, 783) )
|
||||
pen.lineTo( (718, 783) )
|
||||
pen.curveTo( (739, 783) , (749, 712) , (728, 697) )
|
||||
pen.closePath()
|
||||
|
||||
piPen = PointInsidePen(None, (416, 783)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.intersectionCount, 0)
|
||||
|
||||
def test_contour_decimals(self):
|
||||
def draw_contour(pen):
|
||||
pen.moveTo( (727.546875, 697.0) )
|
||||
pen.lineTo( (504.375, 698.515625) )
|
||||
pen.curveTo( (487.328125, 719.359375), (507.84375, 783.140625), (555.796875, 783.140625) )
|
||||
pen.lineTo( (717.96875, 783.140625) )
|
||||
pen.curveTo( (738.890625, 783.140625), (748.796875, 711.5), (727.546875, 697.0) )
|
||||
pen.closePath()
|
||||
|
||||
piPen = PointInsidePen(None, (416.625, 783.140625)) # this point is outside
|
||||
draw_contour(piPen)
|
||||
self.assertEqual(piPen.intersectionCount, 0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user