def __init__(self,pathlist,allowG1,diameter,stepover,depth,islandslist=[]): self.outpaths = pathlist self.islands = islandslist self.diameter = diameter self.stepover = stepover self.childrenIslands = [] self.childrenOutpath = [] self.children = [] self.fullpath = [] self.depth = depth self.islandG1SegList = Path("islandG1SegList") self.outPathG1SegList = Path("outPathG1SegList") self.allowG1 = allowG1 maxdepth=100 import sys sys.setrecursionlimit(max(sys.getrecursionlimit(),maxdepth+100)) if depth>maxdepth: return None self.eliminateOutsideIslands() self.inoutprofile() self.interesect() self.removeOutOfProfile() self.removeInsideIslands() self.getNewPathAndIslands() self.getPaths() if len (self.CleanPath)>0: self.recurse()
def __init__(self, pathlist, RecursiveDepth, ProfileDir, CutDir, AdditionalCut, Overcuts, CustomRecursiveDepth, ignoreIslands, allowG1, diameter, stepover, depth, islandslist=[]): self.outpaths = pathlist self.islands = islandslist self.diameter = diameter self.stepover = stepover self.RecursiveDepth = RecursiveDepth self.ProfileDir = ProfileDir self.CutDir = CutDir self.AdditionalCut = float(AdditionalCut) self.Overcuts = bool(Overcuts) self.CustomRecursiveDepth = CustomRecursiveDepth self.childrenIslands = [] self.childrenOutpath = [] self.fullpath = [] self.depth = depth self.islandG1SegList = Path("islandG1SegList") self.outPathG1SegList = Path("outPathG1SegList") self.ignoreIslands = ignoreIslands self.allowG1 = allowG1 maxdepthchoice = { "Single profile": 0, "Custom recursive depth": int(self.CustomRecursiveDepth - 1), "Full pocket": 100 } profileDirChoice = {"inside": 1., "outside": -1.} cutDirChoice = {"conventional milling": 1., "climbing milling": -1.} self.selectCutDir = cutDirChoice.get(self.CutDir, 1.) self.profiledir = profileDirChoice.get(self.ProfileDir, 1.) if self.RecursiveDepth == "Full pocket": self.profiledir = 1. #to avoid making full pockets, with full recursive depth, outside the path maxdepth = maxdepthchoice.get(self.RecursiveDepth, 0) maxdepth = min(maxdepth, 999) import sys sys.setrecursionlimit(max(sys.getrecursionlimit(), maxdepth + 1)) if depth > maxdepth: return None self.eliminateOutsideIslands() self.inoutprofile() self.removeOutofProfileLinkingSegs() self.interesect() self.removeOutOfProfile() self.removeInsideIslands() self.getNewPathAndIslands() self.getPaths() if len(self.CleanPath) > 0: self.recurse()
def toPath(self, bid): """convert a block to path""" block = OCV.blocks[bid] paths = [] path = Path(block.name()) self.initPath(bid) start = bmath.Vector(self.cnc.x, self.cnc.y) # get only first path that enters the surface # ignore the deeper ones passno = 0 for line in block: # flatten helical paths line = re.sub(r"\s?z-?[0-9\.]+", "", line) # break after first depth pass if line == "( ---------- cut-here ---------- )": passno = 0 if path: paths.append(path) path = Path(block.name()) if line[:5] == "(pass": passno += 1 if passno > 1: continue cmds = Heuristic.parse_line(line) if cmds is None: continue self.cnc.motionStart(cmds) end = bmath.Vector(self.cnc.xval, self.cnc.yval) if self.cnc.gcode == 0: # rapid move (new block) if path: paths.append(path) path = Path(block.name()) elif self.cnc.gcode == 1: # line if self.cnc.dx != 0.0 or self.cnc.dy != 0.0: path.append(Segment(1, start, end)) elif self.cnc.gcode in (2, 3): # arc xc, yc = self.cnc.motionCenter() center = bmath.Vector(xc, yc) path.append(Segment(self.cnc.gcode, start, end, center)) self.cnc.motionEnd() start = end if path: paths.append(path) return paths
def pathBoolIntersection(self, basepath, islandpath): #basepath = deepcopy(basepath) #islandpath = deepcopy(islandpath) #find first intersecting segment first = None for i, segment in enumerate(islandpath): if basepath.isInside(segment.midPoint()): first = i if first is None: print("not intersecting paths") return None #generate intersected path newisland = Path("new") A = None for i in xrange(first, 2 * len(islandpath) + first): j = i % len(islandpath) segment = islandpath[j] if segment.length() < EPS: continue #ignore zero length segments if not basepath.isInside(segment.midPoint()): if A is None: A = segment.A else: if A is not None: newisland.extend(self.findSubpath(basepath, A, segment.A)) print("new", newisland) A = None newisland.append(segment) #for i,seg in enumerate(newisland): # newisland[i].correct(); print("new2", newisland) return newisland
def getPaths(self): if len (self.CleanPath)>0: if len(self.islandG1SegList) >0 : self.outPathG1SegList.extend(self.islandG1SegList) if self.allowG1 and len(self.outPathG1SegList)>0: for seg in self.outPathG1SegList : path = Path("SegPath") path.append(seg) self.CleanPath.append(path) self.fullpath.extend(self.CleanPath) return self.CleanPath
def execute(self, app): #print("go!") blocks = [] paths_base = [] paths_isl = [] for bid in app.editor.getSelectedBlocks(): if app.gcode[bid].operationTest('island'): paths_isl.extend(app.gcode.toPath(bid)) else: paths_base.extend(app.gcode.toPath(bid)) for island in paths_isl: paths_newbase = [] while len(paths_base) > 0: base = paths_base.pop() base.intersectPath(island) island.intersectPath(base) newbase = Path("diff") #Add segments from outside of islands: for i, seg in enumerate(base): if not island.isInside(seg.midPoint()): newbase.append(seg) #Add segments from islands to base for i, seg in enumerate(island): if base.isInside(seg.midPoint( )): #and base.isInside(seg.A) and base.isInside(seg.B): newbase.append(seg) #Eulerize paths_newbase.extend(newbase.eulerize()) #paths_newbase.extend(newbase.split2contours()) paths_base = paths_newbase for base in paths_base: print(base) #base = base.eulerize(True) block = Block("diff") block.extend(app.gcode.fromPath(base)) blocks.append(block) #active = app.activeBlock() app.gcode.insBlocks( -1, blocks, "Diff") #<<< insert blocks over active block in the editor app.refresh() #<<< refresh editor app.setStatus(_("Generated: Diff")) #<<< feed back result
def removeOutOfProfile(self): self.NewPaths = [] newoutpath = Path("path") for path in self.OutOffsetPathList: for seg in path: newoutpath.append(seg) for OutoffsetPath in self.OutOffsetPathList: for path in self.IntersectedIslands : for seg in path : inside = not OutoffsetPath.isSegInside(seg)==-1 if inside: newoutpath.append(seg) purgednewoutpath= newoutpath.split2contours()#list of paths self.NewPaths.extend(purgednewoutpath)
def _findSubpath(self, path, A, B): print("finding", A, B) sub = None for i in xrange(0, len(path) * 2): #iterate twice with wrap around j = i % len(path) seg = path[j] if eq(seg.A, A): sub = Path("subp") print("seg", sub is None, seg) if sub is not None: sub.append(seg) if eq(seg.B, B): break print("found", sub) return sub
def removeInsideIslands(self): self.CleanPath = [] cleanpath = Path("Path") for path in self.NewPaths : for seg in path : inside = False for island in self.IntersectedIslands : issegin = island.isSegInside(seg)==1 if issegin: if not seg in island: inside = True break if not inside: cleanpath.append(seg) cleanpath = cleanpath.split2contours() self.CleanPath.extend(cleanpath)
def pocket(selectedblocks, RecursiveDepth,ProfileDir,CutDir,AdditionalCut,Overcuts, CustomRecursiveDepth, ignoreIslands, allowG1, diameter, stepover, name,gcode,app): undoinfo = [] msg = "" newblocks = [] allblocks = gcode.blocks islandslist = [] outpathslist= [] ignoreIslandschoicedict = { "Regard all islands except tabs":0, "Ignore all islands":1, "Regard only selected islands":2, } ignoreIslandschoice = ignoreIslandschoicedict.get(ignoreIslands,0) for bid,block in enumerate(allblocks):#all blocks if block.operationTest('island')and not block.operationTest('tab'): if ignoreIslandschoice==0: for islandPath in gcode.toPath(bid): islandslist.append(islandPath) for bid in reversed(selectedblocks):#selected blocks if allblocks[bid].name() in ("Header", "Footer"): continue newpath = [] block = allblocks[bid] if block.operationTest('island')and not block.operationTest('tab') and ignoreIslandschoice==2: for islandPath in gcode.toPath(bid): islandslist.append(islandPath) for path in gcode.toPath(bid): if not path.isClosed(): m = "Path: '%s' is OPEN"%(path.name) if m not in msg: if msg: msg += "\n" msg += m path.close() # Remove tiny segments path.removeZeroLength(abs(diameter)/100.) # Convert very small arcs to lines path.convert2Lines(abs(diameter)/10.) if not block.operationTest('island'): outpathslist.append(path) MyPocket = PocketIsland(outpathslist,RecursiveDepth,ProfileDir,CutDir,AdditionalCut, Overcuts,CustomRecursiveDepth, ignoreIslands, allowG1,diameter,stepover,0,app,islandslist) newpathList = MyPocket.getfullpath() #concatenate newpath in a single list and split2contours if allowG1 : MyFullPath = Path("Pocket") for path in newpathList : for seg in path: MyFullPath.append(seg) newpathList = MyFullPath.split2contours() if newpathList: # remember length to shift all new blocks # the are inserted before before = len(newblocks) undoinfo.extend(gcode.importPath(bid+1, newpathList, newblocks, True, False)) new = len(newblocks)-before for i in range(before): newblocks[i] += new allblocks[bid].enable = False gcode.addUndo(undoinfo) # return new blocks inside the blocks list del selectedblocks[:] selectedblocks.extend(newblocks) return msg
def execute(self, app): dragoff = self.fromMm("offset") angleth = self["angle"] swivelz = self.fromMm("swivelz") initdir = self["initdir"] CNC.vars["cutfeed"] = self.fromMm("feed") simulate = self["simulate"] simpreci = self["simpreci"] def initPoint(P, dir, offset): P = Vector(P[0], P[1]) if dir == 'X+': P[0] += offset elif dir == 'X-': P[0] -= offset elif dir == 'Y+': P[1] += offset elif dir == 'Y-': P[1] -= offset return P blocks = [] for bid in app.editor.getSelectedBlocks(): if len(app.gcode.toPath(bid)) < 1: continue opath = app.gcode.toPath(bid)[0] npath = Path("dragknife %s: %s" % (dragoff, app.gcode[bid].name())) if not simulate: #Entry vector ventry = Segment(Segment.LINE, initPoint(opath[0].A, initdir, -dragoff), opath[0].A) #Exit vector vexit = Segment(Segment.LINE, opath[-1].B, initPoint(opath[-1].B, initdir, dragoff)) opath.append(vexit) prevseg = ventry #Generate path with tangential lag for dragknife operation for i, seg in enumerate(opath): #Get adjacent tangential vectors in this point TA = prevseg.tangentEnd() TB = seg.tangentStart() #Compute difference between tangential vectors of two neighbor segments angle = degrees(acos(TA.dot(TB))) #Compute swivel direction arcdir = (TA[0] * TB[1]) - (TA[1] * TB[0]) if arcdir < 0: arcdir = Segment.CW else: arcdir = Segment.CCW #Append swivel if needed (also always do entry/exit) if abs(angle) > angleth or (abs(angle) > 1 and (i == 0 or i == len(opath) - 1)): arca = Segment(arcdir, prevseg.tangentialOffset(dragoff).B, seg.tangentialOffset(dragoff).A, prevseg.B) if swivelz != 0: arca._inside = [swivelz] npath.append(arca) #Append segment with tangential offset if i < len(opath) - 1: npath.append(seg.tangentialOffset(dragoff)) prevseg = seg elif simulate: opath = opath.linearize(simpreci, True) prevknife = initPoint(opath[0].A, initdir, -dragoff) for seg in opath: dist = sqrt((seg.B[0] - prevknife[0])**2 + (seg.B[1] - prevknife[1])**2) move = (seg.B - prevknife).unit() * (dist - dragoff) newknife = prevknife + move if not eq(newknife, prevknife): npath.append(Segment(Segment.LINE, prevknife, newknife)) prevknife = newknife eblock = app.gcode.fromPath(npath) blocks.append(eblock) #active = app.activeBlock() #if active == 0: active+=1 active = -1 #add to end app.gcode.insBlocks( active, blocks, "Dragknife") #<<< insert blocks over active block in the editor app.refresh() #<<< refresh editor app.setStatus(_("Generated: Dragknife")) #<<< feed back result
def pocket(blocks, allowG1, diameter, stepover, name,gcode,items): undoinfo = [] msg = "" newblocks = [] islandslist = [] for bid,block in enumerate(gcode.blocks): if block.operationTest('island'): for islandPath in gcode.toPath(bid): islandslist.append(islandPath) for bid in reversed(blocks): if gcode.blocks[bid].name() in ("Header", "Footer"): continue newpath = [] for path in gcode.toPath(bid): if not path.isClosed(): m = "Path: '%s' is OPEN"%(path.name) if m not in msg: if msg: msg += "\n" msg += m path.close() # Remove tiny segments path.removeZeroLength(abs(diameter)/100.) # Convert very small arcs to lines path.convert2Lines(abs(diameter)/10.) path.directionSet(1) #turn path to CW (conventional when milling inside) D = path.direction() if D==0: D=1 remove = ["cut","reverse","climb","conventional","cw","ccw","pocket"] if name is None: path.name = Block.operationName(path.name, "pocket,conventional,cw", remove) else: path.name = Block.operationName(path.name, name, remove) MyPocket = PocketIsland([path],allowG1,diameter,stepover,0,islandslist) newpathList = MyPocket.getfullpath() #concatenate newpath in a single list and split2contours if allowG1 : MyFullPath = Path("Pocket") for path in newpathList : for seg in path: MyFullPath.append(seg) newpathList = MyFullPath.split2contours() if newpathList: # remember length to shift all new blocks # the are inserted before before = len(newblocks) undoinfo.extend(gcode.importPath(bid+1, newpathList, newblocks, True, False)) new = len(newblocks)-before for i in range(before): newblocks[i] += new gcode.blocks[bid].enable = False gcode.addUndo(undoinfo) # return new blocks inside the blocks list del blocks[:] blocks.extend(newblocks) return msg