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 addRunningJumpPath( self, end, loop, pathAround ): "Get the running jump path from the perimeter to the intersection or running jump space." if self.combRepository.runningJumpSpaceOverPerimeterWidth.value < 1.0: return if len( pathAround ) < 2: return loop = intercircle.getLargestInsetLoopFromLoopNoMatterWhat( loop, self.combInset ) penultimatePoint = pathAround[ - 2 ] lastPoint = pathAround[ - 1 ] nearestEndDistanceIndex = euclidean.getNearestDistanceIndex( end, loop ) nearestEndIndex = ( nearestEndDistanceIndex.index + 1 ) % len( loop ) nearestEnd = euclidean.getNearestPointOnSegment( loop[ nearestEndDistanceIndex.index ], loop[ nearestEndIndex ], end ) nearestEndMinusLast = nearestEnd - lastPoint nearestEndMinusLastLength = abs( nearestEndMinusLast ) if nearestEndMinusLastLength <= 0.0: return nearestEndMinusLastSegment = nearestEndMinusLast / nearestEndMinusLastLength betweens = self.getBetweens() if self.getIsRunningJumpPathAdded( betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, self.runningJumpSpace ): return doubleCombInset = 2.0 * self.combInset shortJumpSpace = 0.5 * self.runningJumpSpace if shortJumpSpace < doubleCombInset: return if self.getIsRunningJumpPathAdded( betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, shortJumpSpace ): return shortJumpSpace = 0.25 * self.runningJumpSpace if shortJumpSpace < doubleCombInset: return self.getIsRunningJumpPathAdded( betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, shortJumpSpace )
def getOutloopLocation(self, point): "Get location outside of loop." pointComplex = point.dropAxis(2) if str(point) not in self.pointTable: return pointComplex closestBetween = None closestDistanceIndex = euclidean.DistanceIndex(999999999999999999.0, -1) for between in self.getBetweens(): distanceIndex = euclidean.getNearestDistanceIndex( pointComplex, between) if distanceIndex.distance < closestDistanceIndex.distance: closestBetween = between closestDistanceIndex = distanceIndex if closestBetween == None: print( 'This should never happen, closestBetween should always exist.' ) print(point) print(self.getBetweens()) return pointComplex closestIndex = closestDistanceIndex.index segmentBegin = closestBetween[closestIndex] segmentEnd = closestBetween[(closestIndex + 1) % len(closestBetween)] nearestPoint = euclidean.getNearestPointOnSegment( segmentBegin, segmentEnd, pointComplex) distanceToNearestPoint = abs(pointComplex - nearestPoint) nearestMinusOld = 1.5 * (nearestPoint - pointComplex) return pointComplex + nearestMinusOld
def getTransferClosestSurroundingLoopLines( self, oldOrderedLocation, remainingSurroundingLoops ): "Get and transfer the closest remaining surrounding loop." if len( remainingSurroundingLoops ) > 0: oldOrderedLocation.z = remainingSurroundingLoops[ 0 ].z closestDistance = 999999999999999999.0 closestSurroundingLoop = None for remainingSurroundingLoop in remainingSurroundingLoops: distance = euclidean.getNearestDistanceIndex( oldOrderedLocation.dropAxis( 2 ), remainingSurroundingLoop.boundary ).distance if distance < closestDistance: closestDistance = distance closestSurroundingLoop = remainingSurroundingLoop remainingSurroundingLoops.remove( closestSurroundingLoop ) hasTravelledHighRoad = False for line in closestSurroundingLoop.lines: splitLine = gcodec.getSplitLineBeforeBracketSemicolon( line ) firstWord = gcodec.getFirstWord( splitLine ) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine ) if not hasTravelledHighRoad: hasTravelledHighRoad = True self.addHighThread( location ) if location.z > self.highestZ: self.highestZ = location.z self.oldLocation = location self.distanceFeedRate.addLine( line ) return closestSurroundingLoop
def getTransferClosestSurroundingLoopLines(self, oldOrderedLocation, remainingSurroundingLoops): "Get and transfer the closest remaining surrounding loop." if len(remainingSurroundingLoops) > 0: oldOrderedLocation.z = remainingSurroundingLoops[0].z closestDistance = 999999999999999999.0 closestSurroundingLoop = None for remainingSurroundingLoop in remainingSurroundingLoops: distance = euclidean.getNearestDistanceIndex( oldOrderedLocation.dropAxis(2), remainingSurroundingLoop.boundary).distance if distance < closestDistance: closestDistance = distance closestSurroundingLoop = remainingSurroundingLoop remainingSurroundingLoops.remove(closestSurroundingLoop) hasTravelledHighRoad = False for line in closestSurroundingLoop.lines: splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line) firstWord = gcodec.getFirstWord(splitLine) if firstWord == 'G1': location = gcodec.getLocationFromSplitLine( self.oldLocation, splitLine) if not hasTravelledHighRoad: hasTravelledHighRoad = True self.addHighThread(location) if location.z > self.highestZ: self.highestZ = location.z self.oldLocation = location self.distanceFeedRate.addLine(line) return closestSurroundingLoop
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 getIsAsFarAndNotIntersecting(self, begin, center, end, loop): "Determine if the point on the line is at least as far from the loop as the center point." if begin == end: print( "this should never happen but it does not really matter, begin == end in getIsAsFarAndNotIntersecting in comb." ) print(begin) return True centerMinusEnd = center - end centerMinusEndLength = abs(centerMinusEnd) if centerMinusEndLength <= 0.0: return True segment = euclidean.getNormalized(begin - end) segmentCenterMinusEnd = segment * centerMinusEndLength + end nearestCenterDistanceIndex = euclidean.getNearestDistanceIndex(center, loop) nearestCenterMinusEndDistanceIndex = euclidean.getNearestDistanceIndex(segmentCenterMinusEnd, loop) if nearestCenterMinusEndDistanceIndex.distance < nearestCenterDistanceIndex.distance: return False return not euclidean.isLineIntersectingLoops(self.getBetweens(), begin, end)
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 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 getRunningJumpPath(self, end, loop, pathAround): "Get the running jump path from the perimeter to the intersection or running jump space." if self.combPreferences.runningJumpSpaceOverPerimeterWidth.value < 1.0: return pathAround loop = intercircle.getLargestInsetLoopFromLoopNoMatterWhat(loop, self.combInset) lastPoint = pathAround[-1] nearestEndDistanceIndex = euclidean.getNearestDistanceIndex(end, loop) nearestEndIndex = (nearestEndDistanceIndex.index + 1) % len(loop) nearestEnd = euclidean.getNearestPointOnSegment(loop[nearestEndDistanceIndex.index], loop[nearestEndIndex], end) nearestEndMinusLast = nearestEnd - lastPoint nearestEndMinusLastLength = abs(nearestEndMinusLast) if nearestEndMinusLastLength <= 0.0: return pathAround nearestEndMinusLastSegment = nearestEndMinusLast / nearestEndMinusLastLength beginRun = self.getCorneredTruncatedJumpSpacePath(lastPoint, -nearestEndMinusLastSegment) endRun = self.getCorneredTruncatedJumpSpacePath(nearestEnd, nearestEndMinusLastSegment) endRun.reverse() pathAround += beginRun + endRun return pathAround
def addRunningJumpPath(self, end, loop, pathAround): "Get the running jump path from the perimeter to the intersection or running jump space." if self.combRepository.runningJumpSpaceOverPerimeterWidth.value < 1.0: return if len(pathAround) < 2: return loop = intercircle.getLargestInsetLoopFromLoopNoMatterWhat( loop, self.combInset) penultimatePoint = pathAround[-2] lastPoint = pathAround[-1] nearestEndDistanceIndex = euclidean.getNearestDistanceIndex(end, loop) nearestEndIndex = (nearestEndDistanceIndex.index + 1) % len(loop) nearestEnd = euclidean.getNearestPointOnSegment( loop[nearestEndDistanceIndex.index], loop[nearestEndIndex], end) nearestEndMinusLast = nearestEnd - lastPoint nearestEndMinusLastLength = abs(nearestEndMinusLast) if nearestEndMinusLastLength <= 0.0: return nearestEndMinusLastSegment = nearestEndMinusLast / nearestEndMinusLastLength betweens = self.getBetweens() if self.getIsRunningJumpPathAdded(betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, self.runningJumpSpace): return doubleCombInset = 2.0 * self.combInset shortJumpSpace = 0.5 * self.runningJumpSpace if shortJumpSpace < doubleCombInset: return if self.getIsRunningJumpPathAdded(betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, shortJumpSpace): return shortJumpSpace = 0.25 * self.runningJumpSpace if shortJumpSpace < doubleCombInset: return self.getIsRunningJumpPathAdded(betweens, end, lastPoint, nearestEndMinusLastSegment, pathAround, penultimatePoint, shortJumpSpace)
def getOutloopLocation( self, point ): "Get location outside of loop." pointComplex = point.dropAxis( 2 ) if str( point ) not in self.pointTable: return pointComplex closestBetween = None closestDistanceIndex = euclidean.DistanceIndex( 999999999999999999.0, - 1 ) for between in self.getBetweens(): distanceIndex = euclidean.getNearestDistanceIndex( pointComplex, between ) if distanceIndex.distance < closestDistanceIndex.distance: closestBetween = between closestDistanceIndex = distanceIndex if closestBetween == None: print( 'This should never happen, closestBetween should always exist.' ) print( point ) print( self.getBetweens() ) return pointComplex closestIndex = closestDistanceIndex.index segmentBegin = closestBetween[ closestIndex ] segmentEnd = closestBetween[ ( closestIndex + 1 ) % len( closestBetween ) ] nearestPoint = euclidean.getNearestPointOnSegment( segmentBegin, segmentEnd, pointComplex ) distanceToNearestPoint = abs( pointComplex - nearestPoint ) nearestMinusOld = 1.5 * ( nearestPoint - pointComplex ) return pointComplex + nearestMinusOld