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 getPathBetween(self, loop, points): "Add a path between the edge and the fill." paths = getPathsByIntersectedLoop(points[1], points[2], loop) shortestPath = paths[int( euclidean.getPathLength(paths[1]) < euclidean.getPathLength( paths[0]))] if len(shortestPath) < 2: return shortestPath if abs(points[1] - shortestPath[0]) > abs(points[1] - shortestPath[-1]): shortestPath.reverse() loopWiddershins = euclidean.isWiddershins(loop) pathBetween = [] for pointIndex in xrange(len(shortestPath)): center = shortestPath[pointIndex] centerPerpendicular = None beginIndex = pointIndex - 1 if beginIndex >= 0: begin = shortestPath[beginIndex] # with "self.edgeWidth*2.0" better "combed". See calibration file comb_test.stl . centerPerpendicular = intercircle.getWiddershinsByLength( center, begin, self.edgeWidth * 2.0) centerEnd = None endIndex = pointIndex + 1 if endIndex < len(shortestPath): end = shortestPath[endIndex] # with "self.edgeWidth*2.0" better "combed". See calibration file comb_test.stl . centerEnd = intercircle.getWiddershinsByLength( end, center, self.edgeWidth * 2.0) if centerPerpendicular == None: centerPerpendicular = centerEnd elif centerEnd != None: centerPerpendicular = 0.5 * (centerPerpendicular + centerEnd) between = None if centerPerpendicular == None: between = center if between == None: centerSideWiddershins = center + centerPerpendicular if euclidean.isPointInsideLoop( loop, centerSideWiddershins) == loopWiddershins: between = centerSideWiddershins if between == None: centerSideClockwise = center - centerPerpendicular if euclidean.isPointInsideLoop( loop, centerSideClockwise) == loopWiddershins: between = centerSideClockwise if between == None: between = center pathBetween.append(between) return pathBetween
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 getMirrorPath(path): "Get mirror path." close = 0.001 * euclidean.getPathLength(path) pathLimit = len(path) - 1 for pointIndex in xrange(pathLimit, -1, -1): point = path[pointIndex] flipPoint = complex(-point.real, point.imag) if abs(flipPoint - path[-1]) > close: path.append(flipPoint) return path
def getMirrorPath(path): "Get mirror path." close = 0.001 * euclidean.getPathLength(path) pathLimit = len(path) - 1 for pointIndex in xrange(pathLimit, -1, -1): point = path[pointIndex] flipPoint = complex(-point.real, point.imag) if abs(flipPoint - path[-1]) > close: path.append(flipPoint) return path
def getPathBetween(self, loop, points): "Add a path between the edge and the fill." paths = getPathsByIntersectedLoop(points[1], points[2], loop) shortestPath = paths[int(euclidean.getPathLength(paths[1]) < euclidean.getPathLength(paths[0]))] if len(shortestPath) < 2: return shortestPath if abs(points[1] - shortestPath[0]) > abs(points[1] - shortestPath[-1]): shortestPath.reverse() loopWiddershins = euclidean.isWiddershins(loop) pathBetween = [] for pointIndex in xrange(len(shortestPath)): center = shortestPath[pointIndex] centerPerpendicular = None beginIndex = pointIndex - 1 if beginIndex >= 0: begin = shortestPath[beginIndex] centerPerpendicular = intercircle.getWiddershinsByLength(center, begin, self.edgeWidth) centerEnd = None endIndex = pointIndex + 1 if endIndex < len(shortestPath): end = shortestPath[endIndex] centerEnd = intercircle.getWiddershinsByLength(end, center, self.edgeWidth) if centerPerpendicular == None: centerPerpendicular = centerEnd elif centerEnd != None: centerPerpendicular = 0.5 * (centerPerpendicular + centerEnd) between = None if centerPerpendicular == None: between = center if between == None: centerSideWiddershins = center + centerPerpendicular if euclidean.isPointInsideLoop(loop, centerSideWiddershins) == loopWiddershins: between = centerSideWiddershins if between == None: centerSideClockwise = center - centerPerpendicular if euclidean.isPointInsideLoop(loop, centerSideClockwise) == loopWiddershins: between = centerSideClockwise if between == None: between = center pathBetween.append(between) return pathBetween
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 addGcodeFromPerimeterPaths(self, isIntersectingSelf, loop, loopLayer, loopLists, radius): "Add the perimeter paths to the output." segments = [] outlines = [] thickOutlines = [] allLoopLists = loopLists[:] + [thickOutlines] aroundLists = loopLists for pointIndex in xrange(len(loop)): pointBegin = loop[pointIndex] pointEnd = loop[(pointIndex + 1) % len(loop)] if isIntersectingSelf: if euclidean.isLineIntersectingLoops(outlines, pointBegin, pointEnd): segments += getSegmentsFromLoopListsPoints( allLoopLists, pointBegin, pointEnd) else: segments += getSegmentsFromLoopListsPoints( loopLists, pointBegin, pointEnd) addSegmentOutline(False, outlines, pointBegin, pointEnd, self.overlapRemovalWidth) addSegmentOutline(True, thickOutlines, pointBegin, pointEnd, self.overlapRemovalWidth) else: segments += getSegmentsFromLoopListsPoints( loopLists, pointBegin, pointEnd) perimeterPaths = [] path = [] muchSmallerThanRadius = 0.1 * radius segments = getInteriorSegments(loopLayer.loops, segments) for segment in segments: pointBegin = segment[0].point if not isCloseToLast(perimeterPaths, pointBegin, muchSmallerThanRadius): path = [pointBegin] perimeterPaths.append(path) path.append(segment[1].point) if len(perimeterPaths) > 1: firstPath = perimeterPaths[0] lastPath = perimeterPaths[-1] if abs(lastPath[-1] - firstPath[0]) < 0.1 * muchSmallerThanRadius: connectedBeginning = lastPath[:-1] + firstPath perimeterPaths[0] = connectedBeginning perimeterPaths.remove(lastPath) muchGreaterThanRadius = 6.0 * radius for perimeterPath in perimeterPaths: if euclidean.getPathLength(perimeterPath) > muchGreaterThanRadius: self.distanceFeedRate.addGcodeFromThreadZ( perimeterPath, loopLayer.z)
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 addGcodeFromPerimeterPaths( self, nestedRing, isIntersectingSelf, loop, alreadyFilledArounds, halfWidth, boundary ): "Add the perimeter paths to the output." segments = [] outlines = [] thickOutlines = [] allLoopLists = alreadyFilledArounds[:] + [thickOutlines] aroundLists = alreadyFilledArounds for pointIndex in xrange(len(loop)): pointBegin = loop[pointIndex] pointEnd = loop[(pointIndex + 1) % len(loop)] if isIntersectingSelf: if euclidean.isLineIntersectingLoops(outlines, pointBegin, pointEnd): segments += getSegmentsFromLoopListsPoints(allLoopLists, pointBegin, pointEnd) else: segments += getSegmentsFromLoopListsPoints(alreadyFilledArounds, pointBegin, pointEnd) addSegmentOutline(False, outlines, pointBegin, pointEnd, self.overlapRemovalWidth) addSegmentOutline(True, thickOutlines, pointBegin, pointEnd, self.overlapRemovalWidth) else: segments += getSegmentsFromLoopListsPoints(alreadyFilledArounds, pointBegin, pointEnd) perimeterPaths = [] path = [] muchSmallerThanRadius = 0.1 * halfWidth segments = getInteriorSegments(boundary, segments) for segment in segments: pointBegin = segment[0].point if not isCloseToLast(perimeterPaths, pointBegin, muchSmallerThanRadius): path = [pointBegin] perimeterPaths.append(path) path.append(segment[1].point) if len(perimeterPaths) > 1: firstPath = perimeterPaths[0] lastPath = perimeterPaths[-1] if abs(lastPath[-1] - firstPath[0]) < 0.1 * muchSmallerThanRadius: connectedBeginning = lastPath[:-1] + firstPath perimeterPaths[0] = connectedBeginning perimeterPaths.remove(lastPath) muchGreaterThanRadius = 6.0 * halfWidth for perimeterPath in perimeterPaths: if euclidean.getPathLength(perimeterPath) > muchGreaterThanRadius: nestedRing.perimeter.addPath(perimeterPath)
def getInsideness( path, loop ): "Get portion of the path which is inside the loop." if len( path ) < 2: return 0.0 pathLength = euclidean.getPathLength( path ) incrementRatio = 0.017 increment = incrementRatio * pathLength oldPoint = path[ 0 ] numberOfPointsInside = float( euclidean.isPointInsideLoop( loop, oldPoint ) ) for point in path[ 1 : ]: segment = point - oldPoint distance = abs( segment ) numberOfPosts = int( math.ceil( distance / increment ) ) if numberOfPosts > 0: segmentIncrement = segment / float( numberOfPosts ) for post in xrange( numberOfPosts ): postPoint = oldPoint + float( post ) * segmentIncrement numberOfPointsInside += float( euclidean.isPointInsideLoop( loop, postPoint ) ) oldPoint = point return incrementRatio * numberOfPointsInside
def getInsideness(path, loop): "Get portion of the path which is inside the loop." if len(path) < 2: return 0.0 pathLength = euclidean.getPathLength(path) incrementRatio = 0.017 increment = incrementRatio * pathLength oldPoint = path[0] numberOfPointsInside = float(euclidean.isPointInsideLoop(loop, oldPoint)) for point in path[1:]: segment = point - oldPoint distance = abs(segment) numberOfPosts = int(math.ceil(distance / increment)) if numberOfPosts > 0: segmentIncrement = segment / float(numberOfPosts) for post in xrange(numberOfPosts): postPoint = oldPoint + float(post) * segmentIncrement numberOfPointsInside += float( euclidean.isPointInsideLoop(loop, postPoint)) oldPoint = point return incrementRatio * numberOfPointsInside
def addGcodeFromPerimeterPaths(self, isIntersectingSelf, loop, loopLayer, loopLists, radius): "Add the edge paths to the output." segments = [] outlines = [] thickOutlines = [] allLoopLists = loopLists[:] + [thickOutlines] aroundLists = loopLists for pointIndex in xrange(len(loop)): pointBegin = loop[pointIndex] pointEnd = loop[(pointIndex + 1) % len(loop)] if isIntersectingSelf: if euclidean.isLineIntersectingLoops(outlines, pointBegin, pointEnd): segments += getSegmentsFromLoopListsPoints(allLoopLists, pointBegin, pointEnd) else: segments += getSegmentsFromLoopListsPoints(loopLists, pointBegin, pointEnd) addSegmentOutline(False, outlines, pointBegin, pointEnd, self.overlapRemovalWidth) addSegmentOutline(True, thickOutlines, pointBegin, pointEnd, self.overlapRemovalWidth) else: segments += getSegmentsFromLoopListsPoints(loopLists, pointBegin, pointEnd) edgePaths = [] path = [] muchSmallerThanRadius = 0.1 * radius segments = getInteriorSegments(loopLayer.loops, segments) for segment in segments: pointBegin = segment[0].point if not isCloseToLast(edgePaths, pointBegin, muchSmallerThanRadius): path = [pointBegin] edgePaths.append(path) path.append(segment[1].point) if len(edgePaths) > 1: firstPath = edgePaths[0] lastPath = edgePaths[-1] if abs(lastPath[-1] - firstPath[0]) < 0.1 * muchSmallerThanRadius: connectedBeginning = lastPath[: -1] + firstPath edgePaths[0] = connectedBeginning edgePaths.remove(lastPath) muchGreaterThanRadius = 6.0 * radius for edgePath in edgePaths: if euclidean.getPathLength(edgePath) > muchGreaterThanRadius: self.distanceFeedRate.addGcodeFromThreadZ(edgePath, loopLayer.z)