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.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 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 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 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 getCircleIntersectionAhead( self ): "Get the first circle intersection on the circle node ahead." aheadMinusBehind = 0.5 * ( self.circleNodeAhead.circle - self.circleNodeBehind.circle ) circleIntersections = self.circleNodeAhead.circleIntersections circleIntersectionAhead = None circleNodesMidpoint = 0.5 * ( self.circleNodeAhead.circle + self.circleNodeBehind.circle ) largestDot = - 999999999.0 positionRelativeToMidpoint = self.getDemichord( aheadMinusBehind ) circleNodeAheadCircleMinusMidpoint = self.circleNodeAhead.circle - circleNodesMidpoint for circleIntersection in circleIntersections: if not circleIntersection.steppedOn: circleIntersectionRelativeToMidpoint = circleIntersection.getPositionRelativeToBehind() + circleNodeAheadCircleMinusMidpoint circleIntersectionRelativeToMidpoint = euclidean.getNormalized( circleIntersectionRelativeToMidpoint ) dot = euclidean.getDotProduct( positionRelativeToMidpoint, 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 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