def shell(shellCount,extrusionWidth,layer): #This also needs to be made smarter. It can't handle intersections that change the order of the loop yet. ''' This function takes a layer which has been through straighten and order, and forms the perimeter lines which will actually be extruded from the loops. Stores perimeter lines in layer.shells as a list of shell groups. Each shell group is a list of shells with varying insets. Shells are ordered lists of edges similar to loops. ''' insets = [n*extrusionWidth+extrusionWidth/2.0 for n in range(shellCount)] shellGroups = [] for loop in layer.loops: shells = [] for inset in insets: shell = [] for edge in loop: left = sp.cross(sp.array([0,0,1]),edge.dir[0]) shell.append(Basics.edge(edge.a+left*inset,edge.b+left*inset)) for index in range(len(shell)-1): activeEdge = shell[index] nextEdge = shell[index+1] if activeEdge.check2dintersect(nextEdge): intersect = activeEdge.point2dIntersect(nextEdge) shell[index]=Basics.edge(activeEdge.a,intersect) shell[index+1]=Basics.edge(intersect,nextEdge.b) activeEdge = shell[-1] nextEdge = shell[0] if activeEdge.check2dintersect(nextEdge): intersect = activeEdge.point2dIntersect(nextEdge) shell[-1]=Basics.edge(activeEdge.a,intersect) shell[0]=Basics.edge(intersect,nextEdge.b) shells.append(shell) shellGroups.append(shells) layer.shells = shellGroups
def edgeWrap(self, e, n, up=True): """ Similar to edgeShift, but with edge broken up into n segments of equal XY length to fit the function better. """ points = [e.a + m * e.dir[0] * e.length / n for m in range(n)] + [e.b] shiftPoints = [self.pointShift(p, up) for p in points] return [Basics.edge(shiftPoints[k], shiftPoints[k + 1]) for k in range(n)]
def edgeWrap(self, e, n, up=True): ''' Similar to edgeShift, but with edge broken up into n segments of equal XY length to fit the function better. ''' points = [e.a + m * e.dir[0] * e.length / n for m in range(n)] + [e.b] shiftPoints = [self.pointShift(p, up) for p in points] return [ Basics.edge(shiftPoints[k], shiftPoints[k + 1]) for k in range(n) ]
def clean(loop): ''' Takes a straightened, ordered loop and cleans it up by removing any colinear edges with shared endpoints which can be represented as single edges. Returns a straight ordered loop with such substitions made. NOTE FOR NEXT WORK: This appproach makes the handling of the first/last edge interface ugly. Rewrite to save chains as pairs of start and end indices, and not combine anything until all edges have been checked and no chains can be further extended. ''' chain = False startChain = None cleanLoop = [] nextIndex = range(len(loop))[1:]+[0] for i in range(len(loop)): #Look at edge i and edge i+1 act = loop[i] nex = loop[nextIndex[i]] if sp.allclose(act.dir[0],nex.dir[0]): #As this is an ordered loop, we know they share endpoints. Thus if they share dirs these two edges can be replaced by a single one. if not chain: #chain flag remembers whether act can form a single edge with one or more edges before it in the loop. #If chain is false, we're starting a new chain of replaceable edges and need to remember where it starts. startChain = act chain = True elif chain: #If act and nex can't chain together, we've reached the end of any chain we may be in, and should add it to the output. chain = False cleanLoop.append(Basics.edge(startChain.a,act.b)) else: #If we don't have an active chain going, we need to put act into the output as is, since it can't chain with either of its neighbors. cleanLoop.append(act) #handle the hanging stuff from the end of the loop if chain: #If at the end of the for loop the chain flag is still raised, the first edge in loop can be combined with the last edge, and potentially more before it. #Also, the first edge in cleanLoop is guaranteed to have the same dir and startpoint as the first edge in loop. Therefore, if chain, we should combine the first edge in cleanLoop with the active chain. cleanLoop.append(Basics.edge(startChain.a,cleanLoop[0].b)) cleanLoop = cleanLoop[1:] return cleanLoop
def straighten(layer): #Changes all the edges in layer so that if the vector from a to b is regarded as forward, the inside of mesh is always to the left. #layer is a list of edges outputted by mesh.chop. It is NOT a layer. newEdges = [] startLen = len(layer.borders) for edge in layer.borders: right = sp.cross(edge.dir[0],sp.array([0,0,1])) testPoint = edge.midpoint() - 0.0001 * right #A testpoint which is a miniscule distance to the left of the line. if layer.mesh.contains(testPoint): newEdges.append(edge) #print "Did not flip" else: #print "Flipped" newEdges.append(Basics.edge(edge.b,edge.a)) if startLen!=len(newEdges): print "straighten procedure has lost edges." layer.borders = newEdges
def edgeShift(self, e, u=1): ''' Returns edge e with its endpoints shifted vertically by their functional values*u. This does not interpolate at all, so large edges will have problems. ''' return Basics.edge(self.pointShift(e.a, u), self.pointShift(e.b, u))
def edgeShift(self, e, u=1): """ Returns edge e with its endpoints shifted vertically by their functional values*u. This does not interpolate at all, so large edges will have problems. """ return Basics.edge(self.pointShift(e.a, u), self.pointShift(e.b, u))