def findIntersection_naive(self, other_segment, debugMode=False): point = TFSIntersection.calculateIntersectPoint(self.startPoint(), self.endPoint(), other_segment.startPoint(), other_segment.endPoint(), debugMode=debugMode) # print 'findIntersection_naive', '', self.startPoint(), self.endPoint(), other_segment.startPoint(), other_segment.endPoint() # print 'findIntersection_naive', 'point', point if debugMode: print 'findIntersection_naive', 'point', point if not point: if debugMode: print 'findIntersection_naive.0' return None def findT(p0, p1, p): if p0.x == p1.x: return inferTValue(p0.y, p1.y, p.y) else: return inferTValue(p0.x, p1.x, p.x) def interpolateT(startT, endT, t): result = startT + (endT - startT) * t # print 'interpolateT', startT, endT, 't', t, '->', result return result selfT = findT(self.startPoint(), self.endPoint(), point) selfT = interpolateT(self.startT, self.endT, selfT) otherT = findT(other_segment.startPoint(), other_segment.endPoint(), point) otherT = interpolateT(other_segment.startT, other_segment.endT, otherT) if debugMode: print 'findIntersection_naive.3' return selfT, otherT, point
def validate(self): try: if not onJython: import types if type(self.points) not in (types.ListType, types.TupleType): raise TFSValidationException('Unexpected points type: ' + str(type(self.points))) for point in self.points: if not isinstance(point, TFSPoint): raise TFSValidationException( 'Unexpected points type: ' + str(type(point))) if not (2 <= len(self.points) <= 4): raise TFSValidationException('Invalid segment') for point in self.points: point.validate() if self.startPoint() == self.endPoint(): print 'self.startPoint()', self.startPoint( ), 'self.endPoint()', self.endPoint() raise TFSValidationException('Empty segment') startVector = self.startVector() endVector = self.endVector() if startVector is None: raise TFSValidationException('Empty start vector') if endVector is None: raise TFSValidationException('Empty end vector') # if startVector.length() == 0: # print 'startVector', startVector # raise TFSValidationException('Empty start vector') # if endVector.length() == 0: # print 'endVector', endVector # raise TFSValidationException('Empty end vector') if len(self) == 4: cpIntersection = TFSIntersection.calculateIntersectPoint( *self.points) if cpIntersection is not None: startVectorLength = startVector.length() endVectorLength = endVector.length() startIntersectionLength = cpIntersection.distanceTo( self.startPoint()) endIntersectionLength = cpIntersection.distanceTo( self.endPoint()) if ((startIntersectionLength <= startVectorLength * 0.5) and (endIntersectionLength <= endVectorLength * 0.5)): # this curve will cross itself. # print 'cpIntersection', cpIntersection.description() # print 'startVectorLength', startVectorLength # print 'endVectorLength', endVectorLength # print 'startIntersectionLength', startIntersectionLength # print 'endIntersectionLength', endIntersectionLength # print 'hmm', startIntersectionLength, startVectorLength * 0.5, startIntersectionLength > startVectorLength * 0.5 raise TFSValidationException('Crossed cubic bezier') except TFSValidationException, e: print 'TFSSegment.validate', self.description() raise e
def validate(self): try: if not onJython: import types if type(self.points) not in (types.ListType, types.TupleType): raise TFSValidationException("Unexpected points type: " + str(type(self.points))) for point in self.points: if not isinstance(point, TFSPoint): raise TFSValidationException("Unexpected points type: " + str(type(point))) if not (2 <= len(self.points) <= 4): raise TFSValidationException("Invalid segment") for point in self.points: point.validate() if self.startPoint() == self.endPoint(): print "self.startPoint()", self.startPoint(), "self.endPoint()", self.endPoint() raise TFSValidationException("Empty segment") startVector = self.startVector() endVector = self.endVector() if startVector is None: raise TFSValidationException("Empty start vector") if endVector is None: raise TFSValidationException("Empty end vector") # if startVector.length() == 0: # print 'startVector', startVector # raise TFSValidationException('Empty start vector') # if endVector.length() == 0: # print 'endVector', endVector # raise TFSValidationException('Empty end vector') if len(self) == 4: cpIntersection = TFSIntersection.calculateIntersectPoint(*self.points) if cpIntersection is not None: startVectorLength = startVector.length() endVectorLength = endVector.length() startIntersectionLength = cpIntersection.distanceTo(self.startPoint()) endIntersectionLength = cpIntersection.distanceTo(self.endPoint()) if (startIntersectionLength <= startVectorLength * 0.5) and ( endIntersectionLength <= endVectorLength * 0.5 ): # this curve will cross itself. # print 'cpIntersection', cpIntersection.description() # print 'startVectorLength', startVectorLength # print 'endVectorLength', endVectorLength # print 'startIntersectionLength', startIntersectionLength # print 'endIntersectionLength', endIntersectionLength # print 'hmm', startIntersectionLength, startVectorLength * 0.5, startIntersectionLength > startVectorLength * 0.5 raise TFSValidationException("Crossed cubic bezier") except TFSValidationException, e: print "TFSSegment.validate", self.description() raise e
def splitLineWithLine(l0, l1): if not l0.isStraightLine(): raise Exception('Not a straight line') if not l1.isStraightLine(): raise Exception('Not a straight line') p00 = l0.startPoint() p01 = l0.endPoint() p10 = l1.startPoint() p11 = l1.endPoint() intersect = TFSIntersection.calculateIntersectPoint(p00, p01, p10, p11) if intersect is None: raise Exception('lines do not intersect') return openPathWithPoints(p00, intersect), openPathWithPoints(intersect, p01)
def inflateSegmentLeft(segment, hDistance, vDistance): p0 = segment.startPoint() p1 = segment.endPoint() startTangent = segment.startTangent() if len(segment) == 2: offset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) p0 = p0.plus(offset) p1 = p1.plus(offset) newPoints = (p0, p1) elif len(segment) == 3: endTangent = segment.endTangent() startOffset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) endOffset = scaleVectorHV(endTangent.rotate(math.pi * 0.5), hDistance, vDistance) p0 = p0.plus(startOffset) p1 = p1.plus(endOffset) cp0 = TFSntersection.intersectionWithTangents(p0, startTangent, p1, endTangent.invert()) newPoints = (p0, cp0, p1) elif len(segment) == 4: endTangent = segment.endTangent() startOffset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) endOffset = scaleVectorHV(endTangent.rotate(math.pi * 0.5), hDistance, vDistance) oldScale = p0.distanceTo(p1) p0 = p0.plus(startOffset) p1 = p1.plus(endOffset) newScale = p0.distanceTo(p1) cp0 = p0.plus(segment.startVector().scale(newScale / oldScale)) cp1 = p1.minus(segment.endVector().scale(newScale / oldScale)) newPoints = (p0, cp0, cp1, p1) else: raise Exception('Invalid segment') try: return TFSSegment(*newPoints).roundWithDefaultPrecision() except TFSValidationException, e: ''' Inflating a segment can result in an empty or otherwise invalid segment. In fact, this will happen often since we'll be deflating previously inflated rounding curves. That's fine; ignore them. ''' return None
def findIntersection_naive(self, other_segment, debugMode=False): point = TFSIntersection.calculateIntersectPoint( self.startPoint(), self.endPoint(), other_segment.startPoint(), other_segment.endPoint(), debugMode=debugMode) # print 'findIntersection_naive', '', self.startPoint(), self.endPoint(), other_segment.startPoint(), other_segment.endPoint() # print 'findIntersection_naive', 'point', point if debugMode: print 'findIntersection_naive', 'point', point if not point: if debugMode: print 'findIntersection_naive.0' return None def findT(p0, p1, p): if p0.x == p1.x: return inferTValue(p0.y, p1.y, p.y) elif p0.y == p1.y: return inferTValue(p0.x, p1.x, p.x) else: tx = inferTValue(p0.x, p1.x, p.x) ty = inferTValue(p0.y, p1.y, p.y) return (tx + ty) * 0.5 def interpolateT(startT, endT, t): result = startT + (endT - startT) * t # print 'interpolateT', startT, endT, 't', t, '->', result return result selfT = findT(self.startPoint(), self.endPoint(), point) selfT = interpolateT(self.startT, self.endT, selfT) otherT = findT(other_segment.startPoint(), other_segment.endPoint(), point) otherT = interpolateT(other_segment.startT, other_segment.endT, otherT) if debugMode: print 'findIntersection_naive.3' return selfT, otherT, point
def _flateSegmentLeft(segment, hDistance, vDistance=None): """ """ if vDistance is None: vDistance = hDistance if segment.startVector().length() == 0 or segment.endVector().length() == 0: raise Exception("Cannot flate a segment without valid tangents: " + segment.description()) p0 = segment.startPoint() p1 = segment.endPoint() startTangent = segment.startTangent() if len(segment) == 2: offset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) p0 = p0.plus(offset) p1 = p1.plus(offset) newPoints = (p0, p1) elif len(segment) == 3: endTangent = segment.endTangent() startOffset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) endOffset = scaleVectorHV(endTangent.rotate(math.pi * 0.5), hDistance, vDistance) p0 = p0.plus(startOffset) p1 = p1.plus(endOffset) cp0 = TFSntersection.intersectionWithTangents(p0, startTangent, p1, endTangent.invert()) newPoints = (p0, cp0, p1) elif len(segment) == 4: endTangent = segment.endTangent() startOffset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) endOffset = scaleVectorHV(endTangent.rotate(math.pi * 0.5), hDistance, vDistance) oldScale = p0.distanceTo(p1) p0 = p0.plus(startOffset) p1 = p1.plus(endOffset) newScale = p0.distanceTo(p1) cp0 = p0.plus(segment.startVector().scale(newScale / oldScale)) cp1 = p1.minus(segment.endVector().scale(newScale / oldScale)) newPoints = (p0, cp0, cp1, p1) else: raise Exception("Invalid segment") try: result = TFSSegment(*newPoints).roundWithDefaultPrecision() """ Segments can be turned "inside out" when deflating. For example, deflating an arc by more than its "radius". We want to discard these segments. We can detect them by checking whether the naive endpoint tangent has reversed. """ affinity = result.naiveEndpointTangent().dotProduct(segment.naiveEndpointTangent()) if affinity < 0: return None return result except TFSValidationException, e: """ flating a segment can result in an empty or otherwise invalid segment. In fact, this will happen often since we'll be deflating previously inflated rounding curves. That's fine; ignore them. """ return None
def _flateSegmentLeft(segment, hDistance, vDistance=None): ''' ''' if vDistance is None: vDistance = hDistance if (segment.startVector().length() == 0 or segment.endVector().length() == 0): raise Exception('Cannot flate a segment without valid tangents: ' + segment.description()) p0 = segment.startPoint() p1 = segment.endPoint() startTangent = segment.startTangent() if len(segment) == 2: offset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) p0 = p0.plus(offset) p1 = p1.plus(offset) newPoints = (p0, p1) elif len(segment) == 3: endTangent = segment.endTangent() startOffset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) endOffset = scaleVectorHV(endTangent.rotate(math.pi * 0.5), hDistance, vDistance) p0 = p0.plus(startOffset) p1 = p1.plus(endOffset) cp0 = TFSntersection.intersectionWithTangents(p0, startTangent, p1, endTangent.invert()) newPoints = (p0, cp0, p1) elif len(segment) == 4: endTangent = segment.endTangent() startOffset = scaleVectorHV(startTangent.rotate(math.pi * 0.5), hDistance, vDistance) endOffset = scaleVectorHV(endTangent.rotate(math.pi * 0.5), hDistance, vDistance) oldScale = p0.distanceTo(p1) p0 = p0.plus(startOffset) p1 = p1.plus(endOffset) newScale = p0.distanceTo(p1) cp0 = p0.plus(segment.startVector().scale(newScale / oldScale)) cp1 = p1.minus(segment.endVector().scale(newScale / oldScale)) newPoints = (p0, cp0, cp1, p1) else: raise Exception('Invalid segment') try: result = TFSSegment(*newPoints).roundWithDefaultPrecision() ''' Segments can be turned "inside out" when deflating. For example, deflating an arc by more than its "radius". We want to discard these segments. We can detect them by checking whether the naive endpoint tangent has reversed. ''' affinity = result.naiveEndpointTangent().dotProduct( segment.naiveEndpointTangent()) if affinity < 0: return None return result except TFSValidationException as e: ''' flating a segment can result in an empty or otherwise invalid segment. In fact, this will happen often since we'll be deflating previously inflated rounding curves. That's fine; ignore them. ''' return None