def getCrossLimitedStretch(self, crossLimitedStretch, crossLineIterator, locationComplex): "Get cross limited relative stretch for a location." try: line = crossLineIterator.getNext() except StopIteration: return crossLimitedStretch splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) pointComplex = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis(2) pointMinusLocation = locationComplex - pointComplex pointMinusLocationLength = abs(pointMinusLocation) if pointMinusLocationLength <= self.crossLimitDistanceFraction: return crossLimitedStretch parallelNormal = pointMinusLocation / pointMinusLocationLength parallelStretch = euclidean.getDotProduct( parallelNormal, crossLimitedStretch) * parallelNormal if pointMinusLocationLength > self.crossLimitDistance: return parallelStretch crossNormal = complex(parallelNormal.imag, -parallelNormal.real) crossStretch = euclidean.getDotProduct( crossNormal, crossLimitedStretch) * crossNormal crossPortion = (self.crossLimitDistance - pointMinusLocationLength ) / self.crossLimitDistanceRemainder return parallelStretch + crossStretch * crossPortion
def getExtruderOffReversalPoint( self, afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location ): "If the extruder is off and the path is reversing, add intermediate slow points." if self.repository.reversalSlowdownDistanceOverEdgeWidth.value < 0.1: return None if self.extruderActive: return None reversalBufferSlowdownDistance = self.reversalSlowdownDistance * 2.0 afterSegmentComplexLength = abs( afterSegmentComplex ) if afterSegmentComplexLength < reversalBufferSlowdownDistance: return None beforeSegmentComplexLength = abs( beforeSegmentComplex ) if beforeSegmentComplexLength < reversalBufferSlowdownDistance: return None afterSegmentComplexNormalized = afterSegmentComplex / afterSegmentComplexLength beforeSegmentComplexNormalized = beforeSegmentComplex / beforeSegmentComplexLength if euclidean.getDotProduct( afterSegmentComplexNormalized, beforeSegmentComplexNormalized ) < 0.95: return None slowdownFeedRate = self.feedRateMinute * 0.5 self.shouldAddLine = False beforePoint = euclidean.getPointPlusSegmentWithLength( self.reversalSlowdownDistance * abs( beforeSegment ) / beforeSegmentComplexLength, location, beforeSegment ) self.addLinearMovePoint( self.feedRateMinute, beforePoint ) self.addLinearMovePoint( slowdownFeedRate, location ) afterPoint = euclidean.getPointPlusSegmentWithLength( self.reversalSlowdownDistance * abs( afterSegment ) / afterSegmentComplexLength, location, afterSegment ) self.addLinearMovePoint( slowdownFeedRate, afterPoint ) return afterPoint
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 getExtruderOffReversalPoint(self, afterSegment, afterSegmentComplex, beforeSegment, beforeSegmentComplex, location): "If the extruder is off and the path is reversing, add intermediate slow points." if self.filletRepository.reversalSlowdownDistanceOverPerimeterWidth.value < 0.1: return None if self.extruderActive: return None reversalBufferSlowdownDistance = self.reversalSlowdownDistance * 2.0 afterSegmentComplexLength = abs(afterSegmentComplex) if afterSegmentComplexLength < reversalBufferSlowdownDistance: return None beforeSegmentComplexLength = abs(beforeSegmentComplex) if beforeSegmentComplexLength < reversalBufferSlowdownDistance: return None afterSegmentComplexNormalized = afterSegmentComplex / afterSegmentComplexLength beforeSegmentComplexNormalized = beforeSegmentComplex / beforeSegmentComplexLength if euclidean.getDotProduct(afterSegmentComplexNormalized, beforeSegmentComplexNormalized) < 0.95: return None slowdownFeedRate = self.feedRateMinute * 0.5 self.shouldAddLine = False beforePoint = euclidean.getPointPlusSegmentWithLength( self.reversalSlowdownDistance * abs(beforeSegment) / beforeSegmentComplexLength, location, beforeSegment) self.addLinearMovePoint(self.feedRateMinute, beforePoint) self.addLinearMovePoint(slowdownFeedRate, location) afterPoint = euclidean.getPointPlusSegmentWithLength( self.reversalSlowdownDistance * abs(afterSegment) / afterSegmentComplexLength, location, afterSegment) self.addLinearMovePoint(slowdownFeedRate, afterPoint) return afterPoint
def addInsetPointFromClockwiseTriple(begin, center, end, loop, radius): "Get inset point with possible intersection from clockwise triple, out from widdershins loop." centerMinusBegin = center - begin centerMinusBeginLength = abs(centerMinusBegin) centerMinusBeginClockwise = None if centerMinusBeginLength > 0.0: centerMinusBeginClockwise = complex( centerMinusBegin.imag, -centerMinusBegin.real) / centerMinusBeginLength endMinusCenter = end - center endMinusCenterLength = abs(endMinusCenter) endMinusCenterClockwise = None if endMinusCenterLength > 0.0: endMinusCenterClockwise = complex( endMinusCenter.imag, -endMinusCenter.real) / endMinusCenterLength if centerMinusBeginClockwise == None and endMinusCenterClockwise == None: return None if centerMinusBeginClockwise == None: loop.append(center + endMinusCenterClockwise * radius) if endMinusCenterClockwise == None: loop.append(center + centerMinusBeginClockwise * radius) centerClockwise = 0.5 * (centerMinusBeginClockwise + endMinusCenterClockwise) dotProduct = euclidean.getDotProduct(centerMinusBeginClockwise, centerClockwise) loop.append(center + centerClockwise * radius / max(0.5, abs(dotProduct)))
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 isInline( beginComplex, centerComplex, endComplex ): 'Determine if the three complex points form a line.' centerBeginComplex = beginComplex - centerComplex centerEndComplex = endComplex - centerComplex centerBeginLength = abs( centerBeginComplex ) centerEndLength = abs( centerEndComplex ) if centerBeginLength <= 0.0 or centerEndLength <= 0.0: return False centerBeginComplex /= centerBeginLength centerEndComplex /= centerEndLength return euclidean.getDotProduct( centerBeginComplex, centerEndComplex ) < -0.999
def isSharpCorner(beginComplex, centerComplex, endComplex): 'Determine if the three complex points form a sharp corner.' centerBeginComplex = beginComplex - centerComplex centerEndComplex = endComplex - centerComplex centerBeginLength = abs(centerBeginComplex) centerEndLength = abs(centerEndComplex) if centerBeginLength <= 0.0 or centerEndLength <= 0.0: return False centerBeginComplex /= centerBeginLength centerEndComplex /= centerEndLength return euclidean.getDotProduct(centerBeginComplex, centerEndComplex) > 0.9
def getCrossLimitedStretch( self, crossLimitedStretch, crossLineIterator, locationComplex ): "Get cross limited relative stretch for a location." try: line = crossLineIterator.getNext() except StopIteration: return crossLimitedStretch splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) pointComplex = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine).dropAxis(2) pointMinusLocation = locationComplex - pointComplex pointMinusLocationLength = abs( pointMinusLocation ) if pointMinusLocationLength <= self.crossLimitDistanceFraction: return crossLimitedStretch parallelNormal = pointMinusLocation / pointMinusLocationLength parallelStretch = euclidean.getDotProduct( parallelNormal, crossLimitedStretch ) * parallelNormal if pointMinusLocationLength > self.crossLimitDistance: return parallelStretch crossNormal = complex( parallelNormal.imag, - parallelNormal.real ) crossStretch = euclidean.getDotProduct( crossNormal, crossLimitedStretch ) * crossNormal crossPortion = ( self.crossLimitDistance - pointMinusLocationLength ) / self.crossLimitDistanceRemainder return parallelStretch + crossStretch * crossPortion
def isInline( beginComplex, centerComplex, endComplex ): "Determine if the three complex points form a line." centerBeginComplex = beginComplex - centerComplex centerEndComplex = endComplex - centerComplex centerBeginLength = abs( centerBeginComplex ) centerEndLength = abs( centerEndComplex ) if centerBeginLength <= 0.0 or centerEndLength <= 0.0: return False centerBeginComplex /= centerBeginLength centerEndComplex /= centerEndLength return euclidean.getDotProduct( centerBeginComplex, centerEndComplex ) < - 0.999
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 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 addInsetPointFromClockwiseTriple(begin, center, end, loop, radius): 'Get inset point with possible intersection from clockwise triple, out from widdershins loop.' centerMinusBegin = center - begin centerMinusBeginLength = abs(centerMinusBegin) centerMinusBeginClockwise = None if centerMinusBeginLength > 0.0: centerMinusBeginClockwise = complex(centerMinusBegin.imag, -centerMinusBegin.real) / centerMinusBeginLength endMinusCenter = end - center endMinusCenterLength = abs(endMinusCenter) endMinusCenterClockwise = None if endMinusCenterLength > 0.0: endMinusCenterClockwise = complex(endMinusCenter.imag, -endMinusCenter.real) / endMinusCenterLength if centerMinusBeginClockwise == None and endMinusCenterClockwise == None: return None if centerMinusBeginClockwise == None: loop.append(center + endMinusCenterClockwise * radius) if endMinusCenterClockwise == None: loop.append(center + centerMinusBeginClockwise * radius) centerClockwise = 0.5 * (centerMinusBeginClockwise + endMinusCenterClockwise) dotProduct = euclidean.getDotProduct(centerMinusBeginClockwise, centerClockwise) loop.append(center + centerClockwise * radius / max(0.5, abs(dotProduct)))
def getIsParallelToRotation(self, segment): "Determine if the segment is parallel to the rotation." return abs(euclidean.getDotProduct(segment, self.rotation)) > 0.99999
def getIsParallelToRotation(self, segment): 'Determine if the segment is parallel to the rotation.' return abs(euclidean.getDotProduct(segment, self.rotation)) > 0.99999