def getRadialPath(begin, center, end, path): "Get radial path." beginComplex = begin.dropAxis() endComplex = end.dropAxis() centerComplex = center.dropAxis() beginMinusCenterComplex = beginComplex - centerComplex endMinusCenterComplex = endComplex - centerComplex beginMinusCenterComplexRadius = abs(beginMinusCenterComplex) endMinusCenterComplexRadius = abs(endMinusCenterComplex) if beginMinusCenterComplexRadius == 0.0 or endMinusCenterComplexRadius == 0.0: return [begin] beginMinusCenterComplex /= beginMinusCenterComplexRadius endMinusCenterComplex /= endMinusCenterComplexRadius angleDifference = euclidean.getAngleDifferenceByComplex( endMinusCenterComplex, beginMinusCenterComplex) radialPath = [] for point in path: weightEnd = point.x weightBegin = 1.0 - weightEnd weightedRadius = beginMinusCenterComplexRadius * weightBegin + endMinusCenterComplexRadius * weightEnd * ( 1.0 + point.y) radialComplex = weightedRadius * euclidean.getWiddershinsUnitPolar( angleDifference * point.x) * beginMinusCenterComplex polygonPoint = center + Vector3(radialComplex.real, radialComplex.imag, point.z) radialPath.append(polygonPoint) return radialPath
def getRadialPath(begin, end, path, segmentCenter): "Get radial path." beginComplex = begin.dropAxis() endComplex = end.dropAxis() segmentCenterComplex = segmentCenter.dropAxis() beginMinusCenterComplex = beginComplex - segmentCenterComplex endMinusCenterComplex = endComplex - segmentCenterComplex beginMinusCenterComplexRadius = abs(beginMinusCenterComplex) endMinusCenterComplexRadius = abs(endMinusCenterComplex) if beginMinusCenterComplexRadius == 0.0 or endMinusCenterComplexRadius == 0.0: return [begin] beginMinusCenterComplex /= beginMinusCenterComplexRadius endMinusCenterComplex /= endMinusCenterComplexRadius angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCenterComplex, beginMinusCenterComplex) radialPath = [] for point in path: weightEnd = point.x weightBegin = 1.0 - weightEnd weightedRadius = beginMinusCenterComplexRadius * weightBegin + endMinusCenterComplexRadius * weightEnd * ( 1.0 + point.y ) radialComplex = ( weightedRadius * euclidean.getWiddershinsUnitPolar(angleDifference * point.x) * beginMinusCenterComplex ) polygonPoint = segmentCenter + Vector3(radialComplex.real, radialComplex.imag, point.z) radialPath.append(polygonPoint) return radialPath
def splitPointGetAfter(self, location, nextLocation): "Fillet a point into arc segments and return the end of the last segment." if self.filletRadius < 2.0 * self.minimumRadius: return location afterSegment = nextLocation - location afterSegmentComplex = afterSegment.dropAxis(2) thirdAfterSegmentLength = 0.333 * abs(afterSegmentComplex) if thirdAfterSegmentLength < self.minimumRadius: return location beforeSegment = self.oldLocation - location beforeSegmentComplex = beforeSegment.dropAxis(2) thirdBeforeSegmentLength = 0.333 * abs(beforeSegmentComplex) if thirdBeforeSegmentLength < self.minimumRadius: return location extruderOffReversalPoint = self.getExtruderOffReversalPoint( afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location) if extruderOffReversalPoint != None: return extruderOffReversalPoint bevelRadius = min(thirdAfterSegmentLength, self.filletRadius) bevelRadius = min(thirdBeforeSegmentLength, bevelRadius) self.shouldAddLine = False beforePoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs(beforeSegment) / abs(beforeSegmentComplex), location, beforeSegment) self.addLinearMovePoint(self.feedRateMinute, beforePoint) afterPoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs(afterSegment) / abs(afterSegmentComplex), location, afterSegment) afterPointComplex = afterPoint.dropAxis(2) beforePointComplex = beforePoint.dropAxis(2) locationComplex = location.dropAxis(2) midpoint = 0.5 * (afterPoint + beforePoint) midpointComplex = midpoint.dropAxis(2) midpointMinusLocationComplex = midpointComplex - locationComplex midpointLocationLength = abs(midpointMinusLocationComplex) if midpointLocationLength < 0.01 * self.filletRadius: self.addLinearMovePoint(self.getCornerFeedRate(), afterPoint) return afterPoint midpointAfterPointLength = abs(midpointComplex - afterPointComplex) midpointCenterLength = midpointAfterPointLength * midpointAfterPointLength / midpointLocationLength radius = math.sqrt(midpointCenterLength * midpointCenterLength + midpointAfterPointLength * midpointAfterPointLength) centerComplex = midpointComplex + midpointMinusLocationComplex * midpointCenterLength / midpointLocationLength center = Vector3(centerComplex.real, centerComplex.imag, midpoint.z) afterCenterComplex = afterPointComplex - centerComplex beforeCenter = beforePoint - center angleDifference = euclidean.getAngleDifferenceByComplex( afterCenterComplex, beforeCenter.dropAxis()) self.addArc(angleDifference, afterPoint, beforeCenter, beforePoint, center) return afterPoint
def splitPointGetAfter(self, location, nextLocation): "Fillet a point into arc segments and return the end of the last segment." if self.filletRadius < 2.0 * self.minimumRadius: return location afterSegment = nextLocation - location afterSegmentComplex = afterSegment.dropAxis(2) thirdAfterSegmentLength = 0.333 * abs(afterSegmentComplex) if thirdAfterSegmentLength < self.minimumRadius: return location beforeSegment = self.oldLocation - location beforeSegmentComplex = beforeSegment.dropAxis(2) thirdBeforeSegmentLength = 0.333 * abs(beforeSegmentComplex) if thirdBeforeSegmentLength < self.minimumRadius: return location extruderOffReversalPoint = self.getExtruderOffReversalPoint( afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location ) if extruderOffReversalPoint != None: return extruderOffReversalPoint bevelRadius = min(thirdAfterSegmentLength, self.filletRadius) bevelRadius = min(thirdBeforeSegmentLength, bevelRadius) self.shouldAddLine = False beforePoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs(beforeSegment) / abs(beforeSegmentComplex), location, beforeSegment ) self.addLinearMovePoint(self.feedRateMinute, beforePoint) afterPoint = euclidean.getPointPlusSegmentWithLength( bevelRadius * abs(afterSegment) / abs(afterSegmentComplex), location, afterSegment ) afterPointComplex = afterPoint.dropAxis(2) beforePointComplex = beforePoint.dropAxis(2) locationComplex = location.dropAxis(2) midpoint = 0.5 * (afterPoint + beforePoint) midpointComplex = midpoint.dropAxis(2) midpointMinusLocationComplex = midpointComplex - locationComplex midpointLocationLength = abs(midpointMinusLocationComplex) if midpointLocationLength < 0.01 * self.filletRadius: self.addLinearMovePoint(self.getCornerFeedRate(), afterPoint) return afterPoint midpointAfterPointLength = abs(midpointComplex - afterPointComplex) midpointCenterLength = midpointAfterPointLength * midpointAfterPointLength / midpointLocationLength radius = math.sqrt( midpointCenterLength * midpointCenterLength + midpointAfterPointLength * midpointAfterPointLength ) centerComplex = midpointComplex + midpointMinusLocationComplex * midpointCenterLength / midpointLocationLength center = Vector3(centerComplex.real, centerComplex.imag, midpoint.z) afterCenterComplex = afterPointComplex - centerComplex beforeCenter = beforePoint - center angleDifference = euclidean.getAngleDifferenceByComplex(afterCenterComplex, beforeCenter.dropAxis()) self.addArc(angleDifference, afterPoint, beforeCenter, beforePoint, center) return afterPoint
def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) beginRotated = begin * reverseXAxisRotationComplex beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) endRotated = end * reverseXAxisRotationComplex endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) midpointTransformed = 0.5 * (beginTransformed + endTransformed) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs(midMinusBeginTransformed) midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength if midWiddershinsLengthSquared < 0.0: print('Warning, the radius is too small for getArcComplexes in svgReader') print(begin) print(end) print(radius) return [] midWiddershinsLength = midWiddershinsLengthSquared midWiddershinsTransformed *= midWiddershinsLength / abs(midWiddershinsTransformed) centerTransformed = midpointTransformed if largeArcFlag == sweepFlag: centerTransformed -= midWiddershinsTransformed else: centerTransformed += midWiddershinsTransformed beginMinusCenterTransformed = beginTransformed - centerTransformed beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed) if beginMinusCenterTransformedLength <= 0.0: return end beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real) endMinusCenterTransformed = endTransformed - centerTransformed angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCenterTransformed, beginMinusCenterTransformed) if sweepFlag: if angleDifference < 0.0: angleDifference += 2.0 * math.pi else: if angleDifference > 0.0: angleDifference -= 2.0 * math.pi global globalSideAngle sides = int(math.ceil(abs(angleDifference) / globalSideAngle)) sideAngle = angleDifference / float(sides) arcComplexes = [] center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex for side in xrange(1, sides): unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle + float(side) * sideAngle) circumferential = complex(unitPolar.real * radius.real, unitPolar.imag * radius.imag) * beginMinusCenterTransformedLength point = center + circumferential * xAxisRotationComplex arcComplexes.append(point) arcComplexes.append(end) return arcComplexes
def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) beginRotated = begin * reverseXAxisRotationComplex beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) endRotated = end * reverseXAxisRotationComplex endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) midpointTransformed = 0.5 * (beginTransformed + endTransformed) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs(midMinusBeginTransformed) midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength if midWiddershinsLengthSquared < 0.0: print('Warning, the radius is too small for getArcComplexes in svgReader') print(begin) print(end) print(radius) return [] midWiddershinsLength = midWiddershinsLengthSquared midWiddershinsTransformed *= midWiddershinsLength / abs(midWiddershinsTransformed) centerTransformed = midpointTransformed if largeArcFlag == sweepFlag: centerTransformed -= midWiddershinsTransformed else: centerTransformed += midWiddershinsTransformed beginMinusCenterTransformed = beginTransformed - centerTransformed beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed) if beginMinusCenterTransformedLength <= 0.0: return end beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real) endMinusCenterTransformed = endTransformed - centerTransformed angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCenterTransformed, beginMinusCenterTransformed) if sweepFlag: if angleDifference < 0.0: angleDifference += 2.0 * math.pi else: if angleDifference > 0.0: angleDifference -= 2.0 * math.pi global globalSideAngle sides = int(math.ceil(abs(angleDifference) / globalSideAngle)) sideAngle = angleDifference / float(sides) arcComplexes = [] center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex for side in xrange(1, sides): unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle + float(side) * sideAngle) circumferential = complex(unitPolar.real * radius.real, unitPolar.imag * radius.imag) * beginMinusCenterTransformedLength point = center + circumferential * xAxisRotationComplex arcComplexes.append(point) arcComplexes.append(end) return arcComplexes
def getRoundPath(begin, center, close, end, radius, sidesPerRadian): "Get round path." beginComplex = begin.dropAxis() centerComplex = center.dropAxis() endComplex = end.dropAxis() beginComplexSegmentLength = abs(centerComplex - beginComplex) endComplexSegmentLength = abs(centerComplex - endComplex) minimumRadius = lineation.getMinimumRadius(beginComplexSegmentLength, endComplexSegmentLength, radius) if minimumRadius <= close: return [center] beginBevel = center + minimumRadius / beginComplexSegmentLength * (begin - center) endBevel = center + minimumRadius / endComplexSegmentLength * (end - center) beginBevelComplex = beginBevel.dropAxis() endBevelComplex = endBevel.dropAxis() midpointComplex = 0.5 * (beginBevelComplex + endBevelComplex) if radius < 0.0: centerComplex = midpointComplex + midpointComplex - centerComplex midpointMinusCenterComplex = midpointComplex - centerComplex midpointCenterLength = abs(midpointMinusCenterComplex) midpointEndLength = abs(midpointComplex - endBevelComplex) midpointCircleCenterLength = midpointEndLength * midpointEndLength / midpointCenterLength circleRadius = math.sqrt(midpointCircleCenterLength * midpointCircleCenterLength + midpointEndLength * midpointEndLength) circleCenterComplex = midpointComplex + midpointMinusCenterComplex * midpointCircleCenterLength / midpointCenterLength circleCenter = Vector3(circleCenterComplex.real, circleCenterComplex.imag, center.z) endMinusCircleCenterComplex = endBevelComplex - circleCenterComplex beginMinusCircleCenter = beginBevel - circleCenter beginMinusCircleCenterComplex = beginMinusCircleCenter.dropAxis() angleDifference = euclidean.getAngleDifferenceByComplex( endMinusCircleCenterComplex, beginMinusCircleCenterComplex) steps = int(math.ceil(abs(angleDifference) * sidesPerRadian)) stepPlaneAngle = euclidean.getWiddershinsUnitPolar(angleDifference / float(steps)) deltaZStep = (end.z - begin.z) / float(steps) roundPath = [beginBevel] for step in xrange(1, steps): beginMinusCircleCenterComplex = beginMinusCircleCenterComplex * stepPlaneAngle arcPointComplex = circleCenterComplex + beginMinusCircleCenterComplex arcPoint = Vector3(arcPointComplex.real, arcPointComplex.imag, begin.z + deltaZStep * step) roundPath.append(arcPoint) return roundPath + [endBevel]
def getRoundPath(begin, center, close, end, radius, sidesPerRadian): "Get round path." beginComplex = begin.dropAxis() centerComplex = center.dropAxis() endComplex = end.dropAxis() beginComplexSegmentLength = abs(centerComplex - beginComplex) endComplexSegmentLength = abs(centerComplex - endComplex) minimumRadius = lineation.getMinimumRadius(beginComplexSegmentLength, endComplexSegmentLength, radius) if minimumRadius <= close: return [center] beginBevel = center + minimumRadius / beginComplexSegmentLength * (begin - center) endBevel = center + minimumRadius / endComplexSegmentLength * (end - center) beginBevelComplex = beginBevel.dropAxis() endBevelComplex = endBevel.dropAxis() midpointComplex = 0.5 * (beginBevelComplex + endBevelComplex) if radius < 0.0: centerComplex = midpointComplex + midpointComplex - centerComplex midpointMinusCenterComplex = midpointComplex - centerComplex midpointCenterLength = abs(midpointMinusCenterComplex) midpointEndLength = abs(midpointComplex - endBevelComplex) midpointCircleCenterLength = midpointEndLength * midpointEndLength / midpointCenterLength circleRadius = math.sqrt( midpointCircleCenterLength * midpointCircleCenterLength + midpointEndLength * midpointEndLength ) circleCenterComplex = ( midpointComplex + midpointMinusCenterComplex * midpointCircleCenterLength / midpointCenterLength ) circleCenter = Vector3(circleCenterComplex.real, circleCenterComplex.imag, center.z) endMinusCircleCenterComplex = endBevelComplex - circleCenterComplex beginMinusCircleCenter = beginBevel - circleCenter beginMinusCircleCenterComplex = beginMinusCircleCenter.dropAxis() angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCircleCenterComplex, beginMinusCircleCenterComplex) steps = int(math.ceil(abs(angleDifference) * sidesPerRadian)) stepPlaneAngle = euclidean.getWiddershinsUnitPolar(angleDifference / float(steps)) deltaZStep = (end.z - begin.z) / float(steps) roundPath = [beginBevel] for step in xrange(1, steps): beginMinusCircleCenterComplex = beginMinusCircleCenterComplex * stepPlaneAngle arcPointComplex = circleCenterComplex + beginMinusCircleCenterComplex arcPoint = Vector3(arcPointComplex.real, arcPointComplex.imag, begin.z + deltaZStep * step) roundPath.append(arcPoint) return roundPath + [endBevel]
def getArcComplexes( begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation ): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' beginTransformed = complex( begin.real / radius.real, begin.imag / radius.imag ) endTransformed = complex( end.real / radius.real, end.imag / radius.imag ) midpointTransformed = 0.5 * ( beginTransformed + endTransformed ) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs( midMinusBeginTransformed ) midWiddershinsTransformed = complex( - midMinusBeginTransformed.imag, midMinusBeginTransformed.real ) midWiddershinsLength = math.sqrt( 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength ) midWiddershinsTransformed *= midWiddershinsLength / abs( midWiddershinsTransformed ) centerTransformed = midpointTransformed if largeArcFlag == sweepFlag: centerTransformed -= midWiddershinsTransformed else: centerTransformed += midWiddershinsTransformed beginMinusCenterTransformed = beginTransformed - centerTransformed beginAngle = math.atan2( beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real ) endMinusCenterTransformed = endTransformed - centerTransformed angleDifference = euclidean.getAngleDifferenceByComplex( endMinusCenterTransformed, beginMinusCenterTransformed ) if sweepFlag: if angleDifference < 0.0: angleDifference += 2.0 * math.pi else: if angleDifference > 0.0: angleDifference -= 2.0 * math.pi global globalSideAngle sides = int( math.ceil( abs( angleDifference ) / globalSideAngle ) ) sideAngle = angleDifference / sides arcComplexes = [] center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) for side in xrange( 1, sides ): unitPolar = euclidean.getWiddershinsUnitPolar( beginAngle + float(side) * sideAngle ) point = center + complex( unitPolar.real * radius.real, unitPolar.imag * radius.imag ) arcComplexes.append( point ) arcComplexes.append( end ) return arcComplexes
def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' if begin == end: print('Warning, begin equals end in getArcComplexes in svgReader') print(begin) print(end) return [] if radius.imag < 0.0: print('Warning, radius.imag is less than zero in getArcComplexes in svgReader') print(radius) radius = complex(radius.real, abs(radius.imag)) if radius.real < 0.0: print('Warning, radius.real is less than zero in getArcComplexes in svgReader') print(radius) radius = complex(abs(radius.real), radius.imag) if radius.imag <= 0.0: print('Warning, radius.imag is too small for getArcComplexes in svgReader') print(radius) return [end] if radius.real <= 0.0: print('Warning, radius.real is too small for getArcComplexes in svgReader') print(radius) return [end] xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) beginRotated = begin * reverseXAxisRotationComplex endRotated = end * reverseXAxisRotationComplex beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) midpointTransformed = 0.5 * (beginTransformed + endTransformed) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs(midMinusBeginTransformed) if midMinusBeginTransformedLength > 1.0: print('The ellipse radius is too small for getArcComplexes in svgReader.') print('So the ellipse will be scaled to fit, according to the formulas in "Step 3: Ensure radii are large enough" of:') print('http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii') print('') radius *= midMinusBeginTransformedLength beginTransformed /= midMinusBeginTransformedLength endTransformed /= midMinusBeginTransformedLength midpointTransformed /= midMinusBeginTransformedLength midMinusBeginTransformed /= midMinusBeginTransformedLength midMinusBeginTransformedLength = 1.0 midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength if midWiddershinsLengthSquared < 0.0: midWiddershinsLengthSquared = 0.0 midWiddershinsLength = math.sqrt(midWiddershinsLengthSquared) midWiddershinsTransformed *= midWiddershinsLength / abs(midWiddershinsTransformed) centerTransformed = midpointTransformed if largeArcFlag == sweepFlag: centerTransformed -= midWiddershinsTransformed else: centerTransformed += midWiddershinsTransformed beginMinusCenterTransformed = beginTransformed - centerTransformed beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed) if beginMinusCenterTransformedLength <= 0.0: return end beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real) endMinusCenterTransformed = endTransformed - centerTransformed angleDifference = euclidean.getAngleDifferenceByComplex(endMinusCenterTransformed, beginMinusCenterTransformed) if sweepFlag: if angleDifference < 0.0: angleDifference += 2.0 * math.pi else: if angleDifference > 0.0: angleDifference -= 2.0 * math.pi global globalSideAngle sides = int(math.ceil(abs(angleDifference) / globalSideAngle)) sideAngle = angleDifference / float(sides) arcComplexes = [] center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex for side in xrange(1, sides): unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle + float(side) * sideAngle) circumferential = complex(unitPolar.real * radius.real, unitPolar.imag * radius.imag) * beginMinusCenterTransformedLength point = center + circumferential * xAxisRotationComplex arcComplexes.append(point) arcComplexes.append(end) return arcComplexes
def getArcComplexes(begin, end, largeArcFlag, radius, sweepFlag, xAxisRotation): 'Get the arc complexes, procedure at http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes' if begin == end: print('Warning, begin equals end in getArcComplexes in svgReader') print(begin) print(end) return [] if radius.imag < 0.0: print( 'Warning, radius.imag is less than zero in getArcComplexes in svgReader' ) print(radius) radius = complex(radius.real, abs(radius.imag)) if radius.real < 0.0: print( 'Warning, radius.real is less than zero in getArcComplexes in svgReader' ) print(radius) radius = complex(abs(radius.real), radius.imag) if radius.imag <= 0.0: print( 'Warning, radius.imag is too small for getArcComplexes in svgReader' ) print(radius) return [end] if radius.real <= 0.0: print( 'Warning, radius.real is too small for getArcComplexes in svgReader' ) print(radius) return [end] xAxisRotationComplex = euclidean.getWiddershinsUnitPolar(xAxisRotation) reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag) beginRotated = begin * reverseXAxisRotationComplex endRotated = end * reverseXAxisRotationComplex beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag) endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag) midpointTransformed = 0.5 * (beginTransformed + endTransformed) midMinusBeginTransformed = midpointTransformed - beginTransformed midMinusBeginTransformedLength = abs(midMinusBeginTransformed) if midMinusBeginTransformedLength > 1.0: print( 'The ellipse radius is too small for getArcComplexes in svgReader.' ) print( 'So the ellipse will be scaled to fit, according to the formulas in "Step 3: Ensure radii are large enough" of:' ) print( 'http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii' ) print('') radius *= midMinusBeginTransformedLength beginTransformed /= midMinusBeginTransformedLength endTransformed /= midMinusBeginTransformedLength midpointTransformed /= midMinusBeginTransformedLength midMinusBeginTransformed /= midMinusBeginTransformedLength midMinusBeginTransformedLength = 1.0 midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real) midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength if midWiddershinsLengthSquared < 0.0: midWiddershinsLengthSquared = 0.0 midWiddershinsLength = math.sqrt(midWiddershinsLengthSquared) midWiddershinsTransformed *= midWiddershinsLength / abs( midWiddershinsTransformed) centerTransformed = midpointTransformed if largeArcFlag == sweepFlag: centerTransformed -= midWiddershinsTransformed else: centerTransformed += midWiddershinsTransformed beginMinusCenterTransformed = beginTransformed - centerTransformed beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed) if beginMinusCenterTransformedLength <= 0.0: return end beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real) endMinusCenterTransformed = endTransformed - centerTransformed angleDifference = euclidean.getAngleDifferenceByComplex( endMinusCenterTransformed, beginMinusCenterTransformed) if sweepFlag: if angleDifference < 0.0: angleDifference += 2.0 * math.pi else: if angleDifference > 0.0: angleDifference -= 2.0 * math.pi global globalSideAngle sides = int(math.ceil(abs(angleDifference) / globalSideAngle)) sideAngle = angleDifference / float(sides) arcComplexes = [] center = complex( centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex for side in xrange(1, sides): unitPolar = euclidean.getWiddershinsUnitPolar(beginAngle + float(side) * sideAngle) circumferential = complex( unitPolar.real * radius.real, unitPolar.imag * radius.imag) * beginMinusCenterTransformedLength point = center + circumferential * xAxisRotationComplex arcComplexes.append(point) arcComplexes.append(end) return arcComplexes