def getWedgePath(begin, centerBegin, centerEnd, centerEndMinusBegin, end, path): "Get segment path." beginComplex = begin.dropAxis() centerBeginComplex = centerBegin.dropAxis() centerEndComplex = centerEnd.dropAxis() endComplex = end.dropAxis() wedgePath = [] centerBeginMinusBeginComplex = euclidean.getNormalized(centerBeginComplex - beginComplex) centerEndMinusCenterBeginComplexOriginal = centerEndComplex - centerBeginComplex centerEndMinusCenterBeginComplexLength = abs( centerEndMinusCenterBeginComplexOriginal) if centerEndMinusCenterBeginComplexLength <= 0.0: return [centerBegin] centerEndMinusCenterBeginComplex = centerEndMinusCenterBeginComplexOriginal / centerEndMinusCenterBeginComplexLength endMinusCenterEndComplex = euclidean.getNormalized(endComplex - centerEndComplex) widdershinsBegin = getWiddershinsAverageByVector3( centerBeginMinusBeginComplex, centerEndMinusCenterBeginComplex) widdershinsEnd = getWiddershinsAverageByVector3( centerEndMinusCenterBeginComplex, endMinusCenterEndComplex) for point in path: weightEnd = point.x weightBegin = 1.0 - weightEnd polygonPoint = centerBegin + centerEndMinusBegin * point.x weightedWiddershins = widdershinsBegin * weightBegin + widdershinsEnd * weightEnd polygonPoint += weightedWiddershins * point.y * centerEndMinusCenterBeginComplexLength polygonPoint.z += point.z wedgePath.append(polygonPoint) return wedgePath
def getWedgePath( begin, centerBegin, centerEnd, centerEndMinusBegin, end, path ): "Get segment path." beginComplex = begin.dropAxis() centerBeginComplex = centerBegin.dropAxis() centerEndComplex = centerEnd.dropAxis() endComplex = end.dropAxis() wedgePath = [] centerBeginMinusBeginComplex = euclidean.getNormalized( centerBeginComplex - beginComplex ) centerEndMinusCenterBeginComplexOriginal = centerEndComplex - centerBeginComplex centerEndMinusCenterBeginComplexLength = abs( centerEndMinusCenterBeginComplexOriginal ) if centerEndMinusCenterBeginComplexLength <= 0.0: return [ centerBegin ] centerEndMinusCenterBeginComplex = centerEndMinusCenterBeginComplexOriginal / centerEndMinusCenterBeginComplexLength endMinusCenterEndComplex = euclidean.getNormalized( endComplex - centerEndComplex ) widdershinsBegin = getWiddershinsAverageByVector3( centerBeginMinusBeginComplex, centerEndMinusCenterBeginComplex ) widdershinsEnd = getWiddershinsAverageByVector3( centerEndMinusCenterBeginComplex, endMinusCenterEndComplex ) for point in path: weightEnd = point.x weightBegin = 1.0 - weightEnd polygonPoint = centerBegin + centerEndMinusBegin * point.x weightedWiddershins = widdershinsBegin * weightBegin + widdershinsEnd * weightEnd polygonPoint += weightedWiddershins * point.y * centerEndMinusCenterBeginComplexLength polygonPoint.z += point.z wedgePath.append( polygonPoint ) return wedgePath
def getIsInsetPointInsideLoops( inside, loops, pointBegin, pointCenter, pointEnd, radius ): "Determine if the inset point is inside the loops." centerMinusBegin = euclidean.getNormalized( pointCenter - pointBegin ) centerMinusBeginWiddershins = complex( - centerMinusBegin.imag, centerMinusBegin.real ) endMinusCenter = euclidean.getNormalized( pointEnd - pointCenter ) endMinusCenterWiddershins = complex( - endMinusCenter.imag, endMinusCenter.real ) widdershinsNormalized = euclidean.getNormalized( centerMinusBeginWiddershins + endMinusCenterWiddershins ) * radius return euclidean.getIsInFilledRegion( loops, pointCenter + widdershinsNormalized ) == inside
def getIsInsetPointInsideLoops( inside, loops, pointBegin, pointCenter, pointEnd, radius ): 'Determine if the inset point is inside the loops.' centerMinusBegin = euclidean.getNormalized( pointCenter - pointBegin ) centerMinusBeginWiddershins = complex( - centerMinusBegin.imag, centerMinusBegin.real ) endMinusCenter = euclidean.getNormalized( pointEnd - pointCenter ) endMinusCenterWiddershins = complex( - endMinusCenter.imag, endMinusCenter.real ) widdershinsNormalized = euclidean.getNormalized( centerMinusBeginWiddershins + endMinusCenterWiddershins ) * radius return euclidean.getIsInFilledRegion( loops, pointCenter + widdershinsNormalized ) == inside
def addSmoothedInfill(self): "Add smoothed infill." if len(self.infill) < 4: self.distanceFeedRate.addGcodeFromFeedRateThreadZ( self.feedRateMinute, self.infill, self.travelFeedRateMinute, self.oldLocation.z ) return self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.travelFeedRateMinute, self.infill[0], self.oldLocation.z ) self.distanceFeedRate.addLine("M101") lengthMinusOne = len(self.infill) - 1 lengthMinusTwo = lengthMinusOne - 1 wasOriginalPoint = True pointIndex = 0 while pointIndex < lengthMinusOne: nextPoint = self.infill[pointIndex + 1] afterNextIndex = pointIndex + 2 if afterNextIndex < lengthMinusTwo: point = self.infill[pointIndex] midpoint = 0.5 * (point + nextPoint) afterNextPoint = self.infill[afterNextIndex] afterNextNextPoint = self.infill[afterNextIndex + 1] afterNextMidpoint = 0.5 * (afterNextPoint + afterNextNextPoint) shortcutDistance = abs(afterNextMidpoint - midpoint) originalDistance = ( abs(midpoint - point) + abs(afterNextPoint - nextPoint) + abs(afterNextMidpoint - afterNextPoint) ) segment = euclidean.getNormalized(nextPoint - point) afterNextSegment = euclidean.getNormalized(afterNextNextPoint - afterNextPoint) sameDirection = self.getIsParallelToRotation(segment) and self.getIsParallelToRotation(afterNextSegment) if ( originalDistance - shortcutDistance < self.maximumShortening and shortcutDistance < self.maximumDistance and sameDirection ): if wasOriginalPoint: self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, midpoint, self.oldLocation.z ) feedrate = self.feedRateMinute if originalDistance != 0.0: feedrate *= shortcutDistance / originalDistance self.distanceFeedRate.addGcodeMovementZWithFeedRate(feedrate, afterNextMidpoint, self.oldLocation.z) wasOriginalPoint = False pointIndex += 1 else: self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, nextPoint, self.oldLocation.z ) wasOriginalPoint = True else: self.distanceFeedRate.addGcodeMovementZWithFeedRate(self.feedRateMinute, nextPoint, self.oldLocation.z) wasOriginalPoint = True pointIndex += 1 self.distanceFeedRate.addLine("M103")
def addSmoothedInfill(self): 'Add smoothed infill.' if len(self.infill) < 4: self.distanceFeedRate.addGcodeFromFeedRateThreadZ( self.feedRateMinute, self.infill, self.travelFeedRateMinute, self.oldLocation.z) return self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.travelFeedRateMinute, self.infill[0], self.oldLocation.z) self.distanceFeedRate.addLine('M101') lengthMinusOne = len(self.infill) - 1 lengthMinusTwo = lengthMinusOne - 1 wasOriginalPoint = True pointIndex = 0 while pointIndex < lengthMinusOne: nextPoint = self.infill[pointIndex + 1] afterNextIndex = pointIndex + 2 if afterNextIndex < lengthMinusTwo: point = self.infill[pointIndex] midpoint = 0.5 * (point + nextPoint) afterNextPoint = self.infill[afterNextIndex] afterNextNextPoint = self.infill[afterNextIndex + 1] afterNextMidpoint = 0.5 * (afterNextPoint + afterNextNextPoint) shortcutDistance = abs(afterNextMidpoint - midpoint) originalDistance = abs(midpoint - point) + abs( afterNextPoint - nextPoint) + abs(afterNextMidpoint - afterNextPoint) segment = euclidean.getNormalized(nextPoint - point) afterNextSegment = euclidean.getNormalized(afterNextNextPoint - afterNextPoint) sameDirection = self.getIsParallelToRotation( segment) and self.getIsParallelToRotation(afterNextSegment) if originalDistance - shortcutDistance < self.maximumShortening and shortcutDistance < self.maximumDistance and sameDirection: if wasOriginalPoint: self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, midpoint, self.oldLocation.z) feedrate = self.feedRateMinute if originalDistance != 0.0: feedrate *= shortcutDistance / originalDistance self.distanceFeedRate.addGcodeMovementZWithFeedRate( feedrate, afterNextMidpoint, self.oldLocation.z) wasOriginalPoint = False pointIndex += 1 else: self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, nextPoint, self.oldLocation.z) wasOriginalPoint = True else: self.distanceFeedRate.addGcodeMovementZWithFeedRate( self.feedRateMinute, nextPoint, self.oldLocation.z) wasOriginalPoint = True pointIndex += 1 self.distanceFeedRate.addLine('M103')
def getInsetPoint( loop, tinyRadius ): 'Get the inset vertex.' pointIndex = getWideAnglePointIndex(loop) point = loop[ pointIndex % len(loop) ] afterPoint = loop[(pointIndex + 1) % len(loop)] beforePoint = loop[ ( pointIndex - 1 ) % len(loop) ] afterSegmentNormalized = euclidean.getNormalized( afterPoint - point ) beforeSegmentNormalized = euclidean.getNormalized( beforePoint - point ) afterClockwise = complex( afterSegmentNormalized.imag, - afterSegmentNormalized.real ) beforeWiddershins = complex( - beforeSegmentNormalized.imag, beforeSegmentNormalized.real ) midpoint = afterClockwise + beforeWiddershins midpointNormalized = midpoint / abs( midpoint ) return point + midpointNormalized * tinyRadius
def getInsetPoint( loop, tinyRadius ): "Get the inset vertex." pointIndex = getWideAnglePointIndex( loop ) point = loop[ pointIndex % len( loop ) ] afterPoint = loop[ ( pointIndex + 1 ) % len( loop ) ] beforePoint = loop[ ( pointIndex - 1 ) % len( loop ) ] afterSegmentNormalized = euclidean.getNormalized( afterPoint - point ) beforeSegmentNormalized = euclidean.getNormalized( beforePoint - point ) afterClockwise = complex( afterSegmentNormalized.imag, - afterSegmentNormalized.real ) beforeWiddershins = complex( - beforeSegmentNormalized.imag, beforeSegmentNormalized.real ) midpoint = afterClockwise + beforeWiddershins midpointNormalized = midpoint / abs( midpoint ) return point + midpointNormalized * tinyRadius
def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: return [loop] if not evaluate.getEvaluatedBooleanDefault(True, prefix + 'activate', xmlElement): return [loop] overhangAngle = evaluate.getOverhangSupportAngle(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangAngle) overhangVerticalAngle = math.radians( evaluate.getEvaluatedFloatDefault(0.0, prefix + 'inclination', xmlElement)) if overhangVerticalAngle != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalAngle)) if overhangVerticalCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine overhangPlaneAngle = euclidean.getNormalized( complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, xmlElement) return [ euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop) ]
def getManipulatedPaths(close, loop, prefix, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: return [loop] overhangAngle = math.radians( xmlElement.getCascadeFloat(45.0, 'overhangangle')) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangAngle) overhangVerticalAngle = math.radians( evaluate.getEvaluatedFloatZero(prefix + 'verticalangle', xmlElement)) if overhangVerticalAngle != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalAngle)) if overhangVerticalCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine overhangPlaneAngle = euclidean.getNormalized( complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, xmlElement) return [ euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop) ]
def getCircleIntersectionAhead(self): "Get the first circle intersection on the circle node ahead." circleIntersections = self.circleNodeAhead.circleIntersections circleIntersectionAhead = None largestDot = -912345678.0 for circleIntersection in circleIntersections: if not circleIntersection.steppedOn: circleIntersectionRelativeToMidpoint = euclidean.getNormalized( circleIntersection.positionRelativeToBehind + self.aheadMinusBehind ) dot = euclidean.getDotProduct(self.demichord, circleIntersectionRelativeToMidpoint) if dot > largestDot: largestDot = dot circleIntersectionAhead = circleIntersection if circleIntersectionAhead == None: print("Warning, circleIntersectionAhead in getCircleIntersectionAhead in intercircle is None for:") print(self.circleNodeAhead.dividedPoint) print("circleIntersectionsAhead") for circleIntersection in circleIntersections: print(circleIntersection.circleNodeAhead.dividedPoint) print("circleIntersectionsBehind") for circleIntersection in self.circleNodeBehind.circleIntersections: print(circleIntersection.circleNodeAhead.dividedPoint) print("This may lead to a loop not being sliced.") print( "If this is a problem, you may as well send a bug report, even though I probably can not fix this particular problem." ) return circleIntersectionAhead
def getManipulatedPaths(close, elementNode, loop, prefix, sideLength): "Get path with overhangs removed or filled in." if len(loop) < 3: print( 'Warning, loop has less than three sides in getManipulatedPaths in overhang for:' ) print(elementNode) return [loop] derivation = OverhangDerivation(elementNode, prefix) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar( 0.5 * math.pi - derivation.overhangRadians) if derivation.overhangInclinationRadians != 0.0: overhangInclinationCosine = abs( math.cos(derivation.overhangInclinationRadians)) if overhangInclinationCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangInclinationCosine overhangPlaneAngle = euclidean.getNormalized( complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, elementNode) return [ euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop) ]
def getGeometryOutput(derivation, xmlElement): "Get vector3 vertexes from attribute dictionary." if derivation == None: derivation = SquareDerivation() derivation.setToXMLElement(xmlElement) topRight = complex(derivation.topDemiwidth, derivation.demiheight) topLeft = complex(-derivation.topDemiwidth, derivation.demiheight) bottomLeft = complex(-derivation.bottomDemiwidth, -derivation.demiheight) bottomRight = complex(derivation.bottomDemiwidth, -derivation.demiheight) if derivation.interiorAngle != 90.0: interiorPlaneAngle = euclidean.getWiddershinsUnitPolar(math.radians(derivation.interiorAngle - 90.0)) topRight = (topRight - bottomRight) * interiorPlaneAngle + bottomRight topLeft = (topLeft - bottomLeft) * interiorPlaneAngle + bottomLeft lineation.setClosedAttribute(derivation.revolutions, xmlElement) complexLoop = [topRight, topLeft, bottomLeft, bottomRight] originalLoop = complexLoop[:] for revolution in xrange(1, derivation.revolutions): complexLoop += originalLoop spiral = lineation.Spiral(derivation.spiral, 0.25) loop = [] loopCentroid = euclidean.getLoopCentroid(originalLoop) for point in complexLoop: unitPolar = euclidean.getNormalized(point - loopCentroid) loop.append(spiral.getSpiralPoint(unitPolar, Vector3(point.real, point.imag))) return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, 0.5 * math.pi), xmlElement)
def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: print( 'Warning, loop has less than three sides in getManipulatedPaths in overhang for:' ) print(xmlElement) return [loop] overhangRadians = setting.getOverhangRadians(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangRadians) overhangVerticalRadians = math.radians( evaluate.getEvaluatedFloat(0.0, prefix + 'inclination', xmlElement)) if overhangVerticalRadians != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalRadians)) if overhangVerticalCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine overhangPlaneAngle = euclidean.getNormalized( complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, xmlElement) return [ euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop) ]
def getCircleIntersectionAhead(self): 'Get the first circle intersection on the circle node ahead.' circleIntersections = self.circleNodeAhead.circleIntersections circleIntersectionAhead = None largestDot = -912345678.0 for circleIntersection in circleIntersections: if not circleIntersection.steppedOn: circleIntersectionRelativeToMidpoint = euclidean.getNormalized( circleIntersection.positionRelativeToBehind + self.aheadMinusBehind) dot = euclidean.getDotProduct( self.demichord, circleIntersectionRelativeToMidpoint) if dot > largestDot: largestDot = dot circleIntersectionAhead = circleIntersection if circleIntersectionAhead == None: print( 'Warning, circleIntersectionAhead in getCircleIntersectionAhead in intercircle is None for:' ) print(self.circleNodeAhead.dividedPoint) print('circleIntersectionsAhead') for circleIntersection in circleIntersections: print(circleIntersection.circleNodeAhead.dividedPoint) print('circleIntersectionsBehind') for circleIntersection in self.circleNodeBehind.circleIntersections: print(circleIntersection.circleNodeAhead.dividedPoint) print('This may lead to a loop not being sliced.') print( 'If this is a problem, you may as well send a bug report, even though I probably can not fix this particular problem.' ) return circleIntersectionAhead
def getGeometryOutput(derivation, elementNode): "Get vector3 vertexes from attribute dictionary." if derivation is None: derivation = SquareDerivation(elementNode) topRight = complex(derivation.topDemiwidth, derivation.demiheight) topLeft = complex(-derivation.topDemiwidth, derivation.demiheight) bottomLeft = complex(-derivation.bottomDemiwidth, -derivation.demiheight) bottomRight = complex(derivation.bottomDemiwidth, -derivation.demiheight) if derivation.interiorAngle != 90.0: interiorPlaneAngle = euclidean.getWiddershinsUnitPolar( math.radians(derivation.interiorAngle - 90.0)) topRight = (topRight - bottomRight) * interiorPlaneAngle + bottomRight topLeft = (topLeft - bottomLeft) * interiorPlaneAngle + bottomLeft lineation.setClosedAttribute(elementNode, derivation.revolutions) complexLoop = [topRight, topLeft, bottomLeft, bottomRight] originalLoop = complexLoop[:] for revolution in xrange(1, derivation.revolutions): complexLoop += originalLoop spiral = lineation.Spiral(derivation.spiral, 0.25) loop = [] loopCentroid = euclidean.getLoopCentroid(originalLoop) for point in complexLoop: unitPolar = euclidean.getNormalized(point - loopCentroid) loop.append( spiral.getSpiralPoint(unitPolar, Vector3(point.real, point.imag))) return lineation.getGeometryOutputByLoop( elementNode, lineation.SideLoop(loop, 0.5 * math.pi))
def getOverhangDirection(belowOutsetLoops, segmentBegin, segmentEnd): 'Add to span direction from the endpoint segments which overhang the layer below.' segment = segmentEnd - segmentBegin normalizedSegment = euclidean.getNormalized( complex(segment.real, segment.imag)) segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) segmentBegin = segmentYMirror * segmentBegin segmentEnd = segmentYMirror * segmentEnd solidXIntersectionList = [] y = segmentBegin.imag solidXIntersectionList.append( euclidean.XIntersectionIndex(-1.0, segmentBegin.real)) solidXIntersectionList.append( euclidean.XIntersectionIndex(-1.0, segmentEnd.real)) for belowLoopIndex in xrange(len(belowOutsetLoops)): belowLoop = belowOutsetLoops[belowLoopIndex] rotatedOutset = euclidean.getRotatedComplexes(segmentYMirror, belowLoop) euclidean.addXIntersectionIndexesFromLoopY(rotatedOutset, belowLoopIndex, solidXIntersectionList, y) overhangingSegments = euclidean.getSegmentsFromXIntersectionIndexes( solidXIntersectionList, y) overhangDirection = complex() for overhangingSegment in overhangingSegments: overhangDirection += getDoubledRoundZ(overhangingSegment, normalizedSegment) return overhangDirection
def getToothProfileCylinder(gearDerivation, pitchRadius, teeth): 'Get profile for one tooth of a cylindrical gear.' toothProfile = getToothProfileHalfCylinder(gearDerivation, pitchRadius, teeth) profileFirst = toothProfile[0] profileSecond = toothProfile[1] firstMinusSecond = profileFirst - profileSecond remainingDedendum = abs( profileFirst) - pitchRadius + gearDerivation.dedendum firstMinusSecond *= remainingDedendum / abs(firstMinusSecond) extensionPoint = profileFirst + firstMinusSecond if gearDerivation.bevel <= 0.0: toothProfile.insert(0, extensionPoint) return getMirrorPath(toothProfile) unitPolar = euclidean.getWiddershinsUnitPolar(-2.0 / float(teeth) * math.pi) mirrorExtensionPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar mirrorMinusExtension = euclidean.getNormalized(mirrorExtensionPoint - extensionPoint) if remainingDedendum <= gearDerivation.bevel: toothProfile.insert( 0, complex(extensionPoint.real, extensionPoint.imag) + remainingDedendum * mirrorMinusExtension) return getMirrorPath(toothProfile) firstMinusSecond *= (remainingDedendum - gearDerivation.bevel) / abs(firstMinusSecond) toothProfile.insert(0, profileFirst + firstMinusSecond) toothProfile.insert( 0, complex(extensionPoint.real, extensionPoint.imag) + gearDerivation.bevel * mirrorMinusExtension) return getMirrorPath(toothProfile)
def getBoundaryIndexes(self, begin, boundaries, end, points): 'Get boundary indexes and set the points in the way of the original line segment.' boundaryIndexes = [] points.append(begin) switchX = [] segment = euclidean.getNormalized(end - begin) segmentYMirror = complex(segment.real, -segment.imag) beginRotated = segmentYMirror * begin endRotated = segmentYMirror * end y = beginRotated.imag for boundaryIndex in xrange(len(boundaries)): boundary = boundaries[boundaryIndex] boundaryRotated = euclidean.getRotatedComplexes( segmentYMirror, boundary) euclidean.addXIntersectionIndexesFromLoopY(boundaryRotated, boundaryIndex, switchX, y) switchX.sort() maximumX = max(beginRotated.real, endRotated.real) minimumX = min(beginRotated.real, endRotated.real) for xIntersection in switchX: if xIntersection.x > minimumX and xIntersection.x < maximumX: point = segment * complex(xIntersection.x, y) points.append(point) boundaryIndexes.append(xIntersection.index) points.append(end) return boundaryIndexes
def getGeometryOutput(xmlElement): "Get vector3 vertexes from attribute dictionary." inradius = lineation.getComplexByPrefixes(['demisize', 'inradius'], complex(1.0, 1.0), xmlElement) inradius = lineation.getComplexByMultiplierPrefix(2.0, 'size', inradius, xmlElement) demiwidth = lineation.getFloatByPrefixBeginEnd('demiwidth', 'width', inradius.real, xmlElement) demiheight = lineation.getFloatByPrefixBeginEnd('demiheight', 'height', inradius.imag, xmlElement) bottomDemiwidth = lineation.getFloatByPrefixBeginEnd('bottomdemiwidth', 'bottomwidth', demiwidth, xmlElement) topDemiwidth = lineation.getFloatByPrefixBeginEnd('topdemiwidth', 'topwidth', demiwidth, xmlElement) interiorAngle = evaluate.getEvaluatedFloatDefault(90.0, 'interiorangle', xmlElement) topRight = complex(topDemiwidth, demiheight) topLeft = complex(-topDemiwidth, demiheight) bottomLeft = complex(-bottomDemiwidth, -demiheight) bottomRight = complex(bottomDemiwidth, -demiheight) if interiorAngle != 90.0: interiorPlaneAngle = euclidean.getWiddershinsUnitPolar(math.radians(interiorAngle - 90.0)) topRight = (topRight - bottomRight) * interiorPlaneAngle + bottomRight topLeft = (topLeft - bottomLeft) * interiorPlaneAngle + bottomLeft revolutions = evaluate.getEvaluatedIntOne('revolutions', xmlElement) lineation.setClosedAttribute(revolutions, xmlElement) complexLoop = [topRight, topLeft, bottomLeft, bottomRight] originalLoop = complexLoop[:] for revolution in xrange(1, revolutions): complexLoop += originalLoop spiral = lineation.Spiral(0.25, xmlElement) loop = [] loopCentroid = euclidean.getLoopCentroid(originalLoop) for point in complexLoop: unitPolar = euclidean.getNormalized(point - loopCentroid) loop.append(spiral.getSpiralPoint(unitPolar, Vector3(point.real, point.imag))) return lineation.getGeometryOutputByLoop(lineation.SideLoop(loop, 0.5 * math.pi), xmlElement)
def getInsetFromClockwiseTriple(aheadAbsolute, behindAbsolute, center, radius): "Get loop inset from clockwise triple, out from widdershins loop." originalCenterMinusBehind = euclidean.getNormalized(center - behindAbsolute) reverseRoundZAngle = complex(originalCenterMinusBehind.real, -originalCenterMinusBehind.imag) rotatedAheadAbsolute = aheadAbsolute * reverseRoundZAngle rotatedBehindAbsolute = behindAbsolute * reverseRoundZAngle rotatedCenter = center * reverseRoundZAngle aheadIntersection = getIntersectionAtInset(rotatedAheadAbsolute, rotatedCenter, radius) behindIntersection = getIntersectionAtInset(rotatedCenter, rotatedBehindAbsolute, radius) centerMinusAhead = rotatedCenter - rotatedAheadAbsolute if abs(centerMinusAhead.imag) < abs(0.00001 * centerMinusAhead.real): between = 0.5 * (aheadIntersection + behindIntersection) return originalCenterMinusBehind * between yMinusAhead = behindIntersection.imag - aheadIntersection.imag x = aheadIntersection.real + yMinusAhead * centerMinusAhead.real / centerMinusAhead.imag insetFromClockwiseTriple = originalCenterMinusBehind * complex( x, behindIntersection.imag) insetMinusOriginal = insetFromClockwiseTriple - center distance = abs(insetMinusOriginal) maximumDistance = 2.0 * radius if distance < maximumDistance: return insetFromClockwiseTriple return center + maximumDistance / distance * insetMinusOriginal
def getWideAnglePointIndex( loop ): "Get a point index which has a wide enough angle, most point indexes have a wide enough angle, this is just to make sure." dotProductMinimum = 9999999.9 widestPointIndex = 0 for pointIndex in xrange( len( loop ) ): point = loop[ pointIndex % len( loop ) ] afterPoint = loop[ ( pointIndex + 1 ) % len( loop ) ] beforePoint = loop[ ( pointIndex - 1 ) % len( loop ) ] afterSegmentNormalized = euclidean.getNormalized( afterPoint - point ) beforeSegmentNormalized = euclidean.getNormalized( beforePoint - point ) dotProduct = euclidean.getDotProduct( afterSegmentNormalized, beforeSegmentNormalized ) if dotProduct < .99: return pointIndex if dotProduct < dotProductMinimum: dotProductMinimum = dotProduct widestPointIndex = pointIndex return widestPointIndex
def getWideAnglePointIndex(loop): 'Get a point index which has a wide enough angle, most point indexes have a wide enough angle, this is just to make sure.' dotProductMinimum = 9999999.9 widestPointIndex = 0 for pointIndex in xrange(len(loop)): point = loop[ pointIndex % len(loop) ] afterPoint = loop[(pointIndex + 1) % len(loop)] beforePoint = loop[ ( pointIndex - 1 ) % len(loop) ] afterSegmentNormalized = euclidean.getNormalized( afterPoint - point ) beforeSegmentNormalized = euclidean.getNormalized( beforePoint - point ) dotProduct = euclidean.getDotProduct( afterSegmentNormalized, beforeSegmentNormalized ) if dotProduct < .99: return pointIndex if dotProduct < dotProductMinimum: dotProductMinimum = dotProduct widestPointIndex = pointIndex return widestPointIndex
def getPathsBetween(self, begin, end): "Insert paths between the perimeter and the fill." aroundBetweenPath = [] points = [begin] lineX = [] switchX = [] segment = euclidean.getNormalized(end - begin) segmentYMirror = complex(segment.real, -segment.imag) beginRotated = segmentYMirror * begin endRotated = segmentYMirror * end y = beginRotated.imag boundaries = self.getBoundaries() for boundaryIndex in xrange(len(boundaries)): boundary = boundaries[boundaryIndex] boundaryRotated = euclidean.getPointsRoundZAxis( segmentYMirror, boundary) euclidean.addXIntersectionIndexesFromLoopY(boundaryRotated, boundaryIndex, switchX, y) switchX.sort() maximumX = max(beginRotated.real, endRotated.real) minimumX = min(beginRotated.real, endRotated.real) for xIntersection in switchX: if xIntersection.x > minimumX and xIntersection.x < maximumX: point = segment * complex(xIntersection.x, y) points.append(point) lineX.append(xIntersection) points.append(end) lineXIndex = 0 # pathBetweenAdded = False while lineXIndex < len(lineX) - 1: lineXFirst = lineX[lineXIndex] lineXSecond = lineX[lineXIndex + 1] loopFirst = boundaries[lineXFirst.index] if lineXSecond.index == lineXFirst.index: pathBetween = self.getPathBetween( loopFirst, points[lineXIndex:lineXIndex + 4]) pathBetween = self.getSimplifiedAroundPath( points[lineXIndex], points[lineXIndex + 3], loopFirst, pathBetween) aroundBetweenPath += pathBetween lineXIndex += 2 else: lineXIndex += 1 # isLeavingPerimeter = False # if lineXSecond.index != lineXFirst.index: # isLeavingPerimeter = True # pathBetween = self.getPathBetween( points[ lineXIndex + 1 ], points[ lineXIndex + 2 ], isLeavingPerimeter, loopFirst ) # if isLeavingPerimeter: # pathBetweenAdded = True # else: # pathBetween = self.getSimplifiedAroundPath( points[ lineXIndex ], points[ lineXIndex + 3 ], loopFirst, pathBetween ) # pathBetweenAdded = True # aroundBetweenPath += pathBetween # lineXIndex += 2 return aroundBetweenPath
def getPathsBetween(self, begin, end): "Insert paths between the perimeter and the fill." aroundBetweenPath = [] points = [begin] lineX = [] switchX = [] segment = euclidean.getNormalized(end - begin) segmentYMirror = complex(segment.real, -segment.imag) beginRotated = segmentYMirror * begin endRotated = segmentYMirror * end y = beginRotated.imag boundaries = self.getBoundaries() for boundaryIndex in xrange(len(boundaries)): boundary = boundaries[boundaryIndex] boundaryRotated = euclidean.getRotatedComplexes(segmentYMirror, boundary) euclidean.addXIntersectionIndexesFromLoopY(boundaryRotated, boundaryIndex, switchX, y) switchX.sort() maximumX = max(beginRotated.real, endRotated.real) minimumX = min(beginRotated.real, endRotated.real) for xIntersection in switchX: if xIntersection.x > minimumX and xIntersection.x < maximumX: point = segment * complex(xIntersection.x, y) points.append(point) lineX.append(xIntersection) points.append(end) lineXIndex = 0 # pathBetweenAdded = False while lineXIndex < len(lineX) - 1: lineXFirst = lineX[lineXIndex] lineXSecond = lineX[lineXIndex + 1] loopFirst = boundaries[lineXFirst.index] if lineXSecond.index == lineXFirst.index: pathBetween = self.getPathBetween(loopFirst, points[lineXIndex : lineXIndex + 4]) pathBetween = self.getSimplifiedAroundPath( points[lineXIndex], points[lineXIndex + 3], loopFirst, pathBetween ) aroundBetweenPath += pathBetween lineXIndex += 2 else: lineXIndex += 1 # isLeavingPerimeter = False # if lineXSecond.index != lineXFirst.index: # isLeavingPerimeter = True # pathBetween = self.getPathBetween( points[ lineXIndex + 1 ], points[ lineXIndex + 2 ], isLeavingPerimeter, loopFirst ) # if isLeavingPerimeter: # pathBetweenAdded = True # else: # pathBetween = self.getSimplifiedAroundPath( points[ lineXIndex ], points[ lineXIndex + 3 ], loopFirst, pathBetween ) # pathBetweenAdded = True # aroundBetweenPath += pathBetween # lineXIndex += 2 return aroundBetweenPath
def isLoopIntersectingLoop( anotherLoop, loop ): 'Determine if the a loop is intersecting another loop.' for pointIndex in xrange(len(loop)): pointFirst = loop[pointIndex] pointSecond = loop[(pointIndex + 1) % len(loop)] segment = pointFirst - pointSecond normalizedSegment = euclidean.getNormalized(segment) segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) segmentFirstPoint = segmentYMirror * pointFirst segmentSecondPoint = segmentYMirror * pointSecond if euclidean.isLoopIntersectingInsideXSegment( anotherLoop, segmentFirstPoint.real, segmentSecondPoint.real, segmentYMirror, segmentFirstPoint.imag ): return True return False
def getPathBetween( self, loop, points ): "Add a path between the perimeter and the fill." paths = getPathsByIntersectedLoop( points[ 1 ], points[ 2 ], loop ) shortestPath = paths[ int( euclidean.getPathLength( paths[ 1 ] ) < euclidean.getPathLength( paths[ 0 ] ) ) ] if not euclidean.isWiddershins( shortestPath ): shortestPath.reverse() loopAround = intercircle.getLargestInsetLoopFromLoopNoMatterWhat( shortestPath, - self.combInset ) endMinusBegin = points[ 3 ] - points[ 0 ] endMinusBegin = 1.3 * self.combInset * euclidean.getNormalized( endMinusBegin ) aroundPaths = getPathsByIntersectedLoop( points[ 0 ] - endMinusBegin, points[ 3 ] + endMinusBegin, loopAround ) insidePath = aroundPaths[ int( getInsideness( aroundPaths[ 1 ], loop ) > getInsideness( aroundPaths[ 0 ], loop ) ) ] pathBetween = [] for point in insidePath: if euclidean.isPointInsideLoop( loop, point ): pathBetween.append(point ) return pathBetween
def getCircleIntersectionAhead( self ): "Get the first circle intersection on the circle node ahead." circleIntersections = self.circleNodeAhead.circleIntersections circleIntersectionAhead = None largestDot = - 999999999.0 for circleIntersection in circleIntersections: if not circleIntersection.steppedOn: circleIntersectionRelativeToMidpoint = euclidean.getNormalized( circleIntersection.positionRelativeToBehind + self.aheadMinusBehind ) dot = euclidean.getDotProduct( self.demichord, circleIntersectionRelativeToMidpoint ) if dot > largestDot: largestDot = dot circleIntersectionAhead = circleIntersection if circleIntersectionAhead == None: print( 'this should never happen, circleIntersectionAhead in intercircle is None' ) print( self.circleNodeAhead.circle ) for circleIntersection in circleIntersections: print( circleIntersection.circleNodeAhead.circle ) return circleIntersectionAhead
def getManipulatedPaths(close, loop, prefix, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: return [loop] overhangAngle = math.radians(xmlElement.getCascadeFloat(45.0, "overhangangle")) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangAngle) overhangVerticalAngle = math.radians(evaluate.getEvaluatedFloatZero(prefix + "verticalangle", xmlElement)) if overhangVerticalAngle != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalAngle)) if overhangVerticalCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine overhangPlaneAngle = euclidean.getNormalized(complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, xmlElement) return [euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop)]
def getManipulatedPaths(close, elementNode, loop, prefix, sideLength): "Get path with overhangs removed or filled in." if len(loop) < 3: print('Warning, loop has less than three sides in getManipulatedPaths in overhang for:') print(elementNode) return [loop] derivation = OverhangDerivation(elementNode, prefix) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - derivation.overhangRadians) if derivation.overhangInclinationRadians != 0.0: overhangInclinationCosine = abs(math.cos(derivation.overhangInclinationRadians)) if overhangInclinationCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangInclinationCosine overhangPlaneAngle = euclidean.getNormalized(complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, elementNode) return [euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop)]
def getOverhangDirection( belowOutsetLoops, segmentBegin, segmentEnd ): 'Add to span direction from the endpoint segments which overhang the layer below.' segment = segmentEnd - segmentBegin normalizedSegment = euclidean.getNormalized( complex( segment.real, segment.imag ) ) segmentYMirror = complex(normalizedSegment.real, -normalizedSegment.imag) segmentBegin = segmentYMirror * segmentBegin segmentEnd = segmentYMirror * segmentEnd solidXIntersectionList = [] y = segmentBegin.imag solidXIntersectionList.append( euclidean.XIntersectionIndex( - 1.0, segmentBegin.real ) ) solidXIntersectionList.append( euclidean.XIntersectionIndex( - 1.0, segmentEnd.real ) ) for belowLoopIndex in xrange( len( belowOutsetLoops ) ): belowLoop = belowOutsetLoops[ belowLoopIndex ] rotatedOutset = euclidean.getRotatedComplexes( segmentYMirror, belowLoop ) euclidean.addXIntersectionIndexesFromLoopY( rotatedOutset, belowLoopIndex, solidXIntersectionList, y ) overhangingSegments = euclidean.getSegmentsFromXIntersectionIndexes( solidXIntersectionList, y ) overhangDirection = complex() for overhangingSegment in overhangingSegments: overhangDirection += getDoubledRoundZ( overhangingSegment, normalizedSegment ) return overhangDirection
def getGeometryOutput(xmlElement): "Get vector3 vertexes from attribute dictionary." inradius = lineation.getComplexByPrefixes(['demisize', 'inradius'], complex(1.0, 1.0), xmlElement) inradius = lineation.getComplexByMultiplierPrefix(2.0, 'size', inradius, xmlElement) demiwidth = lineation.getFloatByPrefixBeginEnd('demiwidth', 'width', inradius.real, xmlElement) demiheight = lineation.getFloatByPrefixBeginEnd('demiheight', 'height', inradius.imag, xmlElement) bottomDemiwidth = lineation.getFloatByPrefixBeginEnd( 'bottomdemiwidth', 'bottomwidth', demiwidth, xmlElement) topDemiwidth = lineation.getFloatByPrefixBeginEnd('topdemiwidth', 'topwidth', demiwidth, xmlElement) interiorAngle = evaluate.getEvaluatedFloatDefault(90.0, 'interiorangle', xmlElement) topRight = complex(topDemiwidth, demiheight) topLeft = complex(-topDemiwidth, demiheight) bottomLeft = complex(-bottomDemiwidth, -demiheight) bottomRight = complex(bottomDemiwidth, -demiheight) if interiorAngle != 90.0: interiorPlaneAngle = euclidean.getWiddershinsUnitPolar( math.radians(interiorAngle - 90.0)) topRight = (topRight - bottomRight) * interiorPlaneAngle + bottomRight topLeft = (topLeft - bottomLeft) * interiorPlaneAngle + bottomLeft revolutions = evaluate.getEvaluatedIntOne('revolutions', xmlElement) lineation.setClosedAttribute(revolutions, xmlElement) complexLoop = [topRight, topLeft, bottomLeft, bottomRight] originalLoop = complexLoop[:] for revolution in xrange(1, revolutions): complexLoop += originalLoop spiral = lineation.Spiral(0.25, xmlElement) loop = [] loopCentroid = euclidean.getLoopCentroid(originalLoop) for point in complexLoop: unitPolar = euclidean.getNormalized(point - loopCentroid) loop.append( spiral.getSpiralPoint(unitPolar, Vector3(point.real, point.imag))) return lineation.getGeometryOutputByLoop( lineation.SideLoop(loop, 0.5 * math.pi), xmlElement)
def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): "Get path with overhangs removed or filled in." if len(loop) < 3: return [loop] if not evaluate.getEvaluatedBooleanDefault( True, prefix + 'activate', xmlElement ): return [loop] overhangAngle = evaluate.getOverhangSupportAngle(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar( 0.5 * math.pi - overhangAngle ) overhangVerticalAngle = math.radians( evaluate.getEvaluatedFloatDefault(0.0, prefix + 'inclination', xmlElement ) ) if overhangVerticalAngle != 0.0: overhangVerticalCosine = abs( math.cos( overhangVerticalAngle ) ) if overhangVerticalCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine overhangPlaneAngle = euclidean.getNormalized( complex( overhangPlaneAngle.real, imaginaryTimesCosine ) ) alongAway = AlongAway( loop, overhangPlaneAngle ) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath( alongAway, close ) else: alterClockwiseSupportedPath( alongAway, xmlElement ) return [ euclidean.getLoopWithoutCloseSequentialPoints( close, alongAway.loop ) ]
def getManipulatedPaths(close, loop, prefix, sideLength, xmlElement): """Get path with overhangs removed or filled in.""" if len(loop) < 3: print('Warning, loop has less than three sides in getManipulatedPaths in overhang for:') print(xmlElement) return [loop] overhangRadians = setting.getOverhangRadians(xmlElement) overhangPlaneAngle = euclidean.getWiddershinsUnitPolar(0.5 * math.pi - overhangRadians) overhangVerticalRadians = math.radians(evaluate.getEvaluatedFloat(0.0, prefix + 'inclination', xmlElement)) if overhangVerticalRadians != 0.0: overhangVerticalCosine = abs(math.cos(overhangVerticalRadians)) if overhangVerticalCosine == 0.0: return [loop] imaginaryTimesCosine = overhangPlaneAngle.imag * overhangVerticalCosine overhangPlaneAngle = euclidean.getNormalized(complex(overhangPlaneAngle.real, imaginaryTimesCosine)) alongAway = AlongAway(loop, overhangPlaneAngle) if euclidean.getIsWiddershinsByVector3(loop): alterWiddershinsSupportedPath(alongAway, close) else: alterClockwiseSupportedPath(alongAway, xmlElement) return [euclidean.getLoopWithoutCloseSequentialPoints(close, alongAway.loop)]
def getToothProfileCylinder(gearDerivation, pitchRadius, teeth): 'Get profile for one tooth of a cylindrical gear.' toothProfile = getToothProfileHalfCylinder(gearDerivation, pitchRadius, teeth) profileFirst = toothProfile[0] profileSecond = toothProfile[1] firstMinusSecond = profileFirst - profileSecond remainingDedendum = abs(profileFirst) - pitchRadius + gearDerivation.dedendum firstMinusSecond *= remainingDedendum / abs(firstMinusSecond) extensionPoint = profileFirst + firstMinusSecond if gearDerivation.bevel <= 0.0: toothProfile.insert(0, extensionPoint) return getMirrorPath(toothProfile) unitPolar = euclidean.getWiddershinsUnitPolar(-2.0 / float(teeth) * math.pi) mirrorExtensionPoint = complex(-extensionPoint.real, extensionPoint.imag) * unitPolar mirrorMinusExtension = euclidean.getNormalized(mirrorExtensionPoint - extensionPoint) if remainingDedendum <= gearDerivation.bevel: toothProfile.insert(0, complex(extensionPoint.real, extensionPoint.imag) + remainingDedendum * mirrorMinusExtension) return getMirrorPath(toothProfile) firstMinusSecond *= (remainingDedendum - gearDerivation.bevel) / abs(firstMinusSecond) toothProfile.insert(0, profileFirst + firstMinusSecond) toothProfile.insert(0, complex(extensionPoint.real, extensionPoint.imag) + gearDerivation.bevel * mirrorMinusExtension) return getMirrorPath(toothProfile)
def getInsetFromClockwiseTriple( aheadAbsolute, behindAbsolute, center, radius ): "Get loop inset from clockwise triple, out from widdershins loop." originalCenterMinusBehind = euclidean.getNormalized( center - behindAbsolute ) reverseRoundZAngle = complex( originalCenterMinusBehind.real, - originalCenterMinusBehind.imag ) rotatedAheadAbsolute = aheadAbsolute * reverseRoundZAngle rotatedBehindAbsolute = behindAbsolute * reverseRoundZAngle rotatedCenter = center * reverseRoundZAngle aheadIntersection = getIntersectionAtInset( rotatedAheadAbsolute, rotatedCenter, radius ) behindIntersection = getIntersectionAtInset( rotatedCenter, rotatedBehindAbsolute, radius ) centerMinusAhead = rotatedCenter - rotatedAheadAbsolute if abs( centerMinusAhead.imag ) < abs( 0.00001 * centerMinusAhead.real ): between = 0.5 * ( aheadIntersection + behindIntersection ) return originalCenterMinusBehind * between yMinusAhead = behindIntersection.imag - aheadIntersection.imag x = aheadIntersection.real + yMinusAhead * centerMinusAhead.real / centerMinusAhead.imag insetFromClockwiseTriple = originalCenterMinusBehind * complex( x, behindIntersection.imag ) insetMinusOriginal = insetFromClockwiseTriple - center distance = abs( insetMinusOriginal ) maximumDistance = 2.0 * radius if distance < maximumDistance: return insetFromClockwiseTriple return center + maximumDistance / distance * insetMinusOriginal
def getBoundaryIndexes(self, begin, boundaries, end, points): "Get boundary indexes and set the points in the way of the original line segment." boundaryIndexes = [] points.append(begin) switchX = [] segment = euclidean.getNormalized(end - begin) segmentYMirror = complex(segment.real, -segment.imag) beginRotated = segmentYMirror * begin endRotated = segmentYMirror * end y = beginRotated.imag for boundaryIndex in xrange(len(boundaries)): boundary = boundaries[boundaryIndex] boundaryRotated = euclidean.getRotatedComplexes(segmentYMirror, boundary) euclidean.addXIntersectionIndexesFromLoopY(boundaryRotated, boundaryIndex, switchX, y) switchX.sort() maximumX = max(beginRotated.real, endRotated.real) minimumX = min(beginRotated.real, endRotated.real) for xIntersection in switchX: if xIntersection.x > minimumX and xIntersection.x < maximumX: point = segment * complex(xIntersection.x, y) points.append(point) boundaryIndexes.append(xIntersection.index) points.append(end) return boundaryIndexes
def getPathBetween(self, loop, points): "Add a path between the perimeter and the fill." paths = getPathsByIntersectedLoop(points[1], points[2], loop) shortestPath = paths[int( euclidean.getPathLength(paths[1]) < euclidean.getPathLength( paths[0]))] if not euclidean.isWiddershins(shortestPath): shortestPath.reverse() loopAround = intercircle.getLargestInsetLoopFromLoopNoMatterWhat( shortestPath, -self.combInset) endMinusBegin = points[3] - points[0] endMinusBegin = 1.3 * self.combInset * euclidean.getNormalized( endMinusBegin) aroundPaths = getPathsByIntersectedLoop(points[0] - endMinusBegin, points[3] + endMinusBegin, loopAround) insidePath = aroundPaths[int( getInsideness(aroundPaths[1], loop) > getInsideness( aroundPaths[0], loop))] pathBetween = [] for point in insidePath: if euclidean.isPointInsideLoop(loop, point): pathBetween.append(point) return pathBetween
def getIsPointSupportedBySegment(self, endIndex): "Determine if the point on the widdershins loop is supported." endComplex = self.loop[(endIndex % len(self.loop))].dropAxis() endMinusPointComplex = euclidean.getNormalized(endComplex - self.point.dropAxis()) return endMinusPointComplex.imag < self.ySupport
def getIsPointSupportedBySegment( self, endIndex ): "Determine if the point on the widdershins loop is supported." endComplex = self.loop[ ( endIndex % len( self.loop ) ) ].dropAxis() endMinusPointComplex = euclidean.getNormalized( endComplex - self.point.dropAxis() ) return endMinusPointComplex.imag < self.ySupport