def addOrbits( distanceFeedRate, loop, orbitalFeedRatePerSecond, temperatureChangeTime, z ): "Add orbits with the extruder off." timeInOrbit = 0.0 while timeInOrbit < temperatureChangeTime: for point in loop: distanceFeedRate.addGcodeMovementZWithFeedRate( 60.0 * orbitalFeedRatePerSecond, point, z ) timeInOrbit += euclidean.getPolygonLength( loop ) / orbitalFeedRatePerSecond
def getJitteredLoop( self, jitterDistance, jitterLoop ): "Get a jittered loop path." loopLength = euclidean.getPolygonLength( jitterLoop ) lastLength = 0.0 pointIndex = 0 totalLength = 0.0 jitterPosition = ( jitterDistance + 256.0 * loopLength ) % loopLength while totalLength < jitterPosition and pointIndex < len( jitterLoop ): firstPoint = jitterLoop[ pointIndex ] secondPoint = jitterLoop[ ( pointIndex + 1 ) % len( jitterLoop ) ] pointIndex += 1 lastLength = totalLength totalLength += abs( firstPoint - secondPoint ) remainingLength = jitterPosition - lastLength pointIndex = pointIndex % len( jitterLoop ) ultimateJitteredPoint = jitterLoop[ pointIndex ] penultimateJitteredPointIndex = ( pointIndex + len( jitterLoop ) - 1 ) % len( jitterLoop ) penultimateJitteredPoint = jitterLoop[ penultimateJitteredPointIndex ] segment = ultimateJitteredPoint - penultimateJitteredPoint segmentLength = abs( segment ) originalOffsetLoop = euclidean.getAroundLoop( pointIndex, pointIndex, jitterLoop ) if segmentLength <= 0.0: return originalOffsetLoop newUltimatePoint = penultimateJitteredPoint + segment * remainingLength / segmentLength return [ newUltimatePoint ] + originalOffsetLoop
def addPathBeforeEnd( self, aroundBetweenPath, location, loop ): "Add the path before the end of the loop." halfFillInset = 0.5 * self.fillInset if self.arrivalInsetFollowDistance < halfFillInset: return locationComplex = location.dropAxis( 2 ) closestInset = None closestDistanceIndex = euclidean.DistanceIndex( 999999999999999999.0, - 1 ) loop = euclidean.getAwayPoints( loop, self.extrusionWidth ) circleNodes = intercircle.getCircleNodesFromLoop( loop, self.fillInset ) centers = [] centers = intercircle.getCentersFromCircleNodes( circleNodes ) for center in centers: inset = intercircle.getInsetFromClockwiseLoop( center, halfFillInset ) if euclidean.isLargeSameDirection( inset, center, self.fillInset ): if euclidean.isPathInsideLoop( loop, inset ) == euclidean.isWiddershins( loop ): distanceIndex = euclidean.getNearestDistanceIndex( locationComplex, inset ) if distanceIndex.distance < closestDistanceIndex.distance: closestInset = inset closestDistanceIndex = distanceIndex if closestInset == None: return extrusionHalfWidth = 0.5 * self.extrusionWidth closestInset = euclidean.getLoopStartingNearest( extrusionHalfWidth, locationComplex, closestInset ) if euclidean.getPolygonLength( closestInset ) < 0.2 * self.arrivalInsetFollowDistance: return closestInset.append( closestInset[ 0 ] ) closestInset = euclidean.getSimplifiedPath( closestInset, self.extrusionWidth ) closestInset.reverse() pathBeforeArrival = euclidean.getClippedAtEndLoopPath( self.arrivalInsetFollowDistance, closestInset ) pointBeforeArrival = pathBeforeArrival[ - 1 ] aroundBetweenPath.append( pointBeforeArrival ) if self.arrivalInsetFollowDistance <= halfFillInset: return aroundBetweenPath += euclidean.getClippedAtEndLoopPath( halfFillInset, closestInset )[ len( pathBeforeArrival ) - 1 : ]
def getJitteredLoop(self, jitterDistance, jitterLoop): "Get a jittered loop path." loopLength = euclidean.getPolygonLength(jitterLoop) lastLength = 0.0 pointIndex = 0 totalLength = 0.0 jitterPosition = (jitterDistance + 256.0 * loopLength) % loopLength while totalLength < jitterPosition and pointIndex < len(jitterLoop): firstPoint = jitterLoop[pointIndex] secondPoint = jitterLoop[(pointIndex + 1) % len(jitterLoop)] pointIndex += 1 lastLength = totalLength totalLength += abs(firstPoint - secondPoint) remainingLength = jitterPosition - lastLength pointIndex = pointIndex % len(jitterLoop) ultimateJitteredPoint = jitterLoop[pointIndex] penultimateJitteredPointIndex = (pointIndex + len(jitterLoop) - 1) % len(jitterLoop) penultimateJitteredPoint = jitterLoop[penultimateJitteredPointIndex] segment = ultimateJitteredPoint - penultimateJitteredPoint segmentLength = abs(segment) originalOffsetLoop = euclidean.getAroundLoop(pointIndex, pointIndex, jitterLoop) if segmentLength <= 0.0: return [penultimateJitteredPoint] + originalOffsetLoop[-1] newUltimatePoint = penultimateJitteredPoint + segment * remainingLength / segmentLength return [newUltimatePoint] + originalOffsetLoop
def addOrbits(distanceFeedRate, loop, orbitalFeedRatePerSecond, temperatureChangeTime, z): "Add orbits with the extruder off." timeInOrbit = 0.0 while timeInOrbit < temperatureChangeTime: for point in loop: distanceFeedRate.addGcodeMovementZWithFeedRate( 60.0 * orbitalFeedRatePerSecond, point, z) timeInOrbit += euclidean.getPolygonLength( loop) / orbitalFeedRatePerSecond
def addOrbits( loop, skein, temperatureChangeTime, z ): "Add orbits with the extruder off." if len( loop ) < 1: print( 'Zero length loop which was skipped over, this should never happen.' ) if temperatureChangeTime < 1.5: return timeInOrbit = 0.0 while timeInOrbit < temperatureChangeTime: for point in loop: skein.addGcodeFromFeedrateMovementZ( 60.0 * skein.orbitalFeedratePerSecond, point, z ) timeInOrbit += euclidean.getPolygonLength( loop ) / skein.orbitalFeedratePerSecond
def getPathBetween(self, betweenFirst, betweenSecond, isLeavingPerimeter, loopFirst): "Add a path between the perimeter and the fill." loopFirst = intercircle.getLargestInsetLoopFromLoopNoMatterWhat( loopFirst, self.combInset) nearestFirstDistanceIndex = euclidean.getNearestDistanceIndex( betweenFirst, loopFirst) nearestSecondDistanceIndex = euclidean.getNearestDistanceIndex( betweenSecond, loopFirst) firstBeginIndex = (nearestFirstDistanceIndex.index + 1) % len(loopFirst) secondBeginIndex = (nearestSecondDistanceIndex.index + 1) % len(loopFirst) nearestFirst = euclidean.getNearestPointOnSegment( loopFirst[nearestFirstDistanceIndex.index], loopFirst[firstBeginIndex], betweenFirst) nearestSecond = euclidean.getNearestPointOnSegment( loopFirst[nearestSecondDistanceIndex.index], loopFirst[secondBeginIndex], betweenSecond) clockwisePath = [nearestFirst] widdershinsPath = [nearestFirst] loopBeforeLeaving = euclidean.getAroundLoop(firstBeginIndex, firstBeginIndex, loopFirst) if nearestFirstDistanceIndex.index == nearestSecondDistanceIndex.index: if euclidean.getPathLength( widdershinsPath) < self.minimumDepartureDistance: widdershinsPath = [nearestFirst] + loopBeforeLeaving reversedLoop = loopBeforeLeaving[:] reversedLoop.reverse() clockwisePath = [nearestFirst] + reversedLoop else: widdershinsLoop = euclidean.getAroundLoop(firstBeginIndex, secondBeginIndex, loopFirst) widdershinsPath += widdershinsLoop clockwiseLoop = euclidean.getAroundLoop(secondBeginIndex, firstBeginIndex, loopFirst) clockwiseLoop.reverse() clockwisePath += clockwiseLoop clockwisePath.append(nearestSecond) widdershinsPath.append(nearestSecond) if euclidean.getPathLength(widdershinsPath) > euclidean.getPathLength( clockwisePath): loopBeforeLeaving.reverse() widdershinsPath = clockwisePath if isLeavingPerimeter: totalDistance = euclidean.getPathLength(widdershinsPath) loopLength = euclidean.getPolygonLength(loopBeforeLeaving) while totalDistance < self.minimumDepartureDistance: widdershinsPath = [nearestFirst ] + loopBeforeLeaving + widdershinsPath[1:] totalDistance += loopLength return widdershinsPath
def addPathBetween(self, aroundBetweenPath, betweenFirst, betweenSecond, isLeavingPerimeter, loopFirst): "Add a path between the perimeter and the fill." clockwisePath = [betweenFirst] widdershinsPath = [betweenFirst] nearestFirstDistanceIndex = euclidean.getNearestDistanceIndex( betweenFirst, loopFirst) nearestSecondDistanceIndex = euclidean.getNearestDistanceIndex( betweenSecond, loopFirst) firstBeginIndex = (nearestFirstDistanceIndex.index + 1) % len(loopFirst) secondBeginIndex = (nearestSecondDistanceIndex.index + 1) % len(loopFirst) loopBeforeLeaving = euclidean.getAroundLoop(firstBeginIndex, firstBeginIndex, loopFirst) if nearestFirstDistanceIndex.index == nearestSecondDistanceIndex.index: nearestPoint = euclidean.getNearestPointOnSegment( loopFirst[nearestSecondDistanceIndex.index], loopFirst[secondBeginIndex], betweenSecond) widdershinsPath += [nearestPoint] clockwisePath += [nearestPoint] if euclidean.getPathLength( widdershinsPath) < self.minimumPerimeterDepartureDistance: widdershinsPath = [betweenFirst ] + loopBeforeLeaving + [nearestPoint] reversedLoop = loopBeforeLeaving[:] reversedLoop.reverse() clockwisePath = [betweenFirst] + reversedLoop + [nearestPoint] else: widdershinsLoop = euclidean.getAroundLoop(firstBeginIndex, secondBeginIndex, loopFirst) widdershinsPath += widdershinsLoop clockwiseLoop = euclidean.getAroundLoop(secondBeginIndex, firstBeginIndex, loopFirst) clockwiseLoop.reverse() clockwisePath += clockwiseLoop clockwisePath.append(betweenSecond) widdershinsPath.append(betweenSecond) if euclidean.getPathLength(widdershinsPath) > euclidean.getPathLength( clockwisePath): loopBeforeLeaving.reverse() widdershinsPath = clockwisePath if isLeavingPerimeter: totalDistance = euclidean.getPathLength(widdershinsPath) loopLength = euclidean.getPolygonLength(loopBeforeLeaving) while totalDistance < self.minimumPerimeterDepartureDistance: widdershinsPath = [betweenFirst ] + loopBeforeLeaving + widdershinsPath[1:] totalDistance += loopLength aroundBetweenPath += widdershinsPath
def addCoilToThread( self, beginLocation, endZ, loop, thread ): "Add a coil to the thread." if len( loop ) < 1: return loop = euclidean.getLoopStartingNearest( self.halfPerimeterWidth, self.oldLocationComplex, loop ) length = euclidean.getPolygonLength( loop ) if length <= 0.0: return oldPoint = loop[ 0 ] pathLength = 0.0 for point in loop[ 1 : ]: pathLength += abs( point - oldPoint ) along = pathLength / length z = ( 1.0 - along ) * beginLocation.z + along * endZ location = Vector3( point.real, point.imag, z ) thread.append( location ) oldPoint = point self.oldLocationComplex = loop[ - 1 ]
def addPathBeforeEnd(self, aroundBetweenPath, location, loop): "Add the path before the end of the loop." halfFillInset = 0.5 * self.fillInset if self.arrivalInsetFollowDistance < halfFillInset: return locationComplex = location.dropAxis(2) closestInset = None closestDistanceIndex = euclidean.DistanceIndex(999999999999999999.0, -1) loop = euclidean.getAwayPoints(loop, self.extrusionWidth) circleNodes = intercircle.getCircleNodesFromLoop(loop, self.fillInset) centers = [] centers = intercircle.getCentersFromCircleNodes(circleNodes) for center in centers: inset = intercircle.getInsetFromClockwiseLoop( center, halfFillInset) if euclidean.isLargeSameDirection(inset, center, self.fillInset): if euclidean.isPathInsideLoop( loop, inset) == euclidean.isWiddershins(loop): distanceIndex = euclidean.getNearestDistanceIndex( locationComplex, inset) if distanceIndex.distance < closestDistanceIndex.distance: closestInset = inset closestDistanceIndex = distanceIndex if closestInset == None: return extrusionHalfWidth = 0.5 * self.extrusionWidth closestInset = euclidean.getLoopStartingNearest( extrusionHalfWidth, locationComplex, closestInset) if euclidean.getPolygonLength( closestInset) < 0.2 * self.arrivalInsetFollowDistance: return closestInset.append(closestInset[0]) closestInset = euclidean.getSimplifiedPath(closestInset, self.extrusionWidth) closestInset.reverse() pathBeforeArrival = euclidean.getClippedAtEndLoopPath( self.arrivalInsetFollowDistance, closestInset) pointBeforeArrival = pathBeforeArrival[-1] aroundBetweenPath.append(pointBeforeArrival) if self.arrivalInsetFollowDistance <= halfFillInset: return aroundBetweenPath += euclidean.getClippedAtEndLoopPath( halfFillInset, closestInset)[len(pathBeforeArrival) - 1:]
def addCoilToThread(self, beginLocation, endZ, loop, thread): "Add a coil to the thread." if len(loop) < 1: return loop = euclidean.getLoopStartingNearest(self.halfPerimeterWidth, self.oldLocationComplex, loop) length = euclidean.getPolygonLength(loop) if length <= 0.0: return oldPoint = loop[0] pathLength = 0.0 for point in loop[1:]: pathLength += abs(point - oldPoint) along = pathLength / length z = (1.0 - along) * beginLocation.z + along * endZ location = Vector3(point.real, point.imag, z) thread.append(location) oldPoint = point self.oldLocationComplex = loop[-1]
def getPathBetween(self, betweenFirst, betweenSecond, isLeavingPerimeter, loopFirst): "Add a path between the perimeter and the fill." loopFirst = intercircle.getLargestInsetLoopFromLoopNoMatterWhat(loopFirst, self.combInset) nearestFirstDistanceIndex = euclidean.getNearestDistanceIndex(betweenFirst, loopFirst) nearestSecondDistanceIndex = euclidean.getNearestDistanceIndex(betweenSecond, loopFirst) firstBeginIndex = (nearestFirstDistanceIndex.index + 1) % len(loopFirst) secondBeginIndex = (nearestSecondDistanceIndex.index + 1) % len(loopFirst) nearestFirst = euclidean.getNearestPointOnSegment( loopFirst[nearestFirstDistanceIndex.index], loopFirst[firstBeginIndex], betweenFirst ) nearestSecond = euclidean.getNearestPointOnSegment( loopFirst[nearestSecondDistanceIndex.index], loopFirst[secondBeginIndex], betweenSecond ) clockwisePath = [nearestFirst] widdershinsPath = [nearestFirst] loopBeforeLeaving = euclidean.getAroundLoop(firstBeginIndex, firstBeginIndex, loopFirst) if nearestFirstDistanceIndex.index == nearestSecondDistanceIndex.index: if euclidean.getPathLength(widdershinsPath) < self.minimumDepartureDistance: widdershinsPath = [nearestFirst] + loopBeforeLeaving reversedLoop = loopBeforeLeaving[:] reversedLoop.reverse() clockwisePath = [nearestFirst] + reversedLoop else: widdershinsLoop = euclidean.getAroundLoop(firstBeginIndex, secondBeginIndex, loopFirst) widdershinsPath += widdershinsLoop clockwiseLoop = euclidean.getAroundLoop(secondBeginIndex, firstBeginIndex, loopFirst) clockwiseLoop.reverse() clockwisePath += clockwiseLoop clockwisePath.append(nearestSecond) widdershinsPath.append(nearestSecond) if euclidean.getPathLength(widdershinsPath) > euclidean.getPathLength(clockwisePath): loopBeforeLeaving.reverse() widdershinsPath = clockwisePath if isLeavingPerimeter: totalDistance = euclidean.getPathLength(widdershinsPath) loopLength = euclidean.getPolygonLength(loopBeforeLeaving) while totalDistance < self.minimumDepartureDistance: widdershinsPath = [nearestFirst] + loopBeforeLeaving + widdershinsPath[1:] totalDistance += loopLength return widdershinsPath
def addOperatingOrbits( boundaryLoops, pointComplex, skein, temperatureChangeTime, z ): "Add the orbits before the operating layers." if len( boundaryLoops ) < 1: return largestLength = - 999999999.0 largestLoop = None perimeterOutset = 0.4 * skein.extrusionPerimeterWidth greaterThanPerimeterOutset = 1.1 * perimeterOutset for boundaryLoop in boundaryLoops: centers = getCentersFromLoopDirection( True, boundaryLoop, greaterThanPerimeterOutset ) for center in centers: outset = getSimplifiedInsetFromClockwiseLoop( center, perimeterOutset ) if euclidean.isLargeSameDirection( outset, center, perimeterOutset ): loopLength = euclidean.getPolygonLength( outset ) if loopLength > largestLength: largestLength = loopLength largestLoop = outset if largestLoop == None: return if pointComplex != None: largestLoop = euclidean.getLoopStartingNearest( skein.extrusionPerimeterWidth, pointComplex, largestLoop ) addOrbits( largestLoop, skein, temperatureChangeTime, z )
def addPathBetween( self, aroundBetweenPath, betweenFirst, betweenSecond, isLeavingPerimeter, loopFirst ): "Add a path between the perimeter and the fill." clockwisePath = [ betweenFirst ] widdershinsPath = [ betweenFirst ] nearestFirstDistanceIndex = euclidean.getNearestDistanceIndex( betweenFirst, loopFirst ) nearestSecondDistanceIndex = euclidean.getNearestDistanceIndex( betweenSecond, loopFirst ) firstBeginIndex = ( nearestFirstDistanceIndex.index + 1 ) % len( loopFirst ) secondBeginIndex = ( nearestSecondDistanceIndex.index + 1 ) % len( loopFirst ) loopBeforeLeaving = euclidean.getAroundLoop( firstBeginIndex, firstBeginIndex, loopFirst ) if nearestFirstDistanceIndex.index == nearestSecondDistanceIndex.index: nearestPoint = euclidean.getNearestPointOnSegment( loopFirst[ nearestSecondDistanceIndex.index ], loopFirst[ secondBeginIndex ], betweenSecond ) widdershinsPath += [ nearestPoint ] clockwisePath += [ nearestPoint ] if euclidean.getPathLength( widdershinsPath ) < self.minimumPerimeterDepartureDistance: widdershinsPath = [ betweenFirst ] + loopBeforeLeaving + [ nearestPoint ] reversedLoop = loopBeforeLeaving[ : ] reversedLoop.reverse() clockwisePath = [ betweenFirst ] + reversedLoop + [ nearestPoint ] else: widdershinsLoop = euclidean.getAroundLoop( firstBeginIndex, secondBeginIndex, loopFirst ) widdershinsPath += widdershinsLoop clockwiseLoop = euclidean.getAroundLoop( secondBeginIndex, firstBeginIndex, loopFirst ) clockwiseLoop.reverse() clockwisePath += clockwiseLoop clockwisePath.append( betweenSecond ) widdershinsPath.append( betweenSecond ) if euclidean.getPathLength( widdershinsPath ) > euclidean.getPathLength( clockwisePath ): loopBeforeLeaving.reverse() widdershinsPath = clockwisePath if isLeavingPerimeter: totalDistance = euclidean.getPathLength( widdershinsPath ) loopLength = euclidean.getPolygonLength( loopBeforeLeaving ) while totalDistance < self.minimumPerimeterDepartureDistance: widdershinsPath = [ betweenFirst ] + loopBeforeLeaving + widdershinsPath[ 1 : ] totalDistance += loopLength aroundBetweenPath += widdershinsPath