Beispiel #1
0
	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()
Beispiel #2
0
	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
Beispiel #3
0
 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()
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
	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
Beispiel #7
0
	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)
Beispiel #8
0
	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
Beispiel #9
0
    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
Beispiel #10
0
    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
Beispiel #11
0
	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)
Beispiel #12
0
	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
Beispiel #13
0
    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
Beispiel #14
0
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
Beispiel #15
0
class PocketIsland:
	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 eliminateOutsideIslands(self):
		self.insideIslandList = []
		for island in self.islands:
			for path in self.outpaths :
				if island.isPathInside(path)>=0:
					self.insideIslandList.append(island)

	def inoutprofile(self):
		if self.depth == 0:
			offset = -self.diameter / 2.0
		else:
			offset = -self.diameter*self.stepover
		self.OutOffsetPathList = []
		for path in self.outpaths :
			p1=p2=None
			if len(path)>0:
				p1 = path[0].A
			dir = path.direction()
			opath = path.offset(offset*float(dir))
			opath.intersectSelf()
			opath.removeExcluded(path, abs(offset))
			if len(opath)>0:
				p2 = opath[0].A
				self.OutOffsetPathList.append(opath)
				if self.depth >0  and p1 is not None:
					self.outPathG1SegList.append(Segment(Segment.LINE,p1,p2))
		self.islandOffPaths = []
		for island in self.insideIslandList :
			p3=p4=None
			if len(island)>0:
				p3 = island[0].A
			dir = island.direction()
			offIsl = island.offset(-offset*float(dir))
			if len(offIsl)>0:
				p4 = offIsl[0].A
			if self.depth >0 and p3 is not None and p4 is not None :
				self.islandG1SegList.append(Segment(Segment.LINE,p3,p4))
			offIsl.intersectSelf()
			offIsl.removeExcluded(island, abs(offset))
			self.islandOffPaths.append(offIsl)

	def interesect(self):
		self.IntersectedIslands = []
		for island in self.islandOffPaths :
			for path in self.OutOffsetPathList :
				path.intersectPath(island)
				island.intersectPath(path)
			for island2 in self.islandOffPaths :
				island.intersectPath(island2)
			self.IntersectedIslands.append(island)

	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 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 getNewPathAndIslands(self):
		if len(self.CleanPath)==1:
			self.childrenOutpath = self.CleanPath
		else :
			for elt in self.CleanPath: #List of paths
				for elt2 in self.CleanPath :
						ins = elt2.isPathInside(elt)==1
						ident = elt2.isidentical(elt)
						addedelt2  = elt2 in self.childrenIslands 
						if ins and not ident and not addedelt2 :
							self.childrenIslands.append(elt2)
			for elt in self.CleanPath: #List of paths
				for elt2 in self.CleanPath:
						if not elt2 in self.childrenIslands and not elt2 in self.childrenOutpath:
							self.childrenOutpath.append(elt2)

	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:
				self.CleanPath.append(self.outPathG1SegList)
			self.fullpath.extend(self.CleanPath)
		return self.CleanPath

	def recurse(self):
		pcket = PocketIsland(self.childrenOutpath,self.allowG1,self.diameter,self.stepover,self.depth+1,self.childrenIslands)
		self.fullpath.extend(pcket.getfullpath())

	def getfullpath(self) :
		return self.fullpath
Beispiel #16
0
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
Beispiel #17
0
	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
Beispiel #18
0
class PocketIsland:
	def __init__(self,pathlist,RecursiveDepth,ProfileDir,CutDir,AdditionalCut, Overcuts,CustomRecursiveDepth,
				ignoreIslands,
				allowG1,diameter,stepover,depth,app,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
		self.app = app
		maxdepthchoice = {"Single profile":0,
						"Custom offset count":int(self.CustomRecursiveDepth-1),
						"Full pocket":100}
		profileDirChoice = {"inside":1.,"outside":-1.}
		cutDirChoice = {False:1.,True:-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)
		sys.setrecursionlimit(max(sys.getrecursionlimit(),maxdepth+1))
		if depth>maxdepth: return None
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> eliminateOutsideIslands",True)
		self.eliminateOutsideIslands()
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> inoutprofile",True)
		self.inoutprofile()
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> removeOutofProfileLinkingSegs",True)
		self.removeOutofProfileLinkingSegs()
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> interesect",True)
		self.interesect()
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> removeOutOfProfile",True)
		self.removeOutOfProfile()
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> removeInsideIslands",True)
		self.removeInsideIslands()
		self.app.setStatus(_("Generate pocket path")+" - depth:"+str(self.depth+1)+" -> getNewPathAndIslands",True)
		self.getNewPathAndIslands()
		self.getPaths()
		if len (self.CleanPath)>0:
			self.recurse()

	def eliminateOutsideIslands(self):
		self.insideIslandList = []
		for island in self.islands:
			for path in self.outpaths :
				if island.isPathInside(path)>=0:
					self.insideIslandList.append(island)

	def inoutprofile(self):
		if self.depth == 0:
			self.offset = -self.diameter / 2.0 +self.AdditionalCut
			self.offsetLastPass = self.offset
		else:
			self.offset = -self.diameter*self.stepover
			self.offsetLastPass = -min(self.diameter*self.stepover/2.,self.diameter*0.49)
		self.OutOffsetPathList = []
		for path in self.outpaths :
			p1=p2=None
			if len(path)>0:
				p1 = path[0].A
			if self.depth == 0 :
				path.directionSet(self.selectCutDir*float(self.profiledir))
			direct = path.direction()
			opathCopy = path.offset(self.profiledir*self.offset*float(direct))
			points = opathCopy.intersectSelf()
			opathCopy.removeExcluded(path, abs(self.offset))
			if  len(opathCopy)>0: #there remains some path after full offset : not the last pass
				opath = path.offset(self.profiledir*self.offset*float(direct))
				offset = self.offset
			else:# nothing remaining after the last pass => apply offsetLastPass
				opath = path.offset(self.profiledir*self.offsetLastPass*float(direct))
				offset = self.offsetLastPass
			opath.intersectSelf()
			if len (opath)>0 :
				opath.removeExcluded(path, abs(offset))
			opath.removeZeroLength(abs(self.diameter)/100.)
# 			opath.removeZeroLength(abs(EPS*10.))
			opath.convert2Lines(abs(self.diameter)/10.)
			if self.depth == 0 and self.Overcuts :
				opath.overcut(self.profiledir*self.offset*float(direct))
			if len(opath)>0:
				p2 = opath[0].A
				self.OutOffsetPathList.append(opath)
				if self.depth >0  and p1 is not None:
					self.outPathG1SegList.append(Segment(Segment.LINE,p1,p2))
		self.islandOffPaths = []
		for island in self.insideIslandList :
			p3=p4=None
			if len(island)>0:
				p3 = island[0].A
			if self.depth == 0 :
				island.directionSet(-self.selectCutDir*float(self.profiledir))
			direct = island.direction()
			offIsl = island.offset(-self.profiledir*self.offset*float(direct))
			offIsl.intersectSelf()
			if len(offIsl)>0 :
				offIsl.removeExcluded(island, abs(self.offset))
			offIsl.removeZeroLength(abs(self.diameter)/100.)
# 			offIsl.removeZeroLength(abs(EPS*10.))
			offIsl.convert2Lines(abs(self.diameter)/10.)
			if len(offIsl)>0:
				p4 = offIsl[0].A
			if self.depth >0 and p3 is not None and p4 is not None :
				self.islandG1SegList.append(Segment(Segment.LINE,p3,p4))
			if self.depth == 0 and self.Overcuts :
				offIsl.overcut(-self.profiledir*self.offset*float(direct))
			self.islandOffPaths.append(offIsl)

	def removeOutofProfileLinkingSegs(self):
		self.tmpoutG1 = deepcopy(self.outPathG1SegList)
		self.tmpinG1 = deepcopy(self.islandG1SegList)
		for i,seg in enumerate(self.outPathG1SegList) :
			for path in self.islandOffPaths :
				inside =path.isSegInside(seg)==1#outseg inside offsetislands =>pop
				if  inside and seg in self.tmpoutG1:
					self.tmpoutG1.remove(seg)
		for i,seg in enumerate(self.islandG1SegList):
			for path in self.OutOffsetPathList :
				outside = path.isSegInside(seg)<1#inseg outside offsetOutpaths => pop
				if outside and  seg in self.tmpinG1 : 
						self.tmpinG1.remove(seg)
		self.outPathG1SegList = self.tmpoutG1
		self.islandG1SegList = self.tmpinG1

	def interesect(self):
		self.IntersectedIslands = []
		for island in self.islandOffPaths :
			for path in self.OutOffsetPathList :
				path.intersectPath(island)
				island.intersectPath(path)
			for island2 in self.islandOffPaths :
				island.intersectPath(island2)
			self.IntersectedIslands.append(island)

	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 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 getNewPathAndIslands(self):
		if len(self.CleanPath)==1:
			self.childrenOutpath = self.CleanPath
		else :
			for elt in self.CleanPath: #List of paths
				for elt2 in self.CleanPath :
						ins = elt2.isPathInside(elt)==1
						ident = elt2.isidentical(elt)
						addedelt2  = elt2 in self.childrenIslands 
						if ins and not ident and not addedelt2 :
							self.childrenIslands.append(elt2)
			for elt in self.CleanPath: #List of paths
				for elt2 in self.CleanPath:
						if not elt2 in self.childrenIslands and not elt2 in self.childrenOutpath:
							self.childrenOutpath.append(elt2)

	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 recurse(self):
		pcket = PocketIsland(self.childrenOutpath,self.RecursiveDepth,self.ProfileDir,
							self.CutDir,self.AdditionalCut,self.Overcuts, self.CustomRecursiveDepth,
							self.ignoreIslands,
							self.allowG1,self.diameter,self.stepover,self.depth+1,self.app,self.childrenIslands)
		self.fullpath.extend(pcket.getfullpath())

	def getfullpath(self) :
		return self.fullpath