Exemple #1
0
    def execute(self, app):
        rdoc = self["rdoc"]
        radius = self["dia"] / 2
        cw = self["cw"]

        #print("go!")
        blocks = []
        for bid in app.editor.getSelectedBlocks():
            #print(blocks[bid])
            path = app.gcode.toPath(bid)[0]
            #print(path)

            block = Block("trochoid")

            for segment in path:
                #print(segment.A)
                #block.append("g0 x0 y0")
                #block.append("g1 x10 y10")
                #block.append("g1 x20 y10")
                #block.append("g0 x0 y0")
                block.extend(self.trochoid(segment, rdoc, radius, cw))

            blocks.append(block)

        active = app.activeBlock()
        app.gcode.insBlocks(
            active, blocks, "Trochoidal created"
        )  #<<< insert blocks over active block in the editor
        app.refresh()  #<<< refresh editor
        app.setStatus(_("Generated: Trochoidal"))  #<<< feed back result
Exemple #2
0
	def calc(self,x,y,depth,peck,dwell,drillFeed,safeZforG0):
		self.safeZforG0 =float(abs(safeZforG0))
		peck=abs(float(peck))
		currentz=0.0
		self.blocks = []
		self.block = Block(self.name)
		self.block.append(CNC.grapid(x=x,y=y))
		self.block.append(CNC.grapid(z=CNC.vars["safe"]))
		self.accelerateIfNeeded(0.0,drillFeed)
		self.block.append("(entered)")
		while(currentz>depth):
			currentz-=peck
			if currentz < depth:
				currentz = depth
			kwargs={"f":float(drillFeed)}
			self.block.append(CNC.gline(None,None,float(currentz),**kwargs))
			if self.safeZforG0 >0:
				self.block.append(CNC.grapid(z=0.0+self.safeZforG0))
			else :
				self.block.append(CNC.grapid(z=CNC.vars["safe"]))
			self.block.append("g4 %s"%(CNC.fmt("p",float(dwell))))
			if currentz > depth:
				self.accelerateIfNeeded(currentz,drillFeed)
		self.block.append("(exiting)")
		self.block.append(CNC.grapid(z=CNC.vars["safe"]))
		self.blocks.append(self.block)
		return self.blocks
Exemple #3
0
    def slice(self, verts, faces, z, zout=None):
        block = Block("slice %f" % (float(z)))

        #FIXME: slice along different axes
        plane_orig = (0, 0, z)  #z height to slice
        plane_norm = (0, 0, 1)

        #Crosscut
        contours = meshcut.cross_section(verts, faces, plane_orig, plane_norm)

        #Flatten contours
        if zout is not None:
            for contour in contours:
                for segment in contour:
                    segment[2] = zout

        #Contours to G-code
        for contour in contours:
            #print(contour)
            first = contour[0]
            block.append("g0 x%f y%f z%f" % (first[0], first[1], first[2]))
            for segment in contour:
                block.append("g1 x%f y%f z%f" %
                             (segment[0], segment[1], segment[2]))
            block.append("g1 x%f y%f z%f" % (first[0], first[1], segment[2]))
            block.append("( ---------- cut-here ---------- )")
        if block: del block[-1]

        if not block: block = None
        return block
Exemple #4
0
	def insertBlock(self, event=None):
		active = self.index(ACTIVE)
		if self._items:
			bid, lid = self._items[active]
			bid += 1
		else:
			bid = 0

		block = Block()
		block.expand = True
		block.append("g0 x0 y0")
		block.append("g1 z0")
		block.append(CNC.zsafe())
		self.gcode.addUndo(self.gcode.addBlockUndo(bid,block))
		self.selection_clear(0,END)
		self.fill()
		# find location of new block
		while active < self.size():
			if self._items[active][0] == bid:
				break
			active += 1
		self.selection_set(active)
		self.see(active)
		self.activate(active)
		self.edit()
		self.winfo_toplevel().event_generate("<<Modified>>")
Exemple #5
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
Exemple #6
0
	def insertBlock(self, event=None):
		active = self.index(ACTIVE)
		if self._items:
			bid, lid = self._items[active]
			bid += 1
		else:
			bid = 0

		block = Block()
		block.expand = True
		block.append("G0 X0 Y0")
		block.append("G1 Z0")
		block.append(CNC.zsafe())
		self.gcode.addUndo(self.gcode.addBlockUndo(bid,block))
		self.selection_clear(0,END)
		self.fill()
		# find location of new block
		while active < self.size():
			if self._items[active][0] == bid:
				break
			active += 1
		self.selection_set(active)
		self.see(active)
		self.activate(active)
		self.edit()
		self.app.event_generate("<<Modified>>")
Exemple #7
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
Exemple #8
0
	def joinBlocks(self, event=None):
		if not self._items: return
		all_items = self._items
		sel_items = list(map(int,self.curselection()))
		change = True
		bl = Block(self.gcode[sel_items[0]].name())
		for bid in sel_items:
			for line in self.gcode[bid]:
				bl.append(line)
			bl.append("( ---------- cut-here ---------- )")
		del bl[-1]
		self.gcode.addUndo(self.gcode.addBlockUndo(bid+1,bl))
		if change: self.fill()
		self.deleteBlock()
		self.winfo_toplevel().event_generate("<<Modified>>")
Exemple #9
0
    def execute(self, app):
        preci = self.fromMm("preci")
        linpreci = self.fromMm("linpreci")
        numseg = self["numseg"]

        #print("go!")
        blocks = []
        for bid in app.editor.getSelectedBlocks():
            if len(app.gcode.toPath(bid)) < 1: continue

            #nblock = Block("flat "+app.gcode[bid].name())
            #for i in app.gcode[bid]:
            #	nblock.append(re.sub(r"\s?z-?[0-9\.]+","",i))
            #blocks.append(nblock)

            eblock = Block("fit " + app.gcode[bid].name())
            npath = app.gcode.toPath(bid)[0]
            npath = npath.mergeLines(linpreci)
            npath = npath.arcFit(preci, numseg)
            if npath.length() <= 0:
                #FIXME: not sure how this could happen
                print("Warning: ignoring zero length path!")
                continue
            eblock = app.gcode.fromPath(npath, eblock)
            blocks.append(eblock)

        #active = app.activeBlock()
        #if active == 0: active+=1
        active = -1  #add to end
        app.gcode.insBlocks(
            active, blocks,
            "Arc fit")  #<<< insert blocks over active block in the editor
        app.refresh()  #<<< refresh editor
        app.setStatus(_("Generated: Arc fit"))  #<<< feed back result
Exemple #10
0
	def execute(self, app):
		maxseg = self.fromMm("maxseg")
		splitlines = self["splitlines"]

		#print("go!")
		blocks  = []
		for bid in app.editor.getSelectedBlocks():
			if len(app.gcode.toPath(bid)) < 1: continue

			#nblock = Block("flat "+app.gcode[bid].name())
			#for i in app.gcode[bid]:
			#	nblock.append(re.sub(r"\s?z-?[0-9\.]+","",i))
			#blocks.append(nblock)

			eblock = Block("lin "+app.gcode[bid].name())
			opath = app.gcode.toPath(bid)[0]
			npath = opath.linearize(maxseg, splitlines)
			eblock = app.gcode.fromPath(npath,eblock)
			blocks.append(eblock)



		#active = app.activeBlock()
		#if active == 0: active+=1
		active=-1 #add to end
		app.gcode.insBlocks(active, blocks, "Linearized") #<<< insert blocks over active block in the editor
		app.refresh()                                                                                           #<<< refresh editor
		app.setStatus(_("Generated: Linearize"))                           #<<< feed back result
Exemple #11
0
	def make(self):
		d = self.thick

		# Convert to external dimensions
		if self.dx<0:
			dx = -self.dx - d*2	# external to internal
		else:
			dx = self.dx

		if self.dy<0:
			dy = -self.dy - d*2	# external to internal
		else:
			dy = self.dy

		if self.dz<0:
			dz = -self.dz - d*2	# external to internal
		else:
			dz = self.dz

		blocks = []
		block = Block("%s-Bottom"%(self.name))
		block.append("(Box: %g x %g x %g)"%(self.dx,self.dy,self.dz))
		block.append("(Fingers: %d x %d x %d)"%(self.nx,self.ny,self.nz))
		self._rectangle(block, 0.,-d, dx,dy, self.nx,-self.ny, 0,d)
		blocks.append(block)

		block = Block("%s-Left"%(self.name))
		self._rectangle(block, -(dz+5*d),-d, dz,dy, self.nz,self.ny, d,d)
		blocks.append(block)

		block = Block("%s-Right"%(self.name))
		self._rectangle(block, dx+3*d,-d, dz,dy, self.nz,self.ny, d,d)
		blocks.append(block)

		block = Block("%s-Front"%(self.name))
		self._rectangle(block, 0,-(dz+4*d), dx,dz, -self.nx,-self.nz, 0,0)
		blocks.append(block)

		block = Block("%s-Back"%(self.name))
		self._rectangle(block, 0,dy+4*d, dx,dz, -self.nx,-self.nz, 0,0)
		blocks.append(block)

		block = Block("%s-Top"%(self.name))
		self._rectangle(block, dx+dz+8*d,-d, dx,dy, self.nx,-self.ny, 0,d)
		blocks.append(block)
		return blocks
Exemple #12
0
	def splitBlocks(self, event=None):
		if not self._items: return
		all_items = self._items
		sel_items = list(map(int,self.curselection()))
		change = True
		newblocks = []
		for bid in sel_items:
			bl = Block(self.gcode[bid].name())
			for line in self.gcode[bid]:
				if line == "( ---------- cut-here ---------- )":
					#newblocks.append(bl)
					#self.insertBlock(bl)
					self.gcode.addUndo(self.gcode.addBlockUndo(bid+1,bl))
					bl = Block(self.gcode[bid].name())
				else:
					bl.append(line)
		self.gcode.addUndo(self.gcode.addBlockUndo(bid+1,bl))
		#newblocks.append(bl)
		#self.gcode.extend(newblocks)
		if change: self.fill()
		self.deleteBlock()
		self.winfo_toplevel().event_generate("<<Modified>>")
Exemple #13
0
    def slice(self, verts, faces, z, zout=None, axis='z'):
        tags = '[slice]'
        if axis == 'z': tags = '[slice,minz:%f]' % (float(z))
        block = Block("slice %s%f %s" % (axis, float(z), tags))

        #FIXME: slice along different axes
        if axis == 'x':
            plane_orig = (z, 0, 0)
            plane_norm = (1, 0, 0)
        elif axis == 'y':
            plane_orig = (0, z, 0)
            plane_norm = (0, 1, 0)
        else:
            plane_orig = (0, 0, z)  #z height to slice
            plane_norm = (0, 0, 1)

        #Crosscut
        contours = meshcut.cross_section(verts, faces, plane_orig, plane_norm)

        #Flatten contours
        if zout is not None:
            for contour in contours:
                for segment in contour:
                    segment[2] = zout

        #Contours to G-code
        for contour in contours:
            #print(contour)
            first = contour[0]
            block.append("g0 x%f y%f z%f" % (first[0], first[1], first[2]))
            for segment in contour:
                block.append("g1 x%f y%f z%f" %
                             (segment[0], segment[1], segment[2]))
            block.append("g1 x%f y%f z%f" % (first[0], first[1], segment[2]))
            block.append("( ---------- cut-here ---------- )")
        if block: del block[-1]

        if not block: block = None
        return block
Exemple #14
0
	def execute(self, app):
		#print("go!")
		blocks  = []

		bid = app.editor.getSelectedBlocks()[0]
		xbasepath = app.gcode.toPath(bid)[0]

		bid = app.editor.getSelectedBlocks()[1]
		xislandpath = app.gcode.toPath(bid)[0]

		xbasepath.intersectPath(xislandpath)
		xislandpath.intersectPath(xbasepath)

		#xnewisland = self.pathBoolIntersection(xbasepath, xislandpath)
		xnewisland = self.pathBoolIntersection(xislandpath, xbasepath)

		#pth = Path("temp")
		#basepath.invert()
		#pth.extend(basepath)
		#pth.extend(basepath)
		##pth.invert()


		block = Block("intersect")
		block.extend(app.gcode.fromPath(xnewisland))
		blocks.append(block)

		#block = Block("diff")
		#block.extend(app.gcode.fromPath(pth))
		#blocks.append(block)


		active = app.activeBlock()
		app.gcode.insBlocks(active, blocks, "Intersect") #<<< insert blocks over active block in the editor
		app.refresh()                                                                                           #<<< refresh editor
		app.setStatus(_("Generated: Intersect"))                           #<<< feed back result
Exemple #15
0
    def execute(self, app):
        #print("go!")
        blocks = []

        bid = app.editor.getSelectedBlocks()[0]
        xbasepath = app.gcode.toPath(bid)[0]

        bid = app.editor.getSelectedBlocks()[1]
        xislandpath = app.gcode.toPath(bid)[0]

        xbasepath.intersectPath(xislandpath)
        xislandpath.intersectPath(xbasepath)

        #xnewisland = self.pathBoolIntersection(xbasepath, xislandpath)
        xnewisland = self.pathBoolIntersection(xislandpath, xbasepath)

        #pth = Path("temp")
        #basepath.invert()
        #pth.extend(basepath)
        #pth.extend(basepath)
        ##pth.invert()

        block = Block("diff")
        block.extend(app.gcode.fromPath(xnewisland))
        blocks.append(block)

        #block = Block("diff")
        #block.extend(app.gcode.fromPath(pth))
        #blocks.append(block)

        active = app.activeBlock()
        app.gcode.insBlocks(
            active, blocks,
            "Diff")  #<<< insert blocks over active block in the editor
        app.refresh()  #<<< refresh editor
        app.setStatus(_("Generated: Diff"))  #<<< feed back result
Exemple #16
0
    def execute(self, app):
        blocks = []
        for bid in app.editor.getSelectedBlocks():
            if len(app.gcode.toPath(bid)) < 1: continue

            eblock = Block("closed " + app.gcode[bid].name())
            for path in app.gcode.toPath(bid):
                if not path.isClosed():
                    path.append(Segment(Segment.LINE, path[-1].B, path[0].A))
                eblock = app.gcode.fromPath(path, eblock)
            #blocks.append(eblock)
            app.gcode[bid] = eblock

        #active=-1 #add to end
        #app.gcode.insBlocks(active, blocks, "Path closed") #<<< insert blocks over active block in the editor
        app.refresh()  #<<< refresh editor
        app.setStatus(_("Generated: Closepath"))  #<<< feed back result
Exemple #17
0
		def addLines(lines):
			for line in lines.splitlines():
				# Create a new block
				if self.__lid is None:
					self.__bid += 1
					self.__lid = MAXINT
					block = Block()
					undoinfo.append(self.gcode.addBlockUndo(self.__bid,block))
					selitems.append((self.__bid, None))
				else:
					block = self.gcode.blocks[self.__bid]

				if self.__lid == MAXINT:
					selitems.append((self.__bid, len(block)))
				else:
					self.__lid += 1
					selitems.append((self.__bid, self.__lid))
				undoinfo.append(self.gcode.insLineUndo(self.__bid, self.__lid, line))
Exemple #18
0
	def execute(self, app):
		#print("go!")
		blocks  = []
		for bid in app.editor.getSelectedBlocks():
			if len(app.gcode.toPath(bid)) < 1: continue
			path = app.gcode.toPath(bid)[0]
			x,y = path.center()
			eblock = Block("center of "+app.gcode[bid].name())
			eblock.append("G0 x"+str(x)+" y"+str(y))
			eblock.append("G1 Z0 F200")
			eblock.append("G0 Z10")
			blocks.append(eblock)


		#active = app.activeBlock()
		#if active == 0: active+=1
		active=-1 #add to end
		app.gcode.insBlocks(active, blocks, "Center created") #<<< insert blocks over active block in the editor
		app.refresh()                                                                                           #<<< refresh editor
		app.setStatus(_("Generated: Center"))                           #<<< feed back result
Exemple #19
0
 def execute(self, app):
     name = self["name"]
     if not name or name == "default":
         name = "Drillmark"
     marksize = self["Mark size"]
     x0 = self.fromMm("PosX")
     y0 = self.fromMm("PosY")
     marktype = self["Mark type"]
     block = Block(name + " %s diameter %s" %
                   (marktype, CNC.fmt("", marksize)))
     self.appendBurn(app, block)
     self.appendMark(app, block)
     active = app.activeBlock()
     if active == 0:
         active = 1
     blocks = [block]
     app.gcode.insBlocks(active, blocks, _("Manual drill mark"))
     app.refresh()  # <<< refresh editor
     app.setStatus(_("Generated: MyPlugin Result"))
Exemple #20
0
	def joinBlocks(self, event=None):
		if not self._items: return
		all_items = self._items
		sel_items = list(map(int,self.curselection()))
		change = True
		bl = Block(self.gcode[sel_items[0]].name())
		for bid in sel_items:
			for line in self.gcode[bid]:
				bl.append(line)
			bl.append("( ---------- cut-here ---------- )")
		del bl[-1]
		self.gcode.addUndo(self.gcode.addBlockUndo(bid+1,bl))
		if change: self.fill()
		self.deleteBlock()
		self.winfo_toplevel().event_generate("<<Modified>>")
Exemple #21
0
    def execute(self, app):
        #print("go!")
        blocks = []
        for bid in app.editor.getSelectedBlocks():
            if len(app.gcode.toPath(bid)) < 1: continue

            #nblock = Block("flat "+app.gcode[bid].name())
            #for i in app.gcode[bid]:
            #	nblock.append(re.sub(r"\s?z-?[0-9\.]+","",i))
            #blocks.append(nblock)

            eblock = Block("flat " + app.gcode[bid].name())
            eblock = app.gcode.fromPath(app.gcode.toPath(bid), eblock)
            blocks.append(eblock)

        #active = app.activeBlock()
        #if active == 0: active+=1
        active = -1  #add to end
        app.gcode.insBlocks(
            active, blocks, "Shape flattened"
        )  #<<< insert blocks over active block in the editor
        app.refresh()  #<<< refresh editor
        app.setStatus(_("Generated: Flat"))  #<<< feed back result
Exemple #22
0
	def slice(self, verts, faces, z, zout=None, axis='z'):
		tags = '[slice]'
		if axis=='z': tags = '[slice,minz:%f]'%(float(z))
		block = Block("slice %s%f %s"%(axis,float(z),tags))

		#FIXME: slice along different axes
		if axis == 'x':
			plane_orig = (z, 0, 0)
			plane_norm = (1, 0, 0)
		elif axis == 'y':
			plane_orig = (0, z, 0)
			plane_norm = (0, 1, 0)
		else:
			plane_orig = (0, 0, z) #z height to slice
			plane_norm = (0, 0, 1)

		#Crosscut
		contours = meshcut.cross_section(verts, faces, plane_orig, plane_norm)

		#Flatten contours
		if zout is not None:
			for contour in contours:
				for segment in contour:
					segment[2] = zout

		#Contours to G-code
		for contour in contours:
			#print(contour)
			gtype = 0
			for segment in contour:
				block.append("g%s x%f y%f z%f"%(gtype, segment[0],segment[1],segment[2]))
				gtype = 1
			block.append("g1 x%f y%f z%f"%(contour[0][0],contour[0][1],contour[0][2])) #Close shape
			block.append("( ---------- cut-here ---------- )")
		if block: del block[-1]

		if not block: block = None
		return block
Exemple #23
0
	def splitBlocks(self, event=None):
		if not self._items: return
		all_items = self._items
		sel_items = list(map(int,self.curselection()))
		change = True
		newblocks = []
		for bid in sel_items:
			bl = Block(self.gcode[bid].name())
			for line in self.gcode[bid]:
				if line == "( ---------- cut-here ---------- )":
					#newblocks.append(bl)
					#self.insertBlock(bl)
					self.gcode.addUndo(self.gcode.addBlockUndo(bid+1,bl))
					bl = Block(self.gcode[bid].name())
				else:
					bl.append(line)
		self.gcode.addUndo(self.gcode.addBlockUndo(bid+1,bl))
		#newblocks.append(bl)
		#self.gcode.extend(newblocks)
		if change: self.fill()
		self.deleteBlock()
		self.winfo_toplevel().event_generate("<<Modified>>")
Exemple #24
0
	def execute(self, app):
		try:
			import midiparser as midiparser
		except:
			app.setStatus(_("Error: This plugin requires midiparser.py"))
			return

		n = self["name"]
		if not n or n=="default": n="Midi2CNC"

		fileName = self["File"]

		x=0.0
		y=0.0
		z=0.0

		x_dir=1.0;
		y_dir=1.0;
		z_dir=1.0;

		# List of MIDI channels (instruments) to import.
		# Channel 10 is percussion, so better to omit it
		channels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] 

		axes = self["AxisUsed"]
		active_axes = len(axes)

		transpose = (0,0,0)
		ppu = [ 200, 200, 200 ]
		ppu[0] = self["ppu_X"]
		ppu[1] = self["ppu_X"]
		ppu[2] = self["ppu_X"]

		safemin = [ 0, 0, 0 ]
		safemax = [ 100, 100, 50 ]
		safemax[0] = self["max_X"]
		safemax[1] = self["max_Y"]
		safemax[2] = self["max_Z"]

		try:
			midi = midiparser.File(fileName)
		except:
			app.setStatus(_("Error: Sorry can't parse the Midi file."))
			return

		noteEventList=[]
		all_channels=set()

		for track in midi.tracks:
			#channels=set()
			for event in track.events:
				if event.type == midiparser.meta.SetTempo:
					tempo=event.detail.tempo

				# filter undesired instruments
				if ((event.type == midiparser.voice.NoteOn) and (event.channel in channels)):

					if event.channel not in channels:
						channels.add(event.channel)

					# NB: looks like some use "note on (vel 0)" as equivalent to note off, so check for vel=0 here and treat it as a note-off.
					if event.detail.velocity > 0:
						noteEventList.append([event.absolute, 1, event.detail.note_no, event.detail.velocity])
					else:
						noteEventList.append([event.absolute, 0, event.detail.note_no, event.detail.velocity])

				if (event.type == midiparser.voice.NoteOff) and (event.channel in channels):
					if event.channel not in channels:
						channels.add(event.channel)
					noteEventList.append([event.absolute, 0, event.detail.note_no, event.detail.velocity])

			# Finished with this track
			if len(channels) > 0:
				msg=', ' . join(['%2d' % ch for ch in sorted(channels)])
				#print 'Processed track %d, containing channels numbered: [%s ]' % (track.number, msg)
				all_channels = all_channels.union(channels)

		# List all channels encountered
		if len(all_channels) > 0:
			msg=', ' . join(['%2d' % ch for ch in sorted(all_channels)])
			#print 'The file as a whole contains channels numbered: [%s ]' % msg

		# We now have entire file's notes with abs time from all channels
		# We don't care which channel/voice is which, but we do care about having all the notes in order
		# so sort event list by abstime to dechannelify

		noteEventList.sort()
		# print noteEventList
		# print len(noteEventList)

		last_time=-0
		active_notes={} # make this a dict so we can add and remove notes by name

		# Start the output
		#Init blocks
		blocks = []
		block = Block(self.name)
		block.append("(Midi2CNC)")
		block.append("(Midi:%s)" % fileName)
		block.append(CNC.zsafe())
		block.append(CNC.grapid(0,0))
		block.append(CNC.zenter(0))

		for note in noteEventList:
			# note[timestamp, note off/note on, note_no, velocity]
			if last_time < note[0]:

				freq_xyz=[0,0,0]
				feed_xyz=[0,0,0]
				distance_xyz=[0,0,0]
				duration=0

				# "i" ranges from 0 to "the number of active notes *or* the number of active axes,
				# whichever is LOWER". Note that the range operator stops
				# short of the maximum, so this means 0 to 2 at most for a 3-axis machine.
				# E.g. only look for the first few active notes to play despite what
				# is going on in the actual score.

				for i in range(0, min(len(active_notes.values()), active_axes)):

					# Which axis are should we be writing to?
					#
					j = self.axes_dict.get(axes)[i]

					# Debug
					# print"Axes %s: item %d is %d" % (axes_dict.get(args.axes), i, j)

					# Sound higher pitched notes first by sorting by pitch then indexing by axis
					#
					nownote=sorted(active_notes.values(), reverse=True)[i]

					# MIDI note 69	 = A4(440Hz)
					# 2 to the power (69-69) / 12 * 440 = A4 440Hz
					# 2 to the power (64-69) / 12 * 440 = E4 329.627Hz
					#
					freq_xyz[j] = pow(2.0, (nownote-69 + transpose[j])/12.0)*440.0

					# Here is where we need smart per-axis feed conversions
					# to enable use of X/Y *and* Z on a Makerbot
					#
					# feed_xyz[0] = X; feed_xyz[1] = Y; feed_xyz[2] = Z;
					#
					# Feed rate is expressed in mm / minutes so 60 times
					# scaling factor is required.

					feed_xyz[j] = ( freq_xyz[j] * 60.0 ) / ppu[j]

					# Get the duration in seconds from the MIDI values in divisions, at the given tempo
					duration = ( ( ( note[0] - last_time ) + 0.0 ) / ( midi.division + 0.0 ) * ( tempo / 1000000.0 ) )

					# Get the actual relative distance travelled per axis in mm
					distance_xyz[j] = ( feed_xyz[j] * duration ) / 60.0

				# Now that axes can be addressed in any order, need to make sure
				# that all of them are silent before declaring a rest is due.
				if distance_xyz[0] + distance_xyz[1] + distance_xyz[2] > 0:
					# At least one axis is playing, so process the note into
					# movements
					combined_feedrate = math.sqrt(feed_xyz[0]**2 + feed_xyz[1]**2 + feed_xyz[2]**2)

					# Turn around BEFORE crossing the limits of the
					# safe working envelope
					if self.reached_limit( x, distance_xyz[0], x_dir, safemin[0], safemax[0] ):
						x_dir = x_dir * -1
					x = (x + (distance_xyz[0] * x_dir))

					if self.reached_limit( y, distance_xyz[1], y_dir, safemin[1], safemax[1] ):
						y_dir = y_dir * -1
					y = (y + (distance_xyz[1] * y_dir))

					if self.reached_limit( z, distance_xyz[2], z_dir, safemin[2], safemax[2] ):
						z_dir = z_dir * -1
					z = (z + (distance_xyz[2] * z_dir))

					v = (x,y,z)
					block.append(CNC.glinev(1,v,combined_feedrate))

				else:
					# Handle 'rests' in addition to notes.
					duration = (((note[0]-last_time)+0.0)/(midi.division+0.0)) * (tempo/1000000.0)
					block.append(CNC.gcode(4, [("P",duration)]))

				# finally, set this absolute time as the new starting time
				last_time = note[0]

			if note[1]==1: # Note on
				if active_notes.has_key(note[2]):
					pass
				else:
					# key and value are the same, but we don't really care.
					active_notes[note[2]]=note[2]
			elif note[1]==0: # Note off
				if(active_notes.has_key(note[2])):
					active_notes.pop(note[2])

		blocks.append(block)
		active = app.activeBlock()
		if active==0: active=1
		app.gcode.insBlocks(active, blocks, "Midi2CNC")
		app.refresh()
		app.setStatus(_("Generated Midi2CNC, ready to play?"))
Exemple #25
0
	def create_block(self, holes, name):
		targetDepth = self.fromMm("TargetDepth")
		peck = self.fromMm("Peck")
		dwell = self["Dwell"]
		block = Block(name)
		holesCount = 0
		for bid in holes:
			for xH,yH,zH in bid:
				holesCount += 1
				block.append(CNC.zsafe())
				block.append(CNC.grapid(xH,yH))
				if (peck != 0) :
					z = 0
					while z > targetDepth:
						z = max(z-peck, targetDepth)
						block.append(CNC.zenter(zH + z))
						block.append(CNC.zsafe())
				block.append(CNC.zenter(zH + targetDepth))
				#dwell time only on last pass
				if dwell != 0:
					block.append(CNC.gcode(4, [("P",dwell)]))
		#Gcode Zsafe on finish
		block.append(CNC.zsafe())
		return (block,holesCount)
Exemple #26
0
    def execute(self, app):
        #Get inputs
        holesDistance = self.fromMm("HolesDistance")
        targetDepth = self.fromMm("TargetDepth")
        peck = self.fromMm("Peck")
        dwell = self["Dwell"]

        zSafe = CNC.vars["safe"]

        #Check inputs
        if holesDistance <= 0:
            app.setStatus(_("Driller abort: Distance must be > 0"))
            return

        if peck < 0:
            app.setStatus(_("Driller abort: Peck must be >= 0"))
            return

        if dwell < 0:
            app.setStatus(
                _("Driller abort: Dwell time >= 0, here time runs only forward!"
                  ))
            return

        # Get selected blocks from editor
        selBlocks = app.editor.getSelectedBlocks()
        if not selBlocks:
            app.editor.selectAll()
            selBlocks = app.editor.getSelectedBlocks()

        if not selBlocks:
            app.setStatus(_("Driller abort: Please select some path"))
            return

        #Get all segments from gcode
        allSegments = self.extractAllSegments(app, selBlocks)

        #Create holes locations
        allHoles = []
        for bidSegment in allSegments:
            if len(bidSegment) == 0:
                continue

            #Summ all path length
            fullPathLength = 0.0
            for s in bidSegment:
                fullPathLength += s[3]

            #Calc rest
            holes = fullPathLength // holesDistance
            rest = fullPathLength - (holesDistance * (holes))
            #Travel along the path
            elapsedLength = rest / 2.0  #equaly distribute rest, as option???
            bidHoles = []
            while elapsedLength <= fullPathLength:
                #Search best segment to apply line interpolation
                bestSegment = bidSegment[0]
                segmentsSum = 0.0
                perc = 0.0
                for s in bidSegment:
                    bestSegment = s
                    segmentLength = bestSegment[3]
                    perc = (elapsedLength - segmentsSum) / segmentLength
                    segmentsSum += segmentLength
                    if segmentsSum > elapsedLength: break

                #Fist point
                x1 = bestSegment[0][0]
                y1 = bestSegment[0][1]
                z1 = bestSegment[0][2]
                #Last point
                x2 = bestSegment[1][0]
                y2 = bestSegment[1][1]
                z2 = bestSegment[1][2]

                #Check if segment is not excluded
                if not bestSegment[2]:
                    newHolePoint = (x1 + perc * (x2 - x1),
                                    y1 + perc * (y2 - y1),
                                    z1 + perc * (z2 - z1))
                    bidHoles.append(newHolePoint)

                #Go to next hole
                elapsedLength += holesDistance

            #Add bidHoles to allHoles
            allHoles.append(bidHoles)

        #Write gcommands from allSegments to the drill block
        n = self["name"]
        if not n or n == "default": n = "Driller"
        blocks = []
        block = Block(self.name)

        holesCount = 0
        for bid in allHoles:

            for xH, yH, zH in bid:
                holesCount += 1
                block.append(CNC.grapid(None, None, zH + zSafe))
                block.append(CNC.grapid(xH, yH))
                if (peck != 0):
                    z = 0
                    while z > targetDepth:
                        z = max(z - peck, targetDepth)
                        block.append(CNC.zenter(zH + z))
                        block.append(CNC.grapid(None, None, zH + zSafe))
                block.append(CNC.zenter(zH + targetDepth))
                #dwell time only on last pass
                if dwell != 0:
                    block.append(CNC.gcode(4, [("P", dwell)]))

        #Gcode Zsafe on finish
        block.append(CNC.zsafe())
        blocks.append(block)

        #Insert created block
        active = app.activeBlock()
        if active == 0: active = 1
        app.gcode.insBlocks(active, blocks, "Driller")
        app.refresh()
        app.setStatus(_("Generated Driller: %d holes") % holesCount)
Exemple #27
0
    def execute(self, app):
        try:
            import midiparser as midiparser
        except:
            app.setStatus(_("Error: This plugin requires midiparser.py"))
            return

        n = self["name"]
        if not n or n == "default": n = "Midi2CNC"

        fileName = self["File"]

        x = 0.0
        y = 0.0
        z = 0.0

        x_dir = 1.0
        y_dir = 1.0
        z_dir = 1.0

        # List of MIDI channels (instruments) to import.
        # Channel 10 is percussion, so better to omit it
        channels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

        axes = self["AxisUsed"]
        active_axes = len(axes)

        transpose = (0, 0, 0)
        ppu = [200, 200, 200]
        ppu[0] = self["ppu_X"]
        ppu[1] = self["ppu_X"]
        ppu[2] = self["ppu_X"]

        safemin = [0, 0, 0]
        safemax = [100, 100, 50]
        safemax[0] = self["max_X"]
        safemax[1] = self["max_Y"]
        safemax[2] = self["max_Z"]

        try:
            midi = midiparser.File(fileName)
        except:
            app.setStatus(_("Error: Sorry can't parse the Midi file."))
            return

        noteEventList = []
        all_channels = set()

        for track in midi.tracks:
            #channels=set()
            for event in track.events:
                if event.type == midiparser.meta.SetTempo:
                    tempo = event.detail.tempo

                # filter undesired instruments
                if ((event.type == midiparser.voice.NoteOn)
                        and (event.channel in channels)):

                    if event.channel not in channels:
                        channels.add(event.channel)

                    # NB: looks like some use "note on (vel 0)" as equivalent to note off, so check for vel=0 here and treat it as a note-off.
                    if event.detail.velocity > 0:
                        noteEventList.append([
                            event.absolute, 1, event.detail.note_no,
                            event.detail.velocity
                        ])
                    else:
                        noteEventList.append([
                            event.absolute, 0, event.detail.note_no,
                            event.detail.velocity
                        ])

                if (event.type == midiparser.voice.NoteOff) and (event.channel
                                                                 in channels):
                    if event.channel not in channels:
                        channels.add(event.channel)
                    noteEventList.append([
                        event.absolute, 0, event.detail.note_no,
                        event.detail.velocity
                    ])

            # Finished with this track
            if len(channels) > 0:
                msg = ', '.join(['%2d' % ch for ch in sorted(channels)])
                #print 'Processed track %d, containing channels numbered: [%s ]' % (track.number, msg)
                all_channels = all_channels.union(channels)

        # List all channels encountered
        if len(all_channels) > 0:
            msg = ', '.join(['%2d' % ch for ch in sorted(all_channels)])
            #print 'The file as a whole contains channels numbered: [%s ]' % msg

        # We now have entire file's notes with abs time from all channels
        # We don't care which channel/voice is which, but we do care about having all the notes in order
        # so sort event list by abstime to dechannelify

        noteEventList.sort()
        # print noteEventList
        # print len(noteEventList)

        last_time = -0
        active_notes = {
        }  # make this a dict so we can add and remove notes by name

        # Start the output
        #Init blocks
        blocks = []
        block = Block(self.name)
        block.append("(Midi2CNC)")
        block.append("(Midi:%s)" % fileName)
        block.append(CNC.zsafe())
        block.append(CNC.grapid(0, 0))
        block.append(CNC.zenter(0))

        for note in noteEventList:
            # note[timestamp, note off/note on, note_no, velocity]
            if last_time < note[0]:

                freq_xyz = [0, 0, 0]
                feed_xyz = [0, 0, 0]
                distance_xyz = [0, 0, 0]
                duration = 0

                # "i" ranges from 0 to "the number of active notes *or* the number of active axes,
                # whichever is LOWER". Note that the range operator stops
                # short of the maximum, so this means 0 to 2 at most for a 3-axis machine.
                # E.g. only look for the first few active notes to play despite what
                # is going on in the actual score.

                for i in range(0, min(len(active_notes.values()),
                                      active_axes)):

                    # Which axis are should we be writing to?
                    #
                    j = self.axes_dict.get(axes)[i]

                    # Debug
                    # print"Axes %s: item %d is %d" % (axes_dict.get(args.axes), i, j)

                    # Sound higher pitched notes first by sorting by pitch then indexing by axis
                    #
                    nownote = sorted(active_notes.values(), reverse=True)[i]

                    # MIDI note 69	 = A4(440Hz)
                    # 2 to the power (69-69) / 12 * 440 = A4 440Hz
                    # 2 to the power (64-69) / 12 * 440 = E4 329.627Hz
                    #
                    freq_xyz[j] = pow(
                        2.0, (nownote - 69 + transpose[j]) / 12.0) * 440.0

                    # Here is where we need smart per-axis feed conversions
                    # to enable use of X/Y *and* Z on a Makerbot
                    #
                    # feed_xyz[0] = X; feed_xyz[1] = Y; feed_xyz[2] = Z;
                    #
                    # Feed rate is expressed in mm / minutes so 60 times
                    # scaling factor is required.

                    feed_xyz[j] = (freq_xyz[j] * 60.0) / ppu[j]

                    # Get the duration in seconds from the MIDI values in divisions, at the given tempo
                    duration = (((note[0] - last_time) + 0.0) /
                                (midi.division + 0.0) * (tempo / 1000000.0))

                    # Get the actual relative distance travelled per axis in mm
                    distance_xyz[j] = (feed_xyz[j] * duration) / 60.0

                # Now that axes can be addressed in any order, need to make sure
                # that all of them are silent before declaring a rest is due.
                if distance_xyz[0] + distance_xyz[1] + distance_xyz[2] > 0:
                    # At least one axis is playing, so process the note into
                    # movements
                    combined_feedrate = math.sqrt(feed_xyz[0]**2 +
                                                  feed_xyz[1]**2 +
                                                  feed_xyz[2]**2)

                    # Turn around BEFORE crossing the limits of the
                    # safe working envelope
                    if self.reached_limit(x, distance_xyz[0], x_dir,
                                          safemin[0], safemax[0]):
                        x_dir = x_dir * -1
                    x = (x + (distance_xyz[0] * x_dir))

                    if self.reached_limit(y, distance_xyz[1], y_dir,
                                          safemin[1], safemax[1]):
                        y_dir = y_dir * -1
                    y = (y + (distance_xyz[1] * y_dir))

                    if self.reached_limit(z, distance_xyz[2], z_dir,
                                          safemin[2], safemax[2]):
                        z_dir = z_dir * -1
                    z = (z + (distance_xyz[2] * z_dir))

                    v = (x, y, z)
                    block.append(CNC.glinev(1, v, combined_feedrate))

                else:
                    # Handle 'rests' in addition to notes.
                    duration = (((note[0] - last_time) + 0.0) /
                                (midi.division + 0.0)) * (tempo / 1000000.0)
                    block.append(CNC.gcode(4, [("P", duration)]))

                # finally, set this absolute time as the new starting time
                last_time = note[0]

            if note[1] == 1:  # Note on
                if active_notes.has_key(note[2]):
                    pass
                else:
                    # key and value are the same, but we don't really care.
                    active_notes[note[2]] = note[2]
            elif note[1] == 0:  # Note off
                if (active_notes.has_key(note[2])):
                    active_notes.pop(note[2])

        blocks.append(block)
        active = app.activeBlock()
        if active == 0: active = 1
        app.gcode.insBlocks(active, blocks, "Midi2CNC")
        app.refresh()
        app.setStatus(_("Generated Midi2CNC, ready to play?"))
Exemple #28
0
	def make(self,app, XStart=0.0, YStart=0.0, FlatWidth=10., FlatHeight=10., \
			FlatDepth=0, BorderPass=False, CutDirection="Climb", PocketType="Raster"):

		#GCode Blocks
		blocks = []

		#Check parameters
		if CutDirection is "":
			app.setStatus(_("Flatten abort: Cut Direction is undefined"))
			return

		if PocketType is "":
			app.setStatus(_("Flatten abort: Pocket Type is undefined"))
			return

		if FlatWidth <= 0 or FlatHeight <= 0 :
			app.setStatus(_("Flatten abort: Flatten Area dimensions must be > 0"))
			return

		if FlatDepth > 0 :
			app.setStatus(_("Flatten abort: Hey this is only for subtractive machine! Check depth!"))
			return

		#Add Region disabled to show worked area
		block = Block(self.name + " Outline")
		block.enable = False
		block.append(CNC.zsafe())
		xR,yR = self.RectPath(XStart,YStart,FlatWidth,FlatHeight)
		for x,y in zip(xR,yR):
			block.append(CNC.gline(x,y))
		blocks.append(block)

		# Load tool and material settings
		toolDiam = CNC.vars['diameter']
		toolRadius = toolDiam / 2.

		#Calc tool diameter with Maximum Step Over allowed
		StepOverInUnitMax = toolDiam * CNC.vars['stepover'] / 100.0

		#Offset for Border Cut
		BorderXStart = XStart + toolRadius
		BorderYStart = YStart + toolRadius
		BorderWidth = FlatWidth - toolDiam
		BorderHeight = FlatHeight - toolDiam
		BorderXEnd = XStart + FlatWidth - toolRadius
		BorderYEnd = YStart + FlatHeight - toolRadius

		PocketXStart = BorderXStart
		PocketYStart = BorderYStart
		PocketXEnd = BorderXEnd
		PocketYEnd = BorderYEnd

		#Calc space to work with/without border cut
		WToWork = FlatWidth - toolDiam
		HToWork = FlatHeight - toolDiam

		if(WToWork < toolRadius or HToWork < toolRadius):
			app.setStatus(_("Flatten abort: Flatten area is too small for this End Mill."))
			return

		#Prepare points for pocketing
		xP=[]
		yP=[]
        #and border
		xB=[]
		yB=[]

        #---------------------------------------------------------------------
        #Raster approach
		if PocketType == "Raster":
			#Correct sizes if border is used
			if(BorderPass):
				PocketXStart += StepOverInUnitMax
				PocketYStart += StepOverInUnitMax
				PocketXEnd -= StepOverInUnitMax
				PocketYEnd -= StepOverInUnitMax
				WToWork -= (StepOverInUnitMax)
				HToWork -= (StepOverInUnitMax)

			#Calc number of pass
			VerticalCount = (int)(HToWork / StepOverInUnitMax)
			#Calc step minor of Max step
			StepOverInUnit = HToWork / (VerticalCount +1)
			flip = False
			ActualY = PocketYStart
			#Zig zag
			if StepOverInUnit==0 : StepOverInUnit=0.001  #avoid infinite while loop
			while (True):
				#Zig
				xP.append(self.ZigZag(flip,PocketXStart,PocketXEnd))
				yP.append(ActualY)
				flip = not flip
				#Zag
				xP.append(self.ZigZag(flip,PocketXStart,PocketXEnd))
				yP.append(ActualY)
				if(ActualY >= PocketYEnd - StepOverInUnitMax + StepOverInUnit):
					break
				#Up
				ActualY += StepOverInUnit
				xP.append(self.ZigZag(flip,PocketXStart,PocketXEnd))
				yP.append(ActualY)

			#Points for border cut depends on Zig/Zag end
			if(BorderPass):
				if flip:
					xB,yB = self.RectPath(BorderXStart,BorderYEnd,BorderWidth,-BorderHeight)
				else:
					xB,yB = self.RectPath(BorderXEnd,BorderYEnd,-BorderWidth,-BorderHeight)

				#Reverse in case of Climb
				if CutDirection == "Climb":
					xB = xB[::-1]
					yB = yB[::-1]

		#---------------------------------------------------------------------
        #Offset approach
		if PocketType == "Offset":
			#Calc number of pass
			VerticalCount = (int)(HToWork / StepOverInUnitMax)
			HorrizontalCount = (int)(WToWork / StepOverInUnitMax)
			#Make them odd
			if VerticalCount%2 == 0 : VerticalCount += 1
			if HorrizontalCount%2 == 0 : HorrizontalCount += 1
			#Calc step minor of Max step
			StepOverInUnitH = HToWork / (VerticalCount)
			StepOverInUnitW = WToWork / (HorrizontalCount)

			#Start from border to center
			xS = PocketXStart
			yS = PocketYStart
			wS = WToWork
			hS = HToWork
			xC = 0
			yC = 0
			while (xC<=HorrizontalCount/2 and yC<=VerticalCount/2):
				#Pocket offset points
				xO,yO = self.RectPath(xS, yS, wS, hS)
				if CutDirection == "Conventional":
					xO = xO[::-1]
					yO = yO[::-1]

				xP = xP + xO
				yP = yP + yO
				xS+=StepOverInUnitH
				yS+=StepOverInUnitW
				hS-=2.0*StepOverInUnitH
				wS-=2.0*StepOverInUnitW
				xC += 1
				yC += 1

			#Reverse point to start from inside (less stres on the tool)
			xP = xP[::-1]
			yP = yP[::-1]

		#Blocks for pocketing
		block = Block(self.name)
		block.append("(Flatten from X=%g Y=%g)"%(XStart,YStart))
		block.append("(W=%g x H=%g x D=%g)"%(FlatWidth,FlatHeight,FlatDepth))
		block.append("(Approach: %s %s)" % (PocketType,CutDirection))
		if BorderPass : block.append("(with border)")

		#Move safe to first point
		block.append(CNC.zsafe())
		block.append(CNC.grapid(xP[0],yP[0]))
		#Init Depth
		currDepth = 0.
		stepz = CNC.vars['stepz']
		if stepz==0 : stepz=0.001  #avoid infinite while loop

		#Create GCode from points
		while True:
			currDepth -= stepz
			if currDepth < FlatDepth : currDepth = FlatDepth
			block.append(CNC.zenter(currDepth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))

			#Pocketing
			for x,y in zip(xP,yP):
				block.append(CNC.gline(x,y))

			#Border cut if request
			for x,y in zip(xB,yB):
				block.append(CNC.gline(x,y))

			#Verify exit condition
			if currDepth <= FlatDepth : break

			#Move to the begin in a safe way
			block.append(CNC.zsafe())
			block.append(CNC.grapid(xP[0],yP[0]))

		#Zsafe
		block.append(CNC.zsafe())
		blocks.append(block)
		return blocks
Exemple #29
0
    def make(self):
        d = self.thick

        # Convert to external dimensions
        if self.dx < 0:
            dx = -self.dx - d * 2  # external to internal
        else:
            dx = self.dx

        if self.dy < 0:
            dy = -self.dy - d * 2  # external to internal
        else:
            dy = self.dy

        if self.dz < 0:
            dz = -self.dz - d * 2  # external to internal
        else:
            dz = self.dz

        blocks = []
        block = Block("%s-Bottom" % (self.name))
        block.append("(Box: %g x %g x %g)" % (self.dx, self.dy, self.dz))
        block.append("(Fingers: %d x %d x %d)" % (self.nx, self.ny, self.nz))
        self._rectangle(block, 0., -d, dx, dy, self.nx, -self.ny, 0, d)
        blocks.append(block)

        block = Block("%s-Left" % (self.name))
        self._rectangle(block, -(dz + 5 * d), -d, dz, dy, self.nz, self.ny, d,
                        d)
        blocks.append(block)

        block = Block("%s-Right" % (self.name))
        self._rectangle(block, dx + 3 * d, -d, dz, dy, self.nz, self.ny, d, d)
        blocks.append(block)

        block = Block("%s-Front" % (self.name))
        self._rectangle(block, 0, -(dz + 4 * d), dx, dz, -self.nx, -self.nz, 0,
                        0)
        blocks.append(block)

        block = Block("%s-Back" % (self.name))
        self._rectangle(block, 0, dy + 4 * d, dx, dz, -self.nx, -self.nz, 0, 0)
        blocks.append(block)

        block = Block("%s-Top" % (self.name))
        self._rectangle(block, dx + dz + 8 * d, -d, dx, dy, self.nx, -self.ny,
                        0, d)
        blocks.append(block)
        return blocks
Exemple #30
0
	def make(self,RExt=50., RInt=33., ROff=13. , Depth=0):
		self.RExt = RExt
		self.RInt = RInt
		self.ROff = ROff

		if RExt>RInt :
			self.Spins = self.lcm(RExt,RInt) / max(RExt,RInt)
		else:
			self.Spins = self.lcm(RExt,RInt) / min(RExt,RInt)

		self.Depth = Depth
		self.PI = math.pi
		self.theta = 0.0

		blocks = []
		block = Block(self.name)

		block.append("(External Radius = %g)"%(self.RExt))
		block.append("(Internal Radius = %g)"%(self.RInt))
		block.append("(Offset Radius = %g)"%(self.ROff))

		xi,yi = zip(*(self.calc_dots()))

		block.append(CNC.zsafe())
		block.append(CNC.grapid(xi[0],yi[0]))

		currDepth = 0.
		stepz = CNC.vars['stepz']
		if stepz==0 : stepz=0.001  #avoid infinite while loop

		while True:
			currDepth -= stepz
			if currDepth < self.Depth : currDepth = self.Depth
			block.append(CNC.zenter(currDepth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			for x,y in zip(xi,yi):
				block.append(CNC.gline(x,y))
			block.append(CNC.gline(xi[0],yi[0]))
			if currDepth <= self.Depth : break

		block.append(CNC.zsafe())
		blocks.append(block)
		return blocks
Exemple #31
0
	def make(self, Nlines, LineLen, StartEndLen, Step, CornerRes, Depth):
		blocks = []
		block = Block(self.name)

		points = self.zigzag(Nlines, LineLen, StartEndLen, Step, CornerRes)

		block.append(CNC.zsafe())
		block.append(CNC.grapid(points[0][0],points[0][1]))

		currDepth = 0.
		stepz = CNC.vars['stepz']
		if stepz==0 : stepz=0.001  #avoid infinite while loop

		while True:
			currDepth -= stepz
			if currDepth < Depth : currDepth = Depth
			block.append(CNC.zenter(currDepth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			for (x,y) in points:
				block.append(CNC.gline(x,y))
			if currDepth <= Depth : break

		block.append(CNC.zsafe())
		blocks.append(block)
		return blocks
Exemple #32
0
	def calc(self, D, res, pocket):
		blocks = []
		block = Block(self.name)

		# Load tool and material settings
		toolDiam = CNC.vars['diameter']
		toolRadius = toolDiam/2.
		stepz  = CNC.vars['stepz']
		stepxy = toolDiam*(CNC.vars['stepover']/100.)

		if toolDiam <= 0 or stepxy <= 0 or stepz <= 0 or D <= 0 or res <= 0:
			return blocks

		currDepth = 0.

		def setCutFeedrate():
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))

		def addCircumference(radius):
			block.append(CNC.garc(2,radius, 0., i=-radius))

		# Mills a circle, pocketing it if needed
		def addSingleCircle(radius, depth):
			if pocket:
				block.append(CNC.grapid(0., 0.))
				block.append(CNC.zenter(depth))
				setCutFeedrate()
				currRadius = 0.
				while radius > currRadius+stepxy:
					currRadius += stepxy
					block.append(CNC.gline(currRadius, 0))
					addCircumference(currRadius)
				if radius-currRadius > 0:
					block.append(CNC.gline(radius, 0))
					addCircumference(radius)
			else:
				block.append(CNC.grapid(radius, 0.))
				block.append(CNC.zenter(depth))
				setCutFeedrate()
				addCircumference(radius)

		# Mills a circle in steps of height "stepz"
		def addCircle(radius, depth, currDepth):
			while depth < currDepth-stepz:
				currDepth -= stepz
				addSingleCircle(radius, currDepth)
			if currDepth-depth > 0:
				addSingleCircle(radius, depth)
			return depth

		block.append(CNC.zsafe())
		r = D/2.
		r -= toolRadius # Removes offset of ball-end tool
		angleInc = res
		currAngle = 0.
		angle = math.pi/2. # 90 degrees
		while angle > currAngle+angleInc:
			currAngle += angleInc
			radius = r * math.cos(-currAngle)
			depth  = r * math.sin(-currAngle) - toolRadius # Removes vertical offset (centers the ball tool in Z=0, rather than the tip)
			currDepth = addCircle(radius, depth, currDepth)
		if angle-currAngle > 0:
			radius = r * math.cos(-angle)
			depth  = r * math.sin(-angle) - toolRadius
			currDepth = addCircle(radius, depth, currDepth)

		blocks.append(block)
		return blocks
Exemple #33
0
	def execute(self, app):
		# info =xnew,ynew,znew,dxy,dz

		xscale= self["xscale"]
		if xscale=="":xscale=1
		yscale= self["yscale"]
		if yscale=="":yscale=1
		zscale= self["zscale"]
		if zscale=="":zscale=1

		surface = CNC.vars["surface"]
		if zscale>0:
			surface*=zscale

		feed = self["feed"]
		zfeed = CNC.vars["cutfeedz"]
		rpm = self["rpm"]
		if self["zfeed"]:
				zfeed = self["zfeed"]

		#zup = self["zup"]


		centered = self["centered"]

#		zbeforecontact=surface+CNC.vars["zretract"]
#		hardcrust = surface - CNC.vars["hardcrust"]
#		feedbeforecontact = CNC.vars["feedbeforecontact"]/100.0
#		hardcrustfeed = CNC.vars["hardcrustfeed"]/100.0

		# Get selected blocks from editor

		selBlocks = app.editor.getSelectedBlocks()
		if not selBlocks:
			app.setStatus(_("Scaling abort: Please select some path"))
			return 
		elements=len(app.editor.getSelectedBlocks())
		print("elements",elements)
		for bid in app.editor.getSelectedBlocks():
				if len(app.gcode.toPath(bid)) < 1: continue
				path = app.gcode.toPath(bid)[0]
				if centered:
					center = path.center()
				else:
					center=0,0
		print ("center",center[0],center[1])
	#	if elements>=2:
	#		center=0,0


		#Get all segments from gcode
		allSegments = self.extractAllSegments(app,selBlocks)[0]
		name_block = self.extractAllSegments(app,selBlocks)[1]
#		num_block = self.extractAllSegments(app,selBlocks)[2]

		#Create holes locations
		all_blocks=[]
		for bidSegment in allSegments:
			if len(bidSegment)==0:
				continue
	#		all_blocks = []
			n = self["name"]
	#		if not n or n=="default": n="Trochoidal_3D"
			if elements>1:
				n="scale "
			else:
				if centered:
					n="center scale "+str(name_block)
				else:
					n="scale "+str(name_block)
			bid_block = Block(n)

			for idx, segm in enumerate(bidSegment):
	#			if idx >= 0:
	#			bid_block.append("(idx "+str(idx)+" -------------- )")
				info=self.scaling(segm,center,xscale,yscale,zscale)
				if idx == 0:
					bid_block.append("(---- Scale (x "+str(xscale)+" : 1.0),(y "+str(yscale)+" : 1.0),(z "+str(zscale)+" : 1.0) ---- )")
					bid_block.append("(center "+str(center[0])+" ,"+str(center[1])+" )")
					bid_block.append("M03")
					bid_block.append("S "+str(rpm))
					bid_block.append(CNC.zsafe())
					bid_block.append("F "+str(zfeed))
					bid_block.append("g0 x "+str(info[0])+" y "+str(info[1]))
					currentfeed=oldfeed=zfeed
				else:
				#	if B[5]>=0: #<< zsign
				#		currentfeed=feed
				#	else:
					#relationship
					if info[4]>=0:
						currentfeed=feed
					else:
						rel=info[3]/(info[3]+abs(info[4])) 
						currentfeed=int(rel*feed+(1-rel)*zfeed)

					if segm[0][2]> surface and segm[1][2]>=surface:
						bid_block.append("g0 x "+str(info[0])+" y "+str(info[1])+ " z "+str(info[2]))
					else:
						if currentfeed!=oldfeed:
							bid_block.append("F "+str(currentfeed))
						bid_block.append("g1 x "+str(info[0])+" y "+str(info[1])+ " z "+str(info[2]))
					oldfeed=currentfeed

			bid_block.append(CNC.zsafe()) 			#<<< Move rapid Z axis to the safe height in Stock Material
			all_blocks.append(bid_block)
#			print "bid", bid_block.name(), bid_block,"*****************"
		self.finish_blocks(app, all_blocks,elements)
Exemple #34
0
	def make(self,n = 2, size = 100, depth = 0):
		self.n = n
		self.size = size
		self.depth = depth

		blocks = []
		block = Block(self.name)

		xi,yi = zip(*(self.hilbert(0.0,0.0,size,0.0,0.0,size,n)))

		block.append(CNC.zsafe())
		block.append(CNC.grapid(xi[0],yi[0]))

		currDepth = 0.
		stepz = CNC.vars['stepz']
		if stepz==0 : stepz=0.001  #avoid infinite while loop

		while True:
			currDepth -= stepz
			if currDepth < self.depth : currDepth = self.depth
			block.append(CNC.zenter(currDepth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			for x,y in zip(xi,yi):
				block.append(CNC.gline(x,y))
			if currDepth <= self.depth : break

		block.append(CNC.zsafe())
		blocks.append(block)
		return blocks
Exemple #35
0
	def execute(self, app):
		try:
			from PIL import Image
		except:
			app.setStatus(_("Sketch abort: This plugin requires PIL/Pillow to read image data"))
			return

		n = self["name"]
		if not n or n=="default": n="Sketch"

		#Calc desired size
		grundgy =self["Grundgy"]
		maxSize = self["MaxSize"]
		squiggleTotal  = self["SquiggleTotal"]
		squiggleLength = self["SquiggleLength"]
		depth = self["Depth"]
		drawBorder = self["DrawBorder"]
		channel = self["Channel"]

		radius = 1
		if grundgy == "Low":
			radius = 2
		elif grundgy == "Medium":
			radius = 3
		elif grundgy == "High":
			radius = 6
		elif grundgy == "Very High":
			radius = 9

		#Check parameters
		if maxSize < 1:
			app.setStatus(_("Sketch abort: Too small to draw anything!"))
			return

		if squiggleTotal < 1:
			app.setStatus(_("Sketch abort: Please let me draw at least 1 squiggle"))
			return
			
		if squiggleLength <= 0:
			app.setStatus(_("Sketch abort: Squiggle Length must be > 0"))
			return

		fileName = self["File"]
		try:
			img = Image.open(fileName)
		except:
			app.setStatus(_("Sketch abort: Can't read image file"))
			return

		#Create a scaled image to work faster with big image and better with small ones
		iWidth,iHeight = img.size
		resampleRatio = 800.0 / iHeight
		img = img.resize((int(iWidth *resampleRatio) ,int(iHeight * resampleRatio)), Image.ANTIALIAS)
		if channel == 'Blue':
			img = img.convert('RGB')
			img = img.split()[0]
		elif channel == 'Green':
			img = img.convert('RGB')
			img = img.split()[1]
		elif channel == 'Red':
			img = img.convert('RGB')
			img = img.split()[2]
		else:
			img = img.convert ('L') #to calculate luminance

		img = img.transpose(Image.FLIP_TOP_BOTTOM) #ouput correct image
		pix = img.load()

		#Get image size
		self.imgWidth, self.imgHeight =  img.size
		self.ratio = 1
		if (iWidth > iHeight):
			self.ratio = maxSize / float(self.imgWidth)
		else:
			self.ratio = maxSize / float(self.imgHeight)

		#Init blocks
		blocks = []

		#Border block
		block = Block("%s-border"%(self.name))
		block.enable = drawBorder
		block.append(CNC.zsafe())
		block.append(CNC.grapid(0,0))
		block.append(CNC.zenter(depth))
		block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
		block.append(CNC.gline(self.imgWidth * self.ratio, 0))
		block.append(CNC.gline(self.imgWidth * self.ratio, self.imgHeight*self.ratio))
		block.append(CNC.gline(0, self.imgHeight*self.ratio))
		block.append(CNC.gline(0,0))
		blocks.append(block)

		#Draw block
		block = Block(self.name)
		block.append("(Sketch size W=%d x H=%d x distance=%d)" %
			 (self.imgWidth * self.ratio  , self.imgHeight * self.ratio  , depth))
		block.append("(Channel = %s)" %(channel))
		#choose a nice starting point
		x = self.imgWidth / 4.
		y = self.imgHeight / 4.

		#First round search in all image
		self.mostest = 256
		x,y = self.findFirst(pix, True)

		#startAll = time.time()
		for c in range(squiggleTotal):
			#print c,x,y
			#start = time.time()
			x,y = self.findFirst(pix, False)
			#print 'Find mostest: %f' % (time.time() - start)
			#move there
			block.append(CNC.zsafe())
			block.append(CNC.grapid(x*self.ratio, y*self.ratio))
			#tool down
			block.append(CNC.zenter(depth))
			#restore cut/draw feed
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))

			#start = time.time()
			s = 0
			while (s < squiggleLength):
				x,y,distance = self.findInRange(x, y, pix, radius)
				s+= max(1,distance*self.ratio)  #add traveled distance
				#move there
				block.append(CNC.gline(x*self.ratio,y*self.ratio))
				self.fadePixel(x, y, pix) #adjustbrightness int the bright map
			#tool up
			block.append(CNC.zsafe())
			#print 'Squiggle: %f' % (time.time() - start)

		#Gcode Zsafe
		block.append(CNC.zsafe())
		blocks.append(block)
		active = app.activeBlock()
		app.gcode.insBlocks(active, blocks, "Sketch")
		app.refresh()
		app.setStatus(_("Generated Sketch size W=%d x H=%d x distance=%d, Total length:%d") %
			(self.imgWidth*self.ratio  , self.imgHeight*self.ratio , depth, squiggleTotal*squiggleLength))
Exemple #36
0
	def make(self, Nlines, LineLen, StartEndLen, Step, CornerRes, Depth):

		blocks = []
		block = Block(self.name)

		points = self.zigzag(Nlines, LineLen, StartEndLen, Step, CornerRes)

		block.append(CNC.zsafe())
		block.append(CNC.grapid(points[0][0],points[0][1]))

		currDepth = 0.
		stepz = CNC.vars['stepz']
		if stepz==0 : stepz=0.001  #avoid infinite while loop

		while True:
			currDepth -= stepz
			if currDepth < Depth : currDepth = Depth
			block.append(CNC.zenter(currDepth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			for (x,y) in points:
				block.append(CNC.gline(x,y))
			if currDepth <= Depth : break

		block.append(CNC.zsafe())
		blocks.append(block)
		return blocks
Exemple #37
0
	def calc(self, N, phi, Pc):
		N = abs(N)
		# Pitch Circle
		D = N * Pc / math.pi
		R = D / 2.0

		# Diametrical pitch
		Pd = N / D

		# Base Circle
		Db = D * math.cos(phi)
		Rb = Db / 2.0

		# Addendum
		a = 1.0 / Pd

		# Outside Circle
		Ro = R + a
		Do = 2.0 * Ro

		# Tooth thickness
		T = math.pi*D / (2*N)

		# undercut?
		U = 2.0 / (math.sin(phi) * (math.sin(phi)))
		needs_undercut = N < U
		# sys.stderr.write("N:%s R:%s Rb:%s\n" % (N,R,Rb))

		# Clearance
		c = 0.0
		# Dedendum
		b = a + c

		# Root Circle
		Rr = R - b
		Dr = 2.0*Rr

		two_pi = 2.0*math.pi
		half_thick_angle = two_pi / (4.0*N)
		pitch_to_base_angle = self.involute_intersect_angle(Rb, R)
		pitch_to_outer_angle = self.involute_intersect_angle(Rb, Ro) # pitch_to_base_angle

		points = []
		for x in range(1,N+1):
			c = x * two_pi / N

			# angles
			pitch1 = c - half_thick_angle
			base1  = pitch1 - pitch_to_base_angle
			outer1 = pitch1 + pitch_to_outer_angle

			pitch2 = c + half_thick_angle
			base2  = pitch2 + pitch_to_base_angle
			outer2 = pitch2 - pitch_to_outer_angle

			# points
			b1 = self.point_on_circle(Rb, base1)
			p1 = self.point_on_circle(R,  pitch1)
			o1 = self.point_on_circle(Ro, outer1)
			o2 = self.point_on_circle(Ro, outer2)
			p2 = self.point_on_circle(R,  pitch2)
			b2 = self.point_on_circle(Rb, base2)

			if Rr >= Rb:
				pitch_to_root_angle = pitch_to_base_angle - self.involute_intersect_angle(Rb, Rr)
				root1 = pitch1 - pitch_to_root_angle
				root2 = pitch2 + pitch_to_root_angle
				r1 = self.point_on_circle(Rr, root1)
				r2 = self.point_on_circle(Rr, root2)

				points.append(r1)
				points.append(p1)
				points.append(o1)
				points.append(o2)
				points.append(p2)
				points.append(r2)
			else:
				r1 = self.point_on_circle(Rr, base1)
				r2 = self.point_on_circle(Rr, base2)
				points.append(r1)
				points.append(b1)
				points.append(p1)
				points.append(o1)
				points.append(o2)
				points.append(p2)
				points.append(b2)
				points.append(r2)

		first = points[0]
		del points[0]

		blocks = []
		block = Block(self.name)
		blocks.append(block)

		block.append(CNC.grapid(first.x(), first.y()))
		block.append(CNC.zenter(0.0))
		#print first.x(), first.y()
		for v in points:
			block.append(CNC.gline(v.x(), v.y()))
			#print v.x(), v.y()
		#print first.x(), first.y()
		block.append(CNC.gline(first.x(), first.y()))
		block.append(CNC.zsafe())

		#block = Block("%s-center"%(self.name))
		block = Block("%s-basecircle"%(self.name))
		block.enable = False
		block.append(CNC.grapid(Db/2, 0.))
		block.append(CNC.zenter(0.0))
		block.append(CNC.garc(CW, Db/2, 0., i=-Db/2))
		block.append(CNC.zsafe())
		blocks.append(block)
		return blocks
Exemple #38
0
    def execute(self, app):

        n = self["name"]
        if not n or n == "default": n = "Pyrograph"

        #Import parameters
        toolSize = self.fromMm("ToolSize")

        if toolSize <= 0:
            app.setStatus(_("Pyrograph abort: Tool Size must be > 0"))
            return

        filename = self["File"]

        #Open gcode file
        if not (filename == ""):
            app.load(filename)

        inOut = self["In-Out"]
        xadd = self["xAdd"]
        yadd = self["yAdd"]
        if xadd == "": xadd = 1
        if yadd == "": yadd = 1

        #Create the external box
        if inOut == "Out":
            box = Block("Box")
            external_box = []
            box.append(
                CNC.grapid(CNC.vars["xmin"] - xadd, CNC.vars["ymin"] - yadd))
            box.append(
                CNC.gline(CNC.vars["xmin"] - xadd, CNC.vars["ymax"] + yadd))
            box.append(
                CNC.gline(CNC.vars["xmax"] + xadd, CNC.vars["ymax"] + yadd))
            box.append(
                CNC.gline(CNC.vars["xmax"] + xadd, CNC.vars["ymin"] - yadd))
            box.append(
                CNC.gline(CNC.vars["xmin"] - xadd, CNC.vars["ymin"] - yadd))

            #Insert the external block
            external_box.append(box)
            app.gcode.insBlocks(1, external_box, "External_Box")
            app.refresh()

        #Value for creating an offset from the margins of the gcode
        margin = self.fromMm(
            "Margin"
        )  #GIVING RANDOM DECIMALS SHOULD AVOID COINCIDENT SEGMENTS BETWEEN ISLAND AND BASE PATHS THAT CONFUSE THE ALGORITHM. WORKS IN MOST CASES.

        #Add and subtract the margin
        max_x = CNC.vars["xmax"] + margin
        min_x = CNC.vars["xmin"] - margin
        max_y = CNC.vars["ymax"] + margin
        min_y = CNC.vars["ymin"] - margin

        #Difference between offtset margins
        dx = max_x - min_x
        dy = max_y - min_y

        #Number of vertical divisions according to the toolsize
        divisions = dy / toolSize

        #Distance between horizontal lines
        step_y = toolSize
        n_steps_y = int(divisions) + 1

        #Create the snake pattern according to the number of divisions
        pattern = Block(self.name)
        pattern_base = []

        for n in range(n_steps_y):
            if n == 0:
                pattern.append(CNC.grapid(min_x, min_y))  #go to bottom left
            else:
                y0 = min_y + step_y * (n - 1)
                y1 = min_y + step_y * (n)
                if not (n % 2 == 0):
                    pattern.append(CNC.glinev(
                        1, [max_x, y0]))  #write odd lines from left to right
                    pattern.append(CNC.grapid(max_x, y1))
                else:
                    pattern.append(CNC.glinev(
                        1, [min_x, y0]))  #write even lines from right to left
                    pattern.append(CNC.grapid(min_x, y1))

        #Insert the pattern block
        pattern_base.append(pattern)
        app.gcode.insBlocks(1, pattern_base, "pattern")
        app.refresh()

        #Mark pattern as island
        for bid in pattern_base:
            app.gcode.island([1])

        #Select all blocks
        app.editor.selectAll()

        paths_base = []
        paths_isl = []

        points = []

        #Compare blocks to separate island from other blocks
        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))

        #Make intersection between blocks
        while len(paths_base) > 0:
            base = paths_base.pop()
            for island in paths_isl:
                #points.extend(base.intersectPath(island))
                points.extend(island.intersectPath(base))

###SORTING POINTS###
        x = []
        y = []

        #Get (x,y) intersection points
        for i in range(len(points)):
            x.append(points[i][2][0])
            y.append(points[i][2][1])

        #Save (x,y) intersection points in a matrix
        matrix = [[0 for i in range(2)] for j in range(len(x))]

        for i in range(len(x)):
            matrix[i][0] = x[i]
            matrix[i][1] = y[i]

        # for i in range(len(x)):
        # 	print('puntos',points[i][0],points[i][1],matrix[i][0], matrix[i][1])

        #print(matrix)

        #Sort points in increasing y coordinate
        matrix.sort(key=itemgetter(1, 0), reverse=False)

        # for i in range(len(x)):
        # 	print('puntos',points[i][0],points[i][1],matrix[i][0], matrix[i][1])
        #print(matrix)

        index = 0
        pair = 0
        new_matrix = []
        for i in range(len(x)):
            if i == 0:
                index = index + 1
            elif i < len(x) - 1:
                if matrix[i][1] == matrix[i - 1][1]:
                    index = index + 1
                else:
                    if pair % 2 == 0:
                        logic = False
                    else:
                        logic = True
                    submatrix = matrix[i - index:i]
                    submatrix.sort(key=itemgetter(0, 1), reverse=logic)
                    new_matrix.extend(submatrix)
                    index = 1
                    pair = pair + 1
            else:
                #print('entered')
                if pair % 2 == 0:
                    logic = False
                else:
                    logic = True
                if matrix[i][1] == matrix[i - 1][1]:
                    submatrix = matrix[i - index:]
                    submatrix.sort(key=itemgetter(0, 1), reverse=logic)
                    new_matrix.extend(submatrix)
                else:
                    index = 1
                    submatrix = matrix[-1]
                    new_matrix.extend(submatrix)

        # for i in range(len(x)):
        # 	print('puntos',new_matrix[i][0], new_matrix[i][1])

        # for i in range(len(x)):
        # 	print('puntos',new_matrix[i][0], new_matrix[i][1])
        #print(x, y)

###SORTING POINTS END###

#Generate the gcode from points obtained
        blocks = []
        block = Block(self.name)

        for i in range(len(x)):
            if i == 0:
                block.append(CNC.grapid(new_matrix[0][0], new_matrix[0][1]))
                inside = 0
            else:
                if inside == 0:
                    block.append(CNC.gline(new_matrix[i][0], new_matrix[i][1]))
                    inside = 1
                else:
                    block.append(CNC.grapid(new_matrix[i][0],
                                            new_matrix[i][1]))
                    inside = 0

        # for i in range(len(x)):
        # 	print('puntos',x[i], y[i])

        blocks.append(block)
        app.gcode.delBlockUndo(1)
        app.gcode.insBlocks(1, blocks, "Line to Line Burning")

        app.editor.disable()

        for block in blocks:
            block.enable = 1

        #app.editor.enable()
        #app.editor.unselectAll()
        app.refresh()
        app.setStatus(_("Generated Line to Line Burning"))
Exemple #39
0
	def execute(self, app):
		rdoc = self["rdoc"]
		radius = self["dia"]/2
		cw = self["cw"]
		circ = self["circ"]

		#print("go!")
		blocks  = []
		for bid in app.editor.getSelectedBlocks():
			#print(blocks[bid])
			path = app.gcode.toPath(bid)[0]
			#print(path)

			block = Block("trochoid")

			entry = self["entry"]
			for segment in path:
				#print(segment.A)
				#block.append("g0 x0 y0")
				#block.append("g1 x10 y10")
				#block.append("g1 x20 y10")
				#block.append("g0 x0 y0")
				if entry:
					eblock = Block("trochoid-in")
					eblock.append("G0 Z0")
					eblock.append("G0 x"+str(segment.A[0])+" y"+str(segment.A[1]-radius))
					eblock.append("G2 x"+str(segment.A[0])+" y"+str(segment.A[1]-radius)+" i"+str(0)+" j"+str(radius))
					blocks.append(eblock)
					entry = False

				block.append("G0 Z0")
				block.extend(self.trochoid(segment, rdoc, radius, cw, circ))

			blocks.append(block)


		active = app.activeBlock()
		app.gcode.insBlocks(active, blocks, "Trochoidal created") #<<< insert blocks over active block in the editor
		app.refresh()                                                                                           #<<< refresh editor
		app.setStatus(_("Generated: Trochoidal"))                           #<<< feed back result
Exemple #40
0
	def execute(self, app):
		feed = self["feed"]
		zfeed = CNC.vars["cutfeedz"]
		rpm = self["rpm"]
		if self["zfeed"]:
				zfeed = self["zfeed"]

		zup = self["zup"]

		surface = CNC.vars["surface"]
#		zbeforecontact=surface+CNC.vars["zretract"]
#		hardcrust = surface - CNC.vars["hardcrust"]
#		feedbeforecontact = CNC.vars["feedbeforecontact"]/100.0
#		hardcrustfeed = CNC.vars["hardcrustfeed"]/100.0

		# Get selected blocks from editor
		selBlocks = app.editor.getSelectedBlocks()

		if not selBlocks:
			app.setStatus(_("Scaling abort: Please select some path"))
			return 

		#Get all segments from gcode
		allSegments = self.extractAllSegments(app,selBlocks)

		#Create holes locations
#		allHoles=[]
		for bidSegment in allSegments:
			if len(bidSegment)==0:
				continue
		blocks = []
		n = self["name"]
#		if not n or n=="default": n="Trochoidal_3D"
		n="Scaling"
		scal_block = Block(n)

		for idx, segm in enumerate(bidSegment):
			if idx >= 0:
				if idx == 0:
					scal_block.append("M03")
					scal_block.append("S "+str(rpm))
					scal_block.append(CNC.zsafe())
					scal_block.append("F "+str(feed))
					scal_block.append("(--------------------------------------------------)")

				B=self.scaling(segm)

				if segm[0][2]> surface and segm[1][2]>=surface:
					scal_block.append("g0 x "+str(B[0])+" y "+str(B[1])+ " z "+str(B[2]))
				else:
					scal_block.append("g1 x "+str(B[0])+" y "+str(B[1])+ " z "+str(B[2]))
		scal_block.append(CNC.zsafe()) 			#<<< Move rapid Z axis to the safe height in Stock Material
		blocks.append(scal_block)
		self.finish_blocks(app, blocks)
Exemple #41
0
    def execute(self, app):
        name = self['name']

        if not name or name == 'default':
            name = 'Function'

        # Initialize blocks that will contain our gCode
        blocks = []
        block = Block(name)

        #Variable definitions
        formula = self['form']
        res = self['res']  # X resolution
        ran = [self['ranX'],
               self['ranY']]  # Range of X,Y, from -10, to 10 range is 20
        cent = [
            self['centX'], self['centY']
        ]  # Coordinates X,Y of the center from bottom left of the coordinate system
        dim = [self['dimX'], self['dimY']]  # Real dimensions in gcode units
        spacX = self['spacX']  # Spacing of X axis lines
        spacY = self['spacY']  # Spacing of Y axis lines
        lin = self['lin']  # Small value - length of a line in gcode units
        draw = self['draw']  # Draw the coordinate system

        block.append("(Generated with a script by kswiorek)\n")
        block.append("(Equation: " + formula + ")\n")
        block.append("(Resolution: " + str(res) + ")\n")
        block.append("(Range: " + str(ran) + ")\n")
        block.append("(Center: " + str(cent) + ")\n")
        block.append("(Dimensions: " + str(dim) + ")\n")
        block.append("(SpacingXY: " + str(spacX) + ", " + str(spacY) + ")\n")

        def mapc(var, axis):  #Map coordinate systems
            return (var * (dim[axis] / ran[axis]))

        #Define coordinate system mins and maxes
        minX = -cent[0]
        maxX = ran[0] - cent[0]

        minY = -cent[1]
        maxY = ran[1] - cent[1]

        #Define domain and codomain
        X = []
        Y = []

        e_old = ""  #Store old exception to comapre

        #Calculate values for arguments with a resolution
        for i in range(0, int(ran[0] / res +
                              1)):  #Complaints about values beeing floats
            x = i * res + minX  #Iterate x
            X.append(x)
            try:
                Y.append(eval(formula))

            except Exception as exc:  #Append None, not to loose sync with X
                Y.append(None)
                e = str(exc)
                if e != e_old:  #If there is a different exception - display it
                    print("Warning: " + str(e))
                    app.setStatus(_("Warning: " + str(e)))
                    e_old = e

        raised = True  # Z axis is raised at start

        #Clip values out of bounds, replace with None, not to loose sync with X
        for i, item in enumerate(Y):
            y = Y[i]
            if not y is None and (y < minY or y > maxY):
                Y[i] = None

        #Y without "None", min() and max() can't compare them
        Ynn = []  #Y no Nones
        for i, item in enumerate(Y):
            if not Y[i] is None:
                Ynn.append(Y[i])

        block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])]))  #Set feedrate

        if draw:  #If the user selected to draw the coordinate system
            #X axis
            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(0, mapc(cent[1],
                                            1)))  #1st point of X axis line
            block.append(CNC.grapid(z=0))

            block.append(CNC.gline(dim[0] + lin * 1.2, mapc(
                cent[1], 1)))  #End of X axis line + a bit more for the arrow

            block.append(
                CNC.gline(dim[0] - lin / 2,
                          mapc(cent[1], 1) -
                          lin / 2))  #bottom part of the arrow

            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(dim[0] + lin * 1.2, mapc(cent[1], 1),
                                    0))  #End of X axis line
            block.append(CNC.grapid(z=0))

            block.append(
                CNC.gline(dim[0] - lin / 2,
                          mapc(cent[1], 1) + lin / 2))  #top part of the arrow
            block.append(CNC.grapid(z=3))

            #Y axis, just inverted x with y
            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(mapc(cent[0], 0),
                                    0))  #1st point of Y axis line
            block.append(CNC.grapid(z=0))

            block.append(CNC.gline(
                mapc(cent[0], 0), dim[1] +
                lin * 1.2))  #End of Y axis line + a bit more for the arrow

            block.append(
                CNC.gline(mapc(cent[0], 0) - lin / 2,
                          dim[1] - lin / 2))  #left part of the arrow

            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(mapc(cent[0], 0),
                                    dim[1] + lin * 1.2))  #End of Y axis line
            block.append(CNC.grapid(z=0))

            block.append(
                CNC.gline(mapc(cent[0], 0) + lin / 2,
                          dim[1] - lin / 2))  #right part of the arrow
            block.append(CNC.grapid(z=3))

            #X axis number lines
            i = 0
            while i < ran[0] - cent[0]:  #While i is on the left of the arrow
                i += spacX  #Add line spacing

                #Draw lines right of the center
                block.append(
                    CNC.grapid(mapc(i + cent[0], 0),
                               mapc(cent[1], 1) + lin / 2))
                block.append(CNC.grapid(z=0))
                block.append(
                    CNC.gline(mapc(i + cent[0], 0),
                              mapc(cent[1], 1) - lin / 2))
                block.append(CNC.grapid(z=3))

            i = 0
            while i > -cent[
                    0]:  #While i is lower than center coordinate, inverted for easier math
                i -= spacX  #Add line spacing

                #Draw lines left of the center
                block.append(
                    CNC.grapid(mapc(i + cent[0], 0),
                               mapc(cent[1], 1) + lin / 2))
                block.append(CNC.grapid(z=0))
                block.append(
                    CNC.gline(mapc(i + cent[0], 0),
                              mapc(cent[1], 1) - lin / 2))
                block.append(CNC.grapid(z=3))

            #Y axis number lines
            i = 0
            while i < ran[1] - cent[
                    1]:  #While i is between the center and the arrow
                i += spacX  #Add line spacing

                #Draw lines top of the center (everything just inverted)
                block.append(
                    CNC.grapid(
                        mapc(cent[0], 0) + lin / 2, mapc(i + cent[1], 1)))
                block.append(CNC.grapid(z=0))
                block.append(
                    CNC.gline(
                        mapc(cent[0], 0) - lin / 2, mapc(i + cent[1], 1)))
                block.append(CNC.grapid(z=3))

            i = 0
            while i > -1 * cent[1]:
                i -= spacX  #Add line spacing

                #Draw lines bottom of the center
                block.append(
                    CNC.grapid(
                        mapc(cent[0], 0) + lin / 2, mapc(i + cent[1], 1)))
                block.append(CNC.grapid(z=0))
                block.append(
                    CNC.gline(
                        mapc(cent[0], 0) - lin / 2, mapc(i + cent[1], 1)))
                block.append(CNC.grapid(z=3))

            raised = True  #Z was raised

        #Draw graph
        for i, item in enumerate(Y):
            if not Y[i] is None:
                x = mapc(X[i] + cent[0], 0)  #Take an argument
                y = mapc(Y[i] + cent[1], 1)  #Take a value
            else:
                y = Y[i]  #only for tne None checks next

            if y is None and not raised:  #If a None "period" just started raise Z
                raised = True
                block.append(CNC.grapid(z=3))
            elif not y is None and raised:  #If Z was raised and the None "period" ended move to new coordinates
                block.append(CNC.grapid(round(x, 2), round(y, 2)))
                block.append(CNC.grapid(z=0))  #Lower Z
                raised = False
            elif not y is None and not raised:  #Nothing to do with Nones? Just draw
                block.append(CNC.gline(round(x, 2), round(y, 2)))

        block.append(CNC.grapid(z=3))  #Raise on the end

        blocks.append(block)
        active = app.activeBlock()
        app.gcode.insBlocks(active, blocks, 'Function inserted'
                            )  #insert blocks over active block in the editor
        app.refresh()  #refresh editor
        app.setStatus(_('Generated function graph'))  #feed back result
        print()
Exemple #42
0
    def execute(self, app):
        name = self['name']

        if not name or name == 'default':
            name = 'Function'

        # Initialize blocks that will contain our gCode
        blocks = []
        block = Block(name)

        #Variable definitions
        formula = self['form']
        res = self['res']  # X resolution
        ran = [self['ranX'], self['ranY']]  # Range of X,Y, from -10, to 10 range is 20
        cent = [self['centX'], self['centY']]  # Coordinates X,Y of the center from bottom left of the coordinate system
        dim = [self['dimX'], self['dimY']]  # Real dimensions in gcode units
        spacX = self['spacX']  # Spacing of X axis lines
        spacY = self['spacY']  # Spacing of Y axis lines
        lin = self['lin']  # Small value - length of a line in gcode units
        draw = self['draw']  # Draw the coordinate system

        block.append("(Generated with a script by kswiorek)\n")
        block.append("(Equation: " + formula +")\n")
        block.append("(Resolution: " + str(res) +")\n")
        block.append("(Range: " + str(ran) +")\n")
        block.append("(Center: " + str(cent) +")\n")
        block.append("(Dimensions: " + str(dim) +")\n")
        block.append("(SpacingXY: " + str(spacX) +", " + str(spacY) +")\n")

        def mapc(var, axis): #Map coordinate systems
            return (var * (dim[axis]/ran[axis]))

        #Define coordinate system mins and maxes
        minX = -cent[0]
        maxX = ran[0]-cent[0]

        minY = -cent[1]
        maxY = ran[1]-cent[1]

        #Define domain and codomain
        X = []
        Y = []

        e_old = "" #Store old exception to comapre

        #Calculate values for arguments with a resolution
        for i in range(0, int(ran[0]/res+1)): #Complaints about values beeing floats
            x = i*res + minX #Iterate x
            X.append(x)
            try:
                Y.append(eval(formula))

            except Exception as exc: #Append None, not to loose sync with X
                Y.append(None)
                e = str(exc)
                if e != e_old: #If there is a different exception - display it
                    print("Warning: " + str(e))
                    app.setStatus(_("Warning: " + str(e)))
                    e_old = e

        raised = True # Z axis is raised at start

        #Clip values out of bounds, replace with None, not to loose sync with X
        for i, item in enumerate(Y):
            y = Y[i]
            if not y is None and (y < minY or y > maxY):
                Y[i] = None

        #Y without "None", min() and max() can't compare them
        Ynn = [] #Y no Nones
        for i, item in enumerate(Y):
            if not Y[i] is None:
                Ynn.append(Y[i])

        block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])])) #Set feedrate

        if draw: #If the user selected to draw the coordinate system
            #X axis
            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(0, mapc(cent[1], 1))) #1st point of X axis line
            block.append(CNC.grapid(z=0))

            block.append(CNC.gline(dim[0] + lin*1.2, mapc(cent[1], 1))) #End of X axis line + a bit more for the arrow

            block.append(CNC.gline(dim[0] - lin/2, mapc(cent[1], 1) - lin / 2)) #bottom part of the arrow

            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(dim[0] + lin*1.2, mapc(cent[1], 1), 0)) #End of X axis line
            block.append(CNC.grapid(z=0))

            block.append(CNC.gline(dim[0] - lin/2, mapc(cent[1], 1) + lin / 2)) #top part of the arrow
            block.append(CNC.grapid(z=3))

            #Y axis, just inverted x with y
            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(mapc(cent[0], 0), 0)) #1st point of Y axis line
            block.append(CNC.grapid(z=0))

            block.append(CNC.gline(mapc(cent[0], 0), dim[1] + lin*1.2)) #End of Y axis line + a bit more for the arrow

            block.append(CNC.gline(mapc(cent[0], 0) - lin / 2, dim[1] - lin/2)) #left part of the arrow

            block.append(CNC.grapid(z=3))
            block.append(CNC.grapid(mapc(cent[0], 0), dim[1] + lin*1.2)) #End of Y axis line
            block.append(CNC.grapid(z=0))

            block.append(CNC.gline(mapc(cent[0], 0) + lin / 2, dim[1] - lin/2)) #right part of the arrow
            block.append(CNC.grapid(z=3))

            #X axis number lines
            i = 0
            while i < ran[0] - cent[0]: #While i is on the left of the arrow
                i +=spacX #Add line spacing

                #Draw lines right of the center
                block.append(CNC.grapid(mapc(i+cent[0],0), mapc(cent[1], 1) + lin/2))
                block.append(CNC.grapid(z=0))
                block.append(CNC.gline(mapc(i+cent[0],0), mapc(cent[1], 1) - lin/2))
                block.append(CNC.grapid(z=3))

            i = 0
            while i > -cent[0]: #While i is lower than center coordinate, inverted for easier math
                i -=spacX #Add line spacing

                #Draw lines left of the center
                block.append(CNC.grapid(mapc(i+cent[0],0), mapc(cent[1], 1) + lin/2))
                block.append(CNC.grapid(z=0))
                block.append(CNC.gline(mapc(i+cent[0],0), mapc(cent[1], 1) - lin/2))
                block.append(CNC.grapid(z=3))

            #Y axis number lines
            i = 0
            while i < ran[1] - cent[1]: #While i is between the center and the arrow
                i +=spacX #Add line spacing

                #Draw lines top of the center (everything just inverted)
                block.append(CNC.grapid(mapc(cent[0], 0) + lin/2, mapc(i+cent[1],1)))
                block.append(CNC.grapid(z=0))
                block.append(CNC.gline(mapc(cent[0], 0) - lin/2, mapc(i+cent[1],1)))
                block.append(CNC.grapid(z=3))

            i = 0
            while i > -1*cent[1]:
                i -=spacX #Add line spacing

                #Draw lines bottom of the center
                block.append(CNC.grapid(mapc(cent[0], 0) + lin/2, mapc(i+cent[1],1)))
                block.append(CNC.grapid(z=0))
                block.append(CNC.gline(mapc(cent[0], 0) - lin/2, mapc(i+cent[1],1)))
                block.append(CNC.grapid(z=3))

            raised = True #Z was raised

        #Draw graph
        for i, item in enumerate(Y):
            if not Y[i] is None:
                x = mapc(X[i]+cent[0], 0) #Take an argument
                y = mapc(Y[i]+cent[1], 1) #Take a value
            else:
                y = Y[i] #only for tne None checks next

            if y is None and not raised: #If a None "period" just started raise Z
                raised = True
                block.append(CNC.grapid(z=3))
            elif not y is None and raised: #If Z was raised and the None "period" ended move to new coordinates
                block.append(CNC.grapid(round(x, 2),round(y, 2)))
                block.append(CNC.grapid(z=0)) #Lower Z
                raised = False
            elif not y is None and not raised: #Nothing to do with Nones? Just draw
                block.append(CNC.gline(round(x, 2),round(y, 2)))

        block.append(CNC.grapid(z=3)) #Raise on the end

        blocks.append(block)
        active = app.activeBlock()
        app.gcode.insBlocks(active, blocks, 'Function inserted')  #insert blocks over active block in the editor
        app.refresh()  #refresh editor
        app.setStatus(_('Generated function graph'))  #feed back result
        print()
Exemple #43
0
	def execute(self, app):

		#Get inputs
		fontSize      = self.fromMm("FontSize")
		depth         = self.fromMm("Depth")
		textToWrite   = self["Text"]
		fontFileName  = self["FontFile"]
		imageFileName = self["ImageToAscii"]
		charsWidth    = self["CharsWidth"]

		#Check parameters!!!
		if fontSize <=0:
			app.setStatus(_("Text abort: please input a Font size > 0"))
			return
		if fontFileName == "":
			app.setStatus(_("Text abort: please select a font file"))
			return
		if imageFileName != "":
			try:
				textToWrite = self.asciiArt(imageFileName,charsWidth)
			except:
				pass
		if textToWrite == "":
			textToWrite = "Nel mezzo del cammin di nostra vita..."
			return

		#Init blocks
		blocks = []
		n = self["name"]
		if not n or n == "default": n = "Text"
		block = Block(n)
		if(u'\n' in  textToWrite):
			block.append("(Text:)")
			for line in textToWrite.splitlines():
				block.append("(%s)" % line)
		else:
			block.append("(Text: %s)" % textToWrite)

		try:
			import ttf
			font = ttf.TruetypeInfo(fontFileName)
		except:
			app.setStatus(_("Text abort: That embarrassing, I can't read this font file!"))
			return
		cmap = font.get_character_map()

		kern = None
		try:
			kern = font.get_glyph_kernings()
		except:
			pass
		adv = font.get_glyph_advances()

		xOffset = 0
		yOffset = 0
		glyphIndxLast = cmap[' ']
		for c in textToWrite:
			#New line
			if c == u'\n':
				xOffset = 0.0
				yOffset -= 1#offset for new line
				continue

			if c in cmap:
				glyphIndx = cmap[c]

				if (kern and (glyphIndx,glyphIndxLast) in kern):
					k = kern[(glyphIndx,glyphIndxLast)] #FIXME: use kern for offset??

				#Get glyph contours as line segmentes and draw them
				gc = font.get_glyph_contours(glyphIndx)
				if(not gc):
					gc = font.get_glyph_contours(0)#standard glyph for missing glyphs (complex glyph)
				if(gc and not c==' '): #FIXME: for some reason space is not mapped correctly!!!
					self.writeGlyphContour(block, font, gc, fontSize, depth, xOffset, yOffset)

				if glyphIndx < len(adv):
					xOffset += adv[glyphIndx]
				else:
					xOffset += 1
				glyphIndxLast = glyphIndx

		#Remeber to close Font
		font.close()

		#Gcode Zsafe
		block.append(CNC.zsafe())

		blocks.append(block)
		active = app.activeBlock()
		if active==0: active=1
		app.gcode.insBlocks(active, blocks, "Text")
		app.refresh()
		app.setStatus("Generated Text")
Exemple #44
0
	def execute(self, app):
#		ae = self.fromMm("ae")
		if self["splicesteps"] =="" or self["splicesteps"]<4:
			steps=4/(2*pi)
		else:
			steps=self["splicesteps"]/(2*pi)

#		manualsetting = self["manualsetting"]
		manualsetting = 1
#=========== Converted to comment and changed for current compatibility ==============================
#		cutradius = CNC.vars["trochcutdiam"]/2.0
		cutradius = self["diam"]/2.0
#		cutradius = CNC.vars["trochcutdiam"]/2.0
#=========================================================================================
		zfeed = CNC.vars["cutfeedz"]
		feed =CNC.vars["cutfeed"]
		minimfeed =CNC.vars["cutfeed"]
		if manualsetting:
			if self["diam"]:
				cutradius = self["diam"]/2.0

			if self["zfeed"] and self["zfeed"]!="":
				zfeed = self["zfeed"]

#			if self["minimfeed"] and self["minimfeed"]!="":
#				minimfeed = min (self["minimfeed"],feed)

			if self["feed"] and self["feed"]!="":
				feed = self["feed"]
	
			if self["endmill"]:
				self.master["endmill"].makeCurrent(self["endmill"])



#		radius = CNC.vars["cutdiam"]/2.0
#		radius = self["diam"]/2.0
		toolRadius = CNC.vars["diameter"]/2.0
		radius = max(0,cutradius-toolRadius)
		oldradius=radius
#-----------------------------------------------------------
#		helicalRadius = self["helicalDiam"]/2.0
#		if helicalRadius=="":
#			helicalRadius=radius
#		else:
#			helicalRadius=max(0,helicalRadius- toolRadius)
		helicalRadius=radius
#-----------------------------------------------------------

#		helicalRadius=min(0.99*toolRadius,helicalRadius)
#		if radius!=0:
#			helicalRadius= min(helicalRadius,radius)
		helicalPerimeter=pi*2.0*helicalRadius		
	
	#	helicalangle = self["helicalangle"]
	#	if helicalangle>89.5:
	#		helicalangle=89.5
	#	if helicalangle<0.01:
	#		helicalangle=0.01
	#	downPecking=helicalPerimeter*tan(radians(helicalangle))

		cw = self["cw"]
		surface = CNC.vars["surface"]
#=========== Converted to comment and changed for current compatibility ==============================
#		zbeforecontact=surface+CNC.vars["zretract"]
#		zbeforecontact=surface+CNC.vars["zretract"]
#		hardcrust = surface - CNC.vars["hardcrust"]
#		feedbeforecontact = CNC.vars["feedbeforecontact"]/100.0
#		hardcrustfeed = CNC.vars["hardcrustfeed"]/100.0

		zbeforecontact=surface
		zbeforecontact=surface
		hardcrust = surface
		feedbeforecontact = zfeed
		hardcrustfeed = feed
#=====================================================================================================

		t_splice = self["TypeSplice"]
		dtadaptative = 0.0001
		adaptativepolice=0
#		minimradius = min(radius, toolRadius*self["MinTrochDiam"]/(100))
#		minimradius = min(radius, toolRadius*self["MinTrochDiam"]/(100))
#		minimradius = min(radius, toolRadius*CNC.vars["mintrochdiam"]/(100))
		atot = self.fromMm("ae")
#		spiral_twists=(radius-helicalRadius)/atot#<<spiral ae smaller than ae (aprox 50%)
#		if (radius-helicalRadius)%atot: spiral_twists=1+(radius-helicalRadius)//atot
		spiral_twists=ceil(radius-helicalRadius)/atot#<<spiral ae smaller than ae (aprox 50%)

		rpm = self["rpm"]

		downPecking=helicalPerimeter*zfeed/feed
		helicalangle=degrees(atan2(downPecking,helicalPerimeter))

#		steps=self["splicesteps"]/2*pi

#		K_Z = self["K_Z"]
#		if K_Z == "":
#			K_Z = 1.0
#		K_XY = self["K_XY"]
#		if K_XY == "": 
#			K_XY = 1.0
#		s_z = self["S_z"]
#		s_xy = self["S_xy"]
#		xyfeed = CNC.vars["cutfeed"]
#		zfeed *= K_Z
#		xyfeed *=K_XY		


		# Get selected blocks from editor
#	def trochprofile_bcnc(self, cutDiam=0.0, direction=None, offset=0.0, overcut=False,adaptative=False, adaptedRadius=0.0, tooldiameter=0.0, name=None):

#		app.trochprofile_bcnc(trochcutdiam, direction, self["offset"], self["overcut"], self["adaptative"], cornerradius, CNC.vars["diameter"], name) #<< diameter only to information
	#	cornerradius = (cutradius - CNC.vars["diameter"]/2.0
		direction=self["direction"]
		if direction!="on (3d Path)":
			targetDepth=self["targetDepth"]
			depthIncrement=self["depthIncrement"]
#			tabsnumber=self["tabsnumber"]
#			tabsWidth=self["tabsWidth"]
#			tabsHeight=self["tabsHeight"]
			tabsnumber=tabsWidth=tabsHeight=0

			app.trochprofile_bcnc(2*cutradius, direction,self["offset"], self["overcut"], self["adaptative"], radius, CNC.vars["diameter"],\
				targetDepth, depthIncrement, tabsnumber, tabsWidth, tabsHeight)
			app.refresh()
#		app.editor.selectAll()

		selBlocks = app.editor.getSelectedBlocks()
#		if not selBlocks:
#			app.editor.selectAll()
#			selBlocks = app.editor.getSelectedBlocks()

		if not selBlocks:
			app.setStatus(_("Trochoid abort: Please select some path"))
			return 
		#Check inputs
		if cutradius <= toolRadius:
				app.setStatus(_("Trochoid Cut Diameter has to be greater than End mill"))
				return

		if helicalRadius <= 0.0:
				app.setStatus(_("Helical Descent Diameter has to be greater than End mill"))
				return

		if feed <= 0:
				app.setStatus(_("Feed has to be greater than 0"))
				return

		if zfeed <= 0:
				app.setStatus(_("Plunge Feed has to be greater than 0"))
				return

		if minimfeed <= 0:
				app.setStatus(_("Minimum Adaptative Feed has to be greater than 0"))
				return

		#Get all segments from gcode
		allSegments = self.extractAllSegments(app,selBlocks)

		#Create holes locations
#		allHoles=[]
		for bidSegment in allSegments:
			if len(bidSegment)==0:
				continue
		blocks = []
#		n = self["name"]
#		if not n or n=="default": n="Trochoidal_3D"
#		newname = Block.operationName(path.name)
		n="Troch3d"
		tr_block = Block(n)
		phi=oldphi=0# oldadaptativephi=0
		oldsegm=[[0,0,0],[0,0,0]]

#		segments ---------------------------------------------
		for idx, segm in enumerate(bidSegment):
			if idx >= 0:
				if cw:
					u = 1
					arc = "G2"
				else:
					u = -1
					arc = "G3"				
#		////////////---------------------------------------------------------------------
#		information: ---------------------------------------------------------------------
				segLength = self.calcSegmentLength(segm)
	#			    ---------------------------------------------
	#				tr_block.append("(seg length "+str(round(segLength,4))+" )")
	#				-----------------------------------------------------------------------------
	#				////////----------------------------------------------------------------------
				if idx == 0:
#					tr_block.append("(--------------   PARAMETERS   ------------------------)")
					tr_block.append("(Cut diam "+str( cutradius*2 )+" (troch "+str(radius*2.0)+"+End mill "+str(toolRadius*2.0)+" ) Advance "+str(atot)+" )")
#					tr_block.append("(Cut diam "+str(CNC.vars["trochcutdiam"])+" (troch "+str(radius*2.0)+" + End mill " + str(toolRadius*2.0)+" ) Advance "+str(atot)+" )")
#					tr_block.append("(Min troch "+str(int(CNC.vars["mintrochdiam"]))+"%  = "+str(minimradius*2.0)+"mm , min cut diam "+str(2*(minimradius+toolRadius))+"mm )")
					tr_block.append("(Feed "+str(feed)+" Plunge feed "+ str(zfeed)+" )")
					#tr_block.append("(Helical diam "+str(round((helicalRadius+toolRadius)*2,2))+" ( helical diam "+str(helicalRadius*2.0)+"+End mill "+str(toolRadius*2.0)+" )")
					tr_block.append("(Helical descent angle " + str(round(helicalangle,2)) +" cut diam " + str(round(helicalRadius*2.0,3))+"  drop by lap "\
										+ str(round(downPecking,2)) + " )")
					tr_block.append("(--------------------------------------------------)")
					tr_block.append("(M06 T0 "+str(toolRadius*2.0)+" mm)")
					tr_block.append("M03")
					tr_block.append("S "+str(rpm))
					tr_block.append("F "+str(feed))
#					phi = atan2(segm[1][1]-segm[0][1], segm[1][0]-segm[0][0])
#					oldphi=phi #<< declare initial angle
#					l = self.pol2car(radius, phi+radians(90*u))
#					r = self.pol2car(radius, phi+radians(-90*u))
#					B = segm[1][0],segm[1][1],segm[1][2]
#					bl = self.pol2car(radius, phi+radians(90*u), B)
#					br = self.pol2car(radius, phi+radians(-90*u), B)
					tr_block.append("( Seg: "+str(idx)+"   length "+str(round(segLength,4))+"  phi "+str(round(degrees(phi),2))+" )")#+ "  oldphi  "+str(round(oldphi*57.29,2))+"   )")
					tr_block.append("(Starting point)")
					if (round(segm[1][1]-segm[0][1],4)==0 and round(segm[1][0]-segm[0][0],4)==0):
						phi=1234567890
						tr_block.append("(The original first movement is vertical)")
					else:
						tr_block.append("(The original first movement is not vertical)")
					tr_block.append(CNC.zsafe())
#					tr_block.append("g0 x "+str(B[0])+" y"+str(B[1])+" )")#" z "+str(B[2])+" )")
#							tr_block.append(arc+" x"+str(bl[0])+" y"+str(bl[1])+" R "+str(radius/2.0)+" z"+str(B[2]))
#					tr_block.append(arc+" x"+str(br[0])+" y"+str(br[1])+" i"+str(r[0]/2.0)+" j"+str(r[1]/2.0))	#<< as cutting					
#					tr_block.append(("g1 x "+str(br[0])+" y"+str(br[1])+" z"+str(B[2])))
#						tr_block.append(arc+" x"+str(bl[0])+" y"+str(bl[1])+" i"+str(l[0])+" j"+str(l[1]))						
#						tr_block.append(arc+" x"+str(br[0])+" y"+str(br[1])+" i"+str(r[0])+" j"+str(r[1])+" z"+str(round(B[2],5)))	#<< as cutting
#					if t_splice=="Circular both sides rectified":
#						tr_block.append(arc+" x"+str(bl[0])+" y"+str(bl[1])+" i"+str(-r[0])+" j"+str(-r[1]))						
					tr_block.append("(--------------------------------------------------)")

#						tr_block.append(CNC.grapid(br[0],br[1],B[2]))
#						tr_block.append(CNC.zsafe()) 			#<<< Move rapid Z axis to the safe height in Stock Material
#						tr_block.append(CNC.zenter(surface)) # <<< TROCHOID CENTER
#						tr_block.append(CNC.grapid(segm[1][0],segm[1][1],segm[1][2]))
#						tr_block.append(CNC.zbeforecontact()) # <<< TROCHOID CENTER
#						tr_block.append(CNC.xyslowentersurface(0,-45.0)) # <<< TROCHOID CENTER
#						tr_block.append(("g0 z "+str(zbeforecontact)))
#				tr_block.append("( new segment begins )")
	#					distance to trochoid center

					# if there is movement in xy plane phi calculate
				if (segm[1][1]-segm[0][1]!=0 or segm[1][0]-segm[0][0]!=0):
					phi = atan2(segm[1][1]-segm[0][1], segm[1][0]-segm[0][0])
#					On surface
#					if segm[0][2]>zbeforecontact and segm[1][2]>zbeforecontact:
					if segm[0][2]>surface and segm[1][2]>surface:
						tr_block.append("(Seg: "+str(idx)+" length "+str(round(segLength,4))+" phi "+str(round(degrees(phi),2))+ " On Surface)" )
						tr_block.append(CNC.grapid(segm[1][0],segm[1][1],segm[1][2]))
					else:
						tr_distance = self.center_distance(segm,atot)
						A = segm[0][0],segm[0][1],segm[0][2]
						d=segLength
						ae = tr_distance[4]
	#				////////////---------------------------------------------------------------------
	#				information: ---------------------------------------------------------------------
						adv = tr_distance[3] #<<< 
						ap = tr_distance[2] # << =zadd
	#			    ---------------------------------------------
						tr_block.append("(-----------------------------------------)")
						control_cameback = self.came_back(segm, oldsegm)
						if control_cameback:
							tr_block.append("(-------------> Came back !! <------------- )")#+str(control_cameback)+" )")
	#						tr_block.append("( old  Ax "+str(round(oldsegm[0][0],3))+" Ay "+str(round(oldsegm[0][1],3))+" Bx "+ str(round(oldsegm[1][0],3))+" By "+ str(round(oldsegm[1][1],3))+" )")
	#						tr_block.append("( curr Ax "+str(round(segm[0][0],3))+" Ay "+str(round(segm[0][1],3))+" Bx "+ str(round(segm[1][0],3))+" By "+ str(round(segm[1][1],3))+" )")
						if round(segLength,5) <= dtadaptative:
							adaptativepolice+=1.0
							tr_block.append("(Seg "+str(idx)+" adaptativepolice " +str(adaptativepolice)+" length "+str(round(segLength,5))+" )")
#	///////////	Trochoid method //////////////////////////////////////////////////////////////////////////////
						if adaptativepolice==0 or adaptativepolice >2.5:

							tr_block.append("( Seg: "+str(idx)+" phi "+str(round(degrees(phi),2))+ " oldphi "+str(round(degrees(oldphi),2))+" length "+str(round(segLength,5))+" )")
							tr_block.append("(ae: "+str(round(ae,5))+" dz: "+str(round(ap,4))+"adv: "+str(round(adv,4))+" )")
		#					tr_block.append("( Bx "+str(round(segm[1][0],2))+ " By "+ str(round(segm[1][1],2)))
		#					-----------------------------------------------------------------------------
		#					////////----------------------------------------------------------------------
							if control_cameback:
		#						adaptativepolice+=0.5
								B = segm[1][0],segm[1][1],segm[1][2]
		#								tr_block.append(CNC.gline(segm[1][0],segm[1][1],segm[1][2]))
								t_splice="came_back"
#								tr_block.extend(self.trochoid(t_splice,A,B,minimradius,radius,oldphi,phi,cw))
								tr_block.extend(self.trochoid(t_splice,A,B,0.0,radius,oldphi,phi,cw))
								tr_block.append("F "+ str(feed))
								t_splice = self["TypeSplice"]

							else:
								# from POINT A -- to ---> POINT B
								if segLength<=adv:
									tr_block.append("(Only one trochoid, oldphi "+str(round(degrees(oldphi),2))+" )")
									tr_block.extend(self.trochoid(t_splice,A,B,oldradius,radius,oldphi,phi,cw))
								while d >adv:
			#					first trochoid
			#						tr_block.append("d "+ str(d))
									B = A[0]+tr_distance[0], A[1]+tr_distance[1], A[2]+tr_distance[2]
								# intermediates points = trochoids points 
			#						tr_block.append(CNC.gline(B[0],B[1],B[2])) # <<< TROCHOID CENTER
		#							tr_block.extend(self.trochoid(A,B,radius,phi,oldphi,cw))

									tr_block.append("(distance to end segment "+str(round(d,4))+" )")
									tr_block.extend(self.trochoid(t_splice,A,B,oldradius,radius,oldphi,phi,cw))
									A=B
									d-=adv
									oldphi=phi
			#					last point
								if  B[0] != segm[1][0] or B[1] != segm[1][1] or B[2] != segm[1][2]:
									B = segm[1][0],segm[1][1],segm[1][2]
			#						tr_block.append(CNC.gline(B[0],B[1],B[2]))  # <<< TROCHOID CENTER
									tr_block.append("(---last trochoid, distance to end segment "+str(round(d,4))+" ---)")
									tr_block.extend(self.trochoid(t_splice,A,B,oldradius,radius,phi,phi,cw))
							adaptativepolice=0

		#	///////	Adapative method //////////////////////////////////////////////////////////////////////////////////////////////////////////
#						if oldphi==3600:
						else:
							if adaptativepolice==1:
								#goes to de two warning movements 
								lastphi=oldphi
								tr_block.append("( Alarm "+ str(adaptativepolice)+"  Seg: "+str(idx)+" phi " + str(round(degrees(phi),2))\
												 + "oldphi "+str(round(degrees(oldphi),2))+ " )")
	#							difangle=(phi-oldadaptativephi)
	#							tr_block.append("(dif angle:"+str(round(difangle,4))+" )")
	#							oldadaptativephi=oldphi=phi
								# round(difangle,5)==round(pi,5):
							elif adaptativepolice==2:
								phi=lastphi
								if control_cameback:# abs(round(difangle,6)) == (round(pi,6)):
									tr_block.append("(Starts adaptative trochoids"+" adaptativepolice "+str(adaptativepolice) )
									adaptativepolice +=0.5
							elif adaptativepolice==2.5:
#								tr_block.append("(-----------------------------------------)")
#								adaptradius=minimradius
								tr_block.append("(Adaptative Seg: "+str(idx)+"   length "+str(round(segLength,5))+"  phi "+str(round(degrees(phi),2))\
												+" oldphi "+str(round(degrees(oldphi),2))+" )")
#								tr_block.append("( Ax "+str(round(segm[0][0],2))+ " Ay "+ str(round(segm[0][1],2)))

#								tr_block.append(CNC.gline(segm[1][0],segm[1][1],segm[1][2]))
								# from POINT A -- to ---> POINT B
#								if adaptativepolice==1:
								tr_distance = self.center_distance(segm,atot/3.0) #<<< short advanc distances 

								A = segm[0][0],segm[0][1],segm[0][2]
								d=segLength
								ae = tr_distance[4]
								adv = tr_distance[3] #<<< 
								d-=adv
								while d >0:#adv:
			#					first trochoid
									if d!=segLength-adv:
										oldphi=phi
			#						tr_block.append("d "+ str(d))
									B = A[0]+tr_distance[0], A[1]+tr_distance[1], A[2]+tr_distance[2]
									#------------------------------
									# adaptradius= a*d + minimradius
									# if d=0 : adaptradius=minimradius
									# if d=seglength : adaptradius=radius
#									a=(radius-minimradius)/segLength
#									adaptradius=a*d+minimradius
									a=radius/segLength
									adaptradius=(self.roundup(a*d,4))#+minimradius
												#------------------------------
									if t_splice!="Splices":
										t_splice="Warpedarc"
									tr_block.append("(from trochoid distance to end segment "+str(round(d,4))+" )")
									tr_block.append("(adaptradius "+ str(round(adaptradius,4))+" radius " + str(radius)+" )")
#									tr_block.append("F "+ str(feed*adaptradius//radius))
									tr_block.append("F "+ str(minimfeed+(feed-minimfeed) *adaptradius//radius))
									if adaptradius>0.0:
										tr_block.extend(self.trochoid(t_splice,A,B,oldradius,adaptradius,oldphi,phi,cw))
									else:
										tr_block.append("(R= "+str(adaptradius)+ "not sent )")
#										tr_block.append("G1 x"+str(round(B[0],4))+" y "+str(round(B[1],4))+" z "+str(round(B[2],4)))
									A=B
									d-=adv
									oldradius=adaptradius
#										oldadaptativephi=0
			#REVISAR, A COMENTADO
			#					last point
					#			d=0
					#			oldradius=adaptradius
					#			adaptradius=minimradius
					#			if  B[0] != segm[1][0] or B[1] != segm[1][1] or B[2] != segm[1][2]:
					#				B = segm[1][0],segm[1][1],segm[1][2]
			#						tr_block.append(CNC.gline(B[0],B[1],B[2]))  # <<< TROCHOID CENTER
					#				tr_block.append("(last trochoid, from trochoid distance to end segment "+str(round(d,4))+" )")
					#				tr_block.append("(adaptradius "+ str(adaptradius)+" )")
					#				tr_block.append("F "+ str(feed*adaptradius//radius))
					#				tr_block.extend(self.trochoid(t_splice,A,B,oldradius,adaptradius,phi,phi,cw))

								adaptativepolice=0
								tr_block.append("(Adaptative Completed)")
								tr_block.append("F "+ str(feed//3))

#								if adaptativepolice>1:
							t_splice = self["TypeSplice"]
#							adaptativepolice=0
							oldradius=radius
						oldsegm=segm
					oldphi=phi
#	///////	Vertical movement ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
				elif idx!=0:	
					tr_block.append("(Seg: "+str(idx)+" length "+str(round(segLength,4))+" phi "+str(round(degrees(phi),2))+" oldphi "+str(round(degrees(oldphi),2))+" )" )
					tr_block.append("(Helical descent")
#						descent
					A=segm[0][0],segm[0][1],segm[0][2]
					if segm[0][2] > segm[1][2]:
						if segm[0][2] >zbeforecontact:# and segm[1][2]<=surface:
							if segm[1][2]<=zbeforecontact:
								B = segm[1][0],segm[1][1],max(segm[1][2],zbeforecontact)
								tr_block.append("(Rapid helical to z before contact "+"helicalRadius "+str(helicalRadius)+" )")
								if idx==1 and oldphi==1234567890:
									tr_block.append("g0 x "+str(B[0])+" y"+str(B[1])+" )")#" z "+str(B[2])+" )")
								tr_block.extend(self.helical(A,B,helicalRadius,phi,u))

	#						Instead of decreasing the speed, to avoid the jerkl, decrease the drop by lap
						if segm[0][2] >surface:# and segm[1][2]<=surface:
							if segm[1][2]<=surface:
								tr_block.append("(Slow helical to surface )" )
								A=A[0],A[1],zbeforecontact
								d=A[2]-surface
								adv=downPecking * feedbeforecontact
								while d > adv:
									B = segm[1][0],segm[1][1],max(segm[1][2],A[2]-adv)
									tr_block.extend(self.helical(A,B,helicalRadius,phi,u))
									A=A[0],A[1],B[2]
									d-=adv
								B = segm[1][0],segm[1][1],surface
								tr_block.extend(self.helical(A,B,helicalRadius,phi,u))

						if segm[0][2] >hardcrust:# and segm[1][2]<=surface:
							if hardcrust< surface:
								if segm[1][2]<=hardcrust:	
									tr_block.append("(Helical in hard crust)" )
									A=A[0],A[1],surface
									d=A[2]-hardcrust
									adv=downPecking * hardcrustfeed
									while d > adv:
										B = segm[1][0],segm[1][1],max(segm[1][2],A[2]-adv)
										tr_block.extend(self.helical(A,B,helicalRadius,phi,u))
										A=A[0],A[1],B[2]
										d-=adv
									B = segm[1][0],segm[1][1],hardcrust
									tr_block.extend(self.helical(A,B,helicalRadius,phi,u))
						
						tr_block.append("(Helical to target )" )
						A=A[0],A[1],hardcrust
						d=A[2]-segm[1][2]
						adv=downPecking
						while d > adv:
							B = segm[1][0],segm[1][1],A[2]-adv
							tr_block.extend(self.helical(A,B,helicalRadius,phi,u))
							A=A[0],A[1],B[2]
							d-=adv
						B = segm[1][0],segm[1][1],segm[1][2]
						tr_block.extend(self.helical(A,B,helicalRadius,phi,u))
						tr_block.append("(Flatten)")
						tr_block.extend(self.helical(B,B,helicalRadius,phi,u))
						if round(helicalRadius,4)!=round(radius,4):
							tr_block.append("(Spiral adjustement)")
	#								tr_block.extend(self.trochoid(t_splice,B,B,radius,helicalRadius,phi,phi+4*pi,cw))
	#						steps=max(1,int(steps*radius*(spiral_twists)/2.0))
	#						steps=min(steps, 12*spiral_twists)
	#						steps*=spiral_twists
#							tr_block.append("(Spiral steps "+str(steps)+" in "+str(int((spiral_twists/2.)+1))+" twists)")
#							tr_block.append("(Spiral "+str(int((spiral_twists/2.)+1))+" twists)")
							tr_block.append("(Spiral "+str(spiral_twists)+" twists)")
							tr_block.extend(self.splice_generator(B,B,helicalRadius,radius,phi,phi-spiral_twists*2*pi, radians(-90),radians(-90),u,1.2*steps))
							tr_block.append("(Target diameter)")
#							tr_block.extend(self.helical(B,B,radius,phi,u))
							tr_block.extend(self.trochoid(t_splice,B,B,radius,radius,phi,phi,cw))

#						ascent
					elif segm[1][2] > segm[0][2]:
						tr_block.append("(Helical rapid ascentt "+"helicalRadius "+str(helicalRadius)+" )" )
						B = segm[1][0],segm[1][1],segm[1][2]
						tr_block.extend(self.helical(A,B,helicalRadius,phi,u))
	#					tr_block.append(CNC.grapid(center[0],center[1],center[2]))
	#					tr_block.extend(CNC.grapid(center))
	#					end of segment
	#					tr_block.append(CNC.gline(segm[1][0],segm[1][1],segm[1][2]))
#					oldsegm=segm
		tr_block.append("(-----------------------------------------)")
		tr_block.append(CNC.zsafe()) 			#<<< Move rapid Z axis to the safe height in Stock Material
		blocks.append(tr_block)
		self.finish_blocks(app, blocks)
Exemple #45
0
	def make(self,app, XStart=0.0, YStart=0.0, ZStart=30., AlignAxis="Y", \
			RotAxis="A", StockLeng=20, ReduceDepth=-1, PassDepth=1, \
			Stepover=1, ZApproach=35, SpiralType="Spiral", CutBoth="True", LiftPass="******"):

		#GCode Blocks
		blocks = []
		
		# Load tool and material settings
		toolDiam = CNC.vars['diameter']
		toolRadius = toolDiam / 2.

		#Calc tool diameter with Maximum Step Over allowed
		StepOverInUnitMax = toolDiam * CNC.vars['stepover'] / 100.0		

		#Check parameters
		if RotAxis == "":
			app.setStatus(_("Spiral abort: Rotary Axis is undefined"))
			return

		if SpiralType == "":
			app.setStatus(_("Spiral abort: Spiral Type is undefined"))
			return

		if ZApproach <= ZStart :
			app.setStatus(_("Spiral abort: Approach height must be greater than Z Start"))
			return

		if ReduceDepth > 0 :
			app.setStatus(_("Spiral abort: Depth Reduction must be negative"))
			return

		if Stepover > StepOverInUnitMax and SpiralType == "Spiral":  #if Type is Lines then stepover is degrees not mm
			app.setStatus(_("Spiral abort: Step Over exceeds tool limits"))
			return 
		elif Stepover > StepOverInUnitMax and SpiralType == "Lines":  # This could cause a tool crash, but could also be used to make faceted shapes.
			dr=tkMessageBox.askyesno("Crash Risk","WARNING: Using a larger stepover value than tool's maximum with lines operation may result in a tool crash. Do you want to continue?")
			sys.stdout.write("%s"%(dr))
			if dr == True or dr == "yes" :
				app.setStatus(_("Risk Accepted")) #Using positive logic, if python returns ANYTHING other than True/yes this will not make g-code.  Incase Python uses No instead of False
			else:
				return
		if StockLeng <= 0 :
			app.setStatus(_("Spiral abort: Stock Length to cut must be positive"))
			return
			

		#Add Region disabled to show worked area
		block = Block(self.name + " Outline")
		block.enable = False
		block.append(CNC.grapid(CNC.vars["wx"],CNC.vars["wy"],ZApproach))  ## Cannot trust Safe-Z with 4th axis!!
		if AlignAxis == "X":
			outlineWidth = StockLeng
		else:
			outlineWidth = 0
		if AlignAxis == "Y":
			outlineHeight = StockLeng
		else:
			outlineHeight = 0
		xR,yR = self.RectPath(XStart,YStart,outlineWidth,outlineHeight)
		for x,y in zip(xR,yR):
			block.append(CNC.gline(x,y))
		blocks.append(block)

		
		if StockLeng < toolDiam :
			app.setStatus(_("Spiral abort: Stock Length is too small for this End Mill."))
			return

		#Prepare points for pocketing
		xP=[]
		yP=[]
		rP=[]
		zP=[]
		gP=[]
        

        #---------------------------------------------------------------------
        #Line approach
		if SpiralType == "Lines":
			#Calc number of indexes
			IndexNum = math.ceil(360/Stepover) # Using the step over as Degrees 
						

			#Calc number of pass
			VerticalCount = math.ceil(abs(ReduceDepth) / PassDepth)
			#Calc even depths of cut
			EvenCutDepths = ReduceDepth / VerticalCount
			
			currentR = 0
			currentZ = ZStart - EvenCutDepths
			direction = 1
			if AlignAxis == "X" :
				currentX = XStart + toolRadius
				currentY = YStart
			elif AlignAxis == "Y":
				currentX = XStart
				currentY = YStart + toolRadius
			else:
				app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
				return			
			
			while (currentZ >= (ZStart + ReduceDepth)):
				#sys.stdout.write("~~~~~%s,%s,%s,%s,%s!"%(currentZ,ZStart,ReduceDepth,EvenCutDepths,VerticalCount))
				while (currentR < 360):
					#sys.stdout.write("~~~~~%s,%s,%s,%s,%s!"%(currentR,Stepover,currentX,currentY,VerticalCount))

					#Plunge in
					gP.append(1)
					rP.append(currentR)
					zP.append(currentZ)			
					xP.append(currentX)
					yP.append(currentY)
					if direction == 1:
						if AlignAxis == "X" :
							currentX = StockLeng - toolRadius
							currentY = YStart
						elif AlignAxis == "Y":
							currentX = XStart
							currentY = StockLeng - toolRadius
						else:
							app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
							return
						if CutBoth == "True" :
							direction = -1
					else :
						if AlignAxis == "X" :
							currentX = XStart + toolRadius
							currentY = YStart
						elif AlignAxis == "Y":
							currentX = XStart
							currentY = YStart + toolRadius
						else:
							app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
							return
						direction = 1
					gP.append(1)
					zP.append(currentZ)			
					xP.append(currentX)
					yP.append(currentY)
					rP.append(currentR)
					# Lift before rotating if required, useful to make non-round shape

					if CutBoth == "False" : # Return to start
					
						#Lift Before return
						gP.append(0)
						rP.append(currentR)
						zP.append(ZApproach)
						xP.append(currentX)
						yP.append(currentY)

						#Return to start
						if AlignAxis == "X" :
							currentX = XStart + toolRadius
							currentY = YStart
						elif AlignAxis == "Y":
							currentX = XStart
							currentY = YStart + toolRadius
						else:
							app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
							return
						gP.append(0)
						xP.append(currentX)
						yP.append(currentY)
						rP.append(currentR)
						zP.append(ZApproach)
						#Rotate
						currentR += Stepover
						gP.append(0)
						xP.append(currentX)
						yP.append(currentY)
						rP.append(currentR)
						zP.append(ZApproach)
					elif LiftPass == "True" and CutBoth == "True" :
						gP.append(0)
						rP.append(currentR)
						zP.append(ZApproach)
						xP.append(currentX)
						yP.append(currentY)
						currentR += Stepover
						gP.append(0)
						xP.append(currentX)
						yP.append(currentY)
						rP.append(currentR)
						zP.append(ZApproach)
					elif LiftPass == "False" and CutBoth == "True" :
						currentR += Stepover
				gP.append(0)
				xP.append(currentX)
				yP.append(currentY)
				rP.append(currentR)
				zP.append(ZApproach)
				currentR=0
				gP.append(0)
				xP.append(currentX)
				yP.append(currentY)
				rP.append(currentR)
				zP.append(ZApproach)		

					
					
					
				#Step Down
				currentZ += EvenCutDepths			

		#---------------------------------------------------------------------
        #Spiral approach
		if SpiralType == "Spiral":
			#Calc number of pass
			StepsPerRot = math.ceil(StockLeng/Stepover)
			TotalRot = 360 * StepsPerRot
			
			#Calc steps in depth
			VerticalCount = math.ceil(abs(ReduceDepth) / PassDepth)
			#Calc even depths of cut
			EvenCutDepths = ReduceDepth / VerticalCount			
			
			direction = 1
			currentZ = ZStart - EvenCutDepths
			if AlignAxis == "X" :
				currentX = XStart + toolRadius
				currentY = YStart
			elif AlignAxis == "Y":
				currentX = XStart
				currentY = YStart + toolRadius
			else:
				app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
				return
			currentR = 0
			while (currentZ >= (ZStart + ReduceDepth)):
				
				# Plunge to depth
				currentR += 90 # Ramp the Plunge
				gP.append(1)
				rP.append(currentR)
				zP.append(currentZ)			
				xP.append(currentX)
				yP.append(currentY)
				
				# One Full Rotation for a clean shoulder
				currentR += 360
				gP.append(1)
				rP.append(currentR)
				zP.append(currentZ)			
				xP.append(currentX)
				yP.append(currentY)
				
				
				if AlignAxis == "X" :
					if direction == 1:
						currentX = StockLeng - toolRadius
					else:
						currentX = XStart + toolRadius
					currentY = YStart
				elif AlignAxis == "Y":
					currentX = XStart
					if direction == 1:
						currentY = StockLeng - toolRadius
					else:
						currentY = YStart + toolRadius
				else:
					app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
					return
					
				currentR += TotalRot
				gP.append(1)
				rP.append(currentR)
				zP.append(currentZ)			
				xP.append(currentX)
				yP.append(currentY)
				
				# One Full Rotation for a clean shoulder
				currentR += 360
				gP.append(1)
				rP.append(currentR)
				zP.append(currentZ)			
				xP.append(currentX)
				yP.append(currentY)
				
				if CutBoth == "True" : 
					direction *=  - 1
				else:
					#Retract
					gP.append(0)
					rP.append(currentR)
					zP.append(ZApproach)			
					xP.append(currentX)
					yP.append(currentY)
					# Return and Rewind
					gP.append(0)
					rP.append(currentR)
					zP.append(ZApproach)
					if AlignAxis == "X" :
						currentX = XStart + toolRadius
						currentY = YStart
					elif AlignAxis == "Y":
						currentX = XStart
						currentY = YStart + toolRadius
					else:
						app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
						return
					xP.append(currentX)
					yP.append(currentY)
				
				
				currentZ += EvenCutDepths
				

#Start G-Code Processes
		#Blocks for pocketing
		block = Block(self.name)
		block.append("(Reduce Rotary by Y=%g)"%(ReduceDepth))
		block.append("(Approach: %s )" % (SpiralType))

		#Move safe to first point
		block.append(CNC.grapid(CNC.vars["mx"],CNC.vars["my"],ZApproach))  ## Cannot trust Safe-Z with 4th axis!!
		if AlignAxis == "X" :
			block.append(CNC.grapid(XStart + toolRadius,YStart))
		elif AlignAxis == "Y":
			block.append(CNC.grapid(XStart,YStart + toolRadius))
		else:
			app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
			return
		
		block.append(CNC.zenter(ZApproach))
		block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
		
		for g,x,y,z,r in zip(gP, xP,yP,zP, rP):
			if RotAxis == "A" :
				if g==0:
					block.append(CNC.grapidABC(x,y,z,r,CNC.vars["wb"],CNC.vars["wc"]))
					#sys.stdout.write("%s,%s,%s,%s,%s"%(g,x,y,z,r))
				else:
					block.append(CNC.glineABC(x,y,z,r,CNC.vars["wb"],CNC.vars["wc"]))
					#sys.stdout.write("%s,%s,%s,%s,%s"%(g,x,y,z,r))
			elif RotAxis == "B" :
				if g==0:
					block.append(CNC.grapidABC(x,y,z,CNC.vars["wa"],r,CNC.vars["wc"]))
				else:
					block.append(CNC.glineABC(x,y,z,CNC.vars["wa"],r,CNC.vars["wc"]))
			elif RotAxis == "C" :
				if g==0:
					block.append(CNC.grapidABC(x,y,z,CNC.vars["wa"],CNC.vars["wb"],r))
				else:
					block.append(CNC.glineABC(x,y,z,CNC.vars["wa"],CNC.vars["wb"],r))

			
		block.append(CNC.grapid(CNC.vars["wx"],CNC.vars["wy"],ZApproach))  ## Cannot trust Safe-Z with 4th axis!!
		if AlignAxis == "X" :
			block.append(CNC.grapid(XStart + toolRadius,YStart))
		elif AlignAxis == "Y":
			block.append(CNC.grapid(XStart,YStart + toolRadius))
		else:
			app.setStatus(_("Spiral abort: Rotary Axis Not Assigned."))
			return
		block.append(CNC.zexit(ZApproach))
		blocks.append(block)
		tkMessageBox.showinfo("Crash Risk","WARNING: Check CAM file Header for Z move. If it exists, remove it to prevent tool crash.")

		return blocks
Exemple #46
0
	def execute(self, app):
		if Image is None:
			app.setStatus(_("Halftone abort: This plugin requires PIL/Pillow to read image data"))
			return

		n = self["name"]
		if not n or n=="default": n="Halftone"

		#Calc desired size
		channel = self["Channel"]
		invert = self["Invert"]
		drawSize = self["DrawSize"]
		cellSize = self["CellSize"]
		dMax = self["DiameterMax"]
		dMin = self["DiameterMin"]
		angle = self["Angle"]
		drawBorder = self["DrawBorder"]
		depth = self["Depth"]
		conical = self["Conical"]

		#Check parameters
		if drawSize < 1:
			app.setStatus(_("Halftone abort: Size too small to draw anything!"))
			return

		if dMin > dMax:
			app.setStatus(_("Halftone abort: Minimum diameter must be minor then Maximum"))
			return

		if dMax < 1:
			app.setStatus(_("Halftone abort: Maximum diameter too small"))
			return

		if cellSize < 1:
			app.setStatus(_("Halftone abort: Cell size too small"))
			return

		tool = app.tools["EndMill"]
		tool_shape = tool["shape"]
		if conical:
			if tool_shape== "V-cutting":
				try:
					v_angle = float(tool["angle"])
				except:
					app.setStatus(_("Halftone abort: Angle in V-Cutting end mill is missing"))
					return
			else:
				app.setStatus(_("Halftone abort: Conical path need V-Cutting end mill"))
				return

		#Open picture file
		fileName = self["File"]
		try:
			img = Image.open(fileName)
		except:
			app.setStatus(_("Halftone abort: Can't read image file"))
			return

		#Create a scaled image to work faster with big image and better with small ones
		squareNorm = True
		if channel == 'Blue(sqrt)':
			img = img.convert('RGB')
			img = img.split()[0]
		elif channel == 'Green(sqrt)':
			img = img.convert('RGB')
			img = img.split()[1]
		elif channel == 'Red(sqrt)':
			img = img.convert('RGB')
			img = img.split()[2]
		else:
			img = img.convert ('L') #to calculate luminance
			squareNorm = False

		 #flip image to ouput correct coordinates
		img = img.transpose(Image.FLIP_TOP_BOTTOM)

		#Calc divisions for halftone
		divisions = drawSize / cellSize
		#Get image size
		self.imgWidth, self.imgHeight =  img.size
		if (self.imgWidth > self.imgHeight):
			scale = drawSize / float(self.imgWidth)
			sample = int(self.imgWidth / divisions)
		else:
			scale = drawSize / float(self.imgHeight)
			sample = int(self.imgHeight / divisions)
		self.ratio = scale

		#Halftone
		circles = self.halftone(img, sample, scale, angle, squareNorm, invert)

		#Init blocks
		blocks = []

		#Border block
		if drawBorder:
			block = Block("%s-border"%(self.name))
			block.append(CNC.zsafe())
			block.append(CNC.grapid(0,0))
			block.append(CNC.zenter(depth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			block.append(CNC.gline(self.imgWidth * self.ratio, 0))
			block.append(CNC.gline(self.imgWidth * self.ratio, self.imgHeight*self.ratio))
			block.append(CNC.gline(0, self.imgHeight*self.ratio))
			block.append(CNC.gline(0,0))
			blocks.append(block)

		#Draw block
		block = Block(self.name)

		#Change color
		if channel == 'Blue(sqrt)':
			block.color = "#0000ff"
		elif channel == 'Green(sqrt)':
			block.color = "#00ff00"
		elif channel == 'Red(sqrt)':
			block.color = "#ff0000"

		block.append("(Halftone size W=%d x H=%d x D=%d ,Total points:%i)" %
			 (self.imgWidth * self.ratio, self.imgHeight * self.ratio, depth, len(circles)))
		block.append("(Channel = %s)" % channel)

		for c in circles:
			x,y,r = c
			r = min(dMax/2.0,r)
			if (r >= dMin/2.):
				block.append(CNC.zsafe())
				block.append(CNC.grapid(x+r,y))
				block.append(CNC.zenter(depth))
				block.append(CNC.garc(CW,x+r,y,i=-r,))
		block.append(CNC.zsafe())
		if conical: block.enable = False
		blocks.append(block)

		if conical:
			blockCon = Block("%s-Conical"%(self.name))
			for c in circles:
				x,y,r = c
				blockCon.append(CNC.zsafe())
				blockCon.append(CNC.grapid(x,y))
				dv = r / math.tan(math.radians(v_angle/2.))
				blockCon.append(CNC.zenter(-dv))
			blockCon.append(CNC.zsafe())
			blocks.append(blockCon)

		#Gcode Zsafe
		active = app.activeBlock()
		app.gcode.insBlocks(active, blocks, "Halftone")
		app.refresh()
		app.setStatus(_("Generated Halftone size W=%d x H=%d x D=%d ,Total points:%i" %
			 (self.imgWidth * self.ratio, self.imgHeight * self.ratio, depth, len(circles))))
Exemple #47
0
    def execute(self, app):

        #Get inputs
        fontSize = self["FontSize"]
        depth = self["Depth"]
        textToWrite = self["Text"]
        fontFileName = self["FontFile"]
        imageFileName = self["ImageToAscii"]
        charsWidth = self["CharsWidth"]

        #Check parameters!!!
        if fontSize <= 0:
            app.setStatus(_("Text abort: please input a Font size > 0"))
            return
        if fontFileName == "":
            app.setStatus(_("Text abort: please select a font file"))
            return
        if imageFileName != "":
            try:
                textToWrite = self.asciiArt(imageFileName, charsWidth)
            except:
                pass
        if textToWrite == "":
            textToWrite = "Nel mezzo del cammin di nostra vita..."
            return

        #Init blocks
        blocks = []
        n = self["name"]
        if not n or n == "default": n = "Text"
        block = Block(n)
        if (u'\n' in textToWrite):
            block.append("(Text:)")
            for line in textToWrite.splitlines():
                block.append("(%s)" % line)
        else:
            block.append("(Text: %s)" % textToWrite)

        try:
            import ttf
            font = ttf.TruetypeInfo(fontFileName)
        except:
            app.setStatus(
                _("Text abort: That embarrassing, I can't read this font file!"
                  ))
            return
        cmap = font.get_character_map()

        kern = None
        try:
            kern = font.get_glyph_kernings()
        except:
            pass
        adv = font.get_glyph_advances()

        xOffset = 0
        yOffset = 0
        glyphIndxLast = cmap[' ']
        for c in textToWrite:
            #New line
            if c == u'\n':
                xOffset = 0.0
                yOffset -= 1  #offset for new line
                continue

            if c in cmap:
                glyphIndx = cmap[c]

                if (kern and (glyphIndx, glyphIndxLast) in kern):
                    k = kern[(glyphIndx,
                              glyphIndxLast)]  #FIXME: use kern for offset??

                #Get glyph contours as line segmentes and draw them
                gc = font.get_glyph_contours(glyphIndx)
                if (not gc):
                    gc = font.get_glyph_contours(
                        0)  #standard glyph for missing glyphs (complex glyph)
                if (
                        gc and not c == ' '
                ):  #FIXME: for some reason space is not mapped correctly!!!
                    self.writeGlyphContour(block, font, gc, fontSize, depth,
                                           xOffset, yOffset)

                if glyphIndx < len(adv):
                    xOffset += adv[glyphIndx]
                else:
                    xOffset += 1
                glyphIndxLast = glyphIndx

        #Remeber to close Font
        font.close()

        #Gcode Zsafe
        block.append(CNC.zsafe())

        blocks.append(block)
        active = app.activeBlock()
        app.gcode.insBlocks(active, blocks, "Text")
        app.refresh()
        app.setStatus("Generated Text")
	def execute(self, app):
		#Get inputs
		holesDistance = self.fromMm("HolesDistance")
		targetDepth = self.fromMm("TargetDepth")
		peck = self.fromMm("Peck")
		dwell = self["Dwell"]

		zSafe = CNC.vars["safe"]

		#Check inputs
		if holesDistance <=0:
			app.setStatus(_("Driller abort: Distance must be > 0"))
			return

		if peck <0:
			app.setStatus(_("Driller abort: Peck must be >= 0"))
			return

		if dwell <0:
			app.setStatus(_("Driller abort: Dwell time >= 0, here time runs only forward!"))
			return

		# Get selected blocks from editor
		selBlocks = app.editor.getSelectedBlocks()
		if not selBlocks:
			app.editor.selectAll()
			selBlocks = app.editor.getSelectedBlocks()

		if not selBlocks:
			app.setStatus(_("Driller abort: Please select some path"))
			return

		#Get all segments from gcode
		allSegments = self.extractAllSegments(app,selBlocks)

		#Create holes locations
		allHoles=[]
		for bidSegment in allSegments:
			if len(bidSegment)==0:
				continue

			#Summ all path length
			fullPathLength = 0.0
			for s in bidSegment:
				fullPathLength += s[3]

			#Calc rest
			holes = fullPathLength // holesDistance
			rest = fullPathLength - (holesDistance * (holes))
			#Travel along the path
			elapsedLength = rest / 2.0 #equaly distribute rest, as option???
			bidHoles = []
			while elapsedLength <= fullPathLength:
				#Search best segment to apply line interpolation
				bestSegment = bidSegment[0]
				segmentsSum = 0.0
				perc = 0.0
				for s in bidSegment:
					bestSegment = s
					segmentLength = bestSegment[3]
					perc = (elapsedLength-segmentsSum) / segmentLength
					segmentsSum += segmentLength
					if segmentsSum > elapsedLength : break

				#Fist point
				x1 = bestSegment[0][0]
				y1 = bestSegment[0][1]
				z1 = bestSegment[0][2]
				#Last point
				x2 = bestSegment[1][0]
				y2 = bestSegment[1][1]
				z2 = bestSegment[1][2]

				#Check if segment is not excluded
				if not bestSegment[2]:
					newHolePoint = (x1 + perc*(x2-x1) ,
						y1 + perc*(y2-y1),
						z1 + perc*(z2-z1))
					bidHoles.append(newHolePoint)

				#Go to next hole
				elapsedLength += holesDistance

			#Add bidHoles to allHoles
			allHoles.append(bidHoles)

		#Write gcommands from allSegments to the drill block
		n = self["name"]
		if not n or n=="default": n="Driller"
		blocks = []
		block = Block(self.name)

		holesCount = 0
		for bid in allHoles:

			for xH,yH,zH in bid:
				holesCount += 1
				block.append(CNC.grapid(None,None,zH + zSafe))
				block.append(CNC.grapid(xH,yH))
				if (peck != 0) :
					z = 0
					while z > targetDepth:
							z = max(z-peck, targetDepth)
							block.append(CNC.zenter(zH + z))
							block.append(CNC.grapid(None,None,zH + zSafe))
				block.append(CNC.zenter(zH + targetDepth))
				#dwell time only on last pass
				if dwell != 0:
						block.append(CNC.gcode(4, [("P",dwell)]))

		#Gcode Zsafe on finish
		block.append(CNC.zsafe())
		blocks.append(block)

		#Insert created block
		active = app.activeBlock()
		if active==0: active=1
		app.gcode.insBlocks(active, blocks, "Driller")
		app.refresh()
		app.setStatus(_("Generated Driller: %d holes")%holesCount)
Exemple #49
0
	def paste(self, event=None):
		try: clipboard = self.selection_get(selection='CLIPBOARD')
		except: return

		ypos = self.yview()[0]
		# paste them after the last selected item
		# bid,lid push them to self so it can be accessed from addLines()
		# python3 might fix this with the inner scope
		try:
			self._bid, self._lid = self._items[self.curselection()[-1]]
		except:
			try:
				self._bid, self._lid = self._items[-1]
			except:
				self._bid = 0
				self._lid = None

		selitems = []
		undoinfo = []

		def addLines(lines):
			for line in lines.splitlines():
				# Create a new block
				if self._lid is None:
					self._bid += 1
					if self._bid > len(self.gcode.blocks):
						self._bid = len(self.gcode.blocks)
					self._lid = MAXINT
					block = Block()
					undoinfo.append(self.gcode.addBlockUndo(self._bid,block))
					selitems.append((self._bid, None))
				else:
					block = self.gcode.blocks[self._bid]

				if self._lid == MAXINT:
					self._lid = len(block)
					selitems.append((self._bid, len(block)))
				else:
					self._lid += 1
					selitems.append((self._bid, self._lid))
				undoinfo.append(self.gcode.insLineUndo(self._bid, self._lid, line))

		try:
			# try to unpickle it
			unpickler = pickle.Unpickler(StringIO(clipboard))
			try:
				while True:
					obj = unpickler.load()
					if isinstance(obj,tuple):
						block = Block.load(obj)
						self._bid += 1
						undoinfo.append(self.gcode.addBlockUndo(self._bid, block))
						selitems.append((self._bid,None))
						self._lid = None
					else:
						addLines(obj)
			except EOFError:
				pass
		except pickle.UnpicklingError:
			# Paste as text
			addLines(clipboard)

		if not undoinfo: return

		self.gcode.addUndo(undoinfo)

		self.selection_clear(0,END)
		self.fill()
		self.yview_moveto(ypos)
		self.select(selitems, clear=True)

		#self.selection_set(ACTIVE)
		#self.see(ACTIVE)
		self.winfo_toplevel().event_generate("<<Modified>>")
Exemple #50
0
	def execute(self, app):
		name = self["name"]
		if not name or name=="default": name="Default Name"
		sel_Blocks = self["Sel_Blocks"]
		#Get inputs
		x = self["X"]
		y = self["Y"]
		z = self["Z"]
		if z == "":
			z=CNC.vars["surface"]

		cutDiam = self["CutDiam"]
		cutRadius = cutDiam/2.0
		if self["endmill"]:
			self.master["endmill"].makeCurrent(self["endmill"])
		toolDiam = CNC.vars["diameter"]
		#Radio = self["RadioHelix"]
		pitch = self["Pitch"]
		Depth = self["Depth"]
		Mult_F_Z = self["Mult_Feed_Z"]
		helicalCut = self["HelicalCut"]
		clearanceEntry = self["ClearanceEntry"]
		clearanceExit = self["ClearanceExit"]
		clearance = clearanceEntry
		entry = self["Entry"]
		returnToSafeZ = self["ReturnToSafeZ"]

		toolDiam = CNC.vars['diameter']
		toolRadius = toolDiam/2.0
		Radio = cutRadius - toolRadius
		if(Radio < 0): Radio = 0

		toolDiam = CNC.vars['diameter']
		toolRadius = toolDiam/2.0
		Radio = cutRadius - toolRadius

		if clearanceEntry =="":
			clearanceEntry =0 
		if clearanceExit =="":
			clearanceExit =0 

		if helicalCut == "Helical Cut":
			turn = 2
			p="HelicalCut "
		elif helicalCut == "Internal Right Thread":
			turn = 2
			p= "IntRightThread "
		elif helicalCut == "Internal Left Thread":
			turn = 3
			p= "IntLeftThread "
		elif helicalCut == "External Right Thread":
			Radio = cutRadius + toolRadius
			turn = 2
			p= "ExtRightThread "
		elif helicalCut == "External Left Thread":
			Radio = cutRadius + toolRadius
			turn = 3
			p= "ExtLeftThread "

# 		------------------------------------------------------------------------------------------------------------------		
		#Check inputs
		if sel_Blocks == 0:
			if x == "" or y == "" :
				app.setStatus(_("If block selected false, please make a value of x"))
				return

		elif helicalCut == "":
			app.setStatus(_("Helical Abort: Please select helical type"))
			return

		elif cutDiam < toolDiam or cutDiam == "":
			app.setStatus(_("Helical Abort: Helix diameter must be greater than the end mill"))
			return

		elif cutDiam <= 0:
			app.setStatus(_("Helical Abort: Helix diameter must be positive"))
			return

		elif pitch <= 0 or pitch =="":
			app.setStatus(_("Helical Abort: Drop must be greater than 0"))
			return

		elif Mult_F_Z <= 0 or Mult_F_Z == "":
			app.setStatus(_("Helical Abort: Z Feed Multiplier must be greater than 0"))
			return

		elif entry == "":
			app.setStatus(_("Helical Abort: Please selecte Entry and Exit type"))
			return

		elif clearanceEntry < 0 or clearanceEntry == "":
			app.setStatus(_("Helical Abort: Entry Edge Clearence may be positive"))
			return

		elif clearanceExit < 0 or clearanceExit == "":
			app.setStatus(_("Helical Abort: Exit Edge Clearence may be positive"))
			return
# 		------------------------------------------------------------------------------------------------------------------		
		#Initialize blocks that will contain our gCode
		blocks = []
		#block = Block(name)
		block = Block( p + str(cutDiam) + " Pitch " + str(pitch) + " Bit " + str(toolDiam) + " depth " + str(Depth))
		
		cutFeed = CNC.vars["cutfeedz"]	#<<< Get cut feed Z for the current material
		cutFeedMax = CNC.vars["cutfeed"] #<<< Get cut feed XY for the current material
# 		------------------------------------------------------------------------------------------------------------------
		# Get selected blocks from editor
		selBlocks = app.editor.getSelectedBlocks()
		if not selBlocks:
			app.editor.selectAll()
			selBlocks = app.editor.getSelectedBlocks()

		if not selBlocks:
			if sel_Blocks == 1:
				app.setStatus(_("Helical abort: Please select some path"))
				return
# 		------------------------------------------------------------------------------------------------------------------
		# Get selected blocks from editor
		if sel_Blocks == 1:
			selBlocks = app.editor.getSelectedBlocks()
			if not selBlocks:
				app.editor.selectAll()
				selBlocks = app.editor.getSelectedBlocks()

			#Get all segments from gcode
			allSegments = self.extractAllSegments(app,selBlocks)

			#Create holes locations
			allHoles=[]
			for bidSegment in allSegments:
				if len(bidSegment)==0:
					continue

				bidHoles = []
				for idx, anchor in enumerate(bidSegment):
					if idx ==2:
						newHolePoint = (anchor[0][0],anchor[0][1],anchor[0][2])
						bidHoles.append(newHolePoint)


				#Add bidHoles to allHoles
				allHoles.append(bidHoles)

# 		------------------------------------------------------------------------------------------------------------------
			holesCount = 0
			for bid in allHoles:
				for xH,yH,zH in bid:
					x = xH
					y = yH

# 		------------------------------------------------------------------------------------------------------------------
#		 Init: Adjust feed and rapid move to Z safe 
		
		if Mult_F_Z is"":
			Mult_F_Z = 1

		if Mult_F_Z == 0:
			Mult_F_Z = 1
	
		if Mult_F_Z * cutFeed > cutFeedMax:
			cutFeed = cutFeedMax
		else:
			cutFeed = cutFeed*Mult_F_Z

		block.append(CNC.zsafe()) 			#<<< Move rapid Z axis to the safe height in Stock Material

#		 Move rapid to X and Y coordinate
		if helicalCut == "Helical Cut" or helicalCut == "Internal Right Thread" or helicalCut == "Internal Left Thread":
			if entry == "Center":
				block.append(CNC.grapid(x,y))
			else:
				block.append(CNC.grapid(x-Radio+clearance ,y))

		if helicalCut == "External Right Thread" or helicalCut == "External Left Thread":
			if entry == "Center":
				clearance = 0.0
			block.append(CNC.grapid(x-Radio-clearance ,y))

		#cutFeed = int(cutFeed)
		block.append(CNC.fmt("f",cutFeed))	#<<< Set cut feed
	#	block.append(CNC.gline(x,y)
	#    while (z < 1):
		block.append(CNC.zenter(z))
		block.append(CNC.gline(x-Radio,y))
	#	cutFeed = int((CNC.vars["cutfeed"]	+ CNC.vars["cutfeedz"])/2)	#<<< Get cut feed for the current material

		#cutFeed = int(cutFeed)
		block.append(CNC.fmt("F",cutFeed))	#<<< Set cut feed
		

#-----------------------------------------------------------------------------------------------------
	#	Uncomment for first flat pass
		if helicalCut == "Helical Cut":
			block.append(CNC.gcode(turn, [("X",x-Radio),("Y",y),("Z", z),("I",Radio), ("J",0)]))
#-----------------------------------------------------------------------------------------------------
		if (z < Depth):
			pitch = -pitch

			while ((z-pitch) < Depth) :
				z = z-pitch
				block.append(CNC.gcode(turn, [("X",x-Radio),("Y",y),("Z", z),("I",Radio), ("J",0)]))

		else:
			while ((z-pitch) >= Depth) :
				z = z-pitch
				block.append(CNC.gcode(turn, [("X",x-Radio),("Y",y),("Z", z),("I",Radio), ("J",0)]))

		#Target Level
		if entry == "Center":
			clearanceExit = 0.0	
		clearance = clearanceExit
		alpha= round(Depth / pitch, 4 ) - round(Depth / pitch, 0)
		alpha = alpha * 2*pi 
		Radiox = Radio * cos(alpha)
		Radioy = Radio * sin(alpha)
		xsi = Radiox - clearance* cos(alpha)
		ysi =Radioy - clearance* sin(alpha)
		xse = Radiox + clearance* cos(alpha)
		yse =Radioy + clearance* sin(alpha)
		z = Depth



		if helicalCut == "Helical Cut":
			block.append(CNC.gcode(turn, [("X",x-Radio),("Y",y),("Z", z),("I",Radio), ("J",0)]))
			#Last flat pass
			block.append(CNC.gcode(turn, [("X",x-Radio),("Y",y),("Z", z),("I",Radio), ("J",0)]))
		elif helicalCut == 	"Internal Right Thread" or helicalCut == "External Right Thread":
			block.append(CNC.gcode(turn, [("X",x-Radiox),("Y",y-Radioy),("Z", z),("I",Radio), ("J",0)]))

		elif helicalCut == 	"Internal Left Thread" or helicalCut ==	"External Left Thread":
			block.append(CNC.gcode(turn, [("X",x-Radiox),("Y",y+Radioy),("Z", z),("I",Radio), ("J",0)]))

		# Exit clearance 
		if helicalCut == "Internal Right Thread":
			block.append(CNC.gline(x-xsi,y-ysi))
		elif helicalCut == "Internal Left Thread":
			block.append(CNC.gline(x-xsi,y+ysi))
		if helicalCut == "External Right Thread":
			block.append(CNC.gline(x-xse,y-yse))
		elif helicalCut == "External Left Thread":
			block.append(CNC.gline(x-xse,y+yse))

		# Return to Z Safe
		if returnToSafeZ == 1: 
			if helicalCut == "Helical Cut" or helicalCut == "Internal Right Thread" or helicalCut == "Internal Left Thread":
				if entry == "Center":
					block.append(CNC.gline(x,y))
			block.append(CNC.zsafe())

		blocks.append(block)
		active = app.activeBlock()
		app.gcode.insBlocks(active, blocks, "Helical_Descent inserted")	#<<< insert blocks over active block in the editor
		app.refresh()												#<<< refresh editor
		app.setStatus(_("Generated: Helical_Descent Result"))				#<<< feed back result
Exemple #51
0
    def make(self, RExt=50., RInt=33., ROff=13., Depth=0):
        self.RExt = RExt
        self.RInt = RInt
        self.ROff = ROff

        if RExt > RInt:
            self.Spins = self.lcm(RExt, RInt) / max(RExt, RInt)
        else:
            self.Spins = self.lcm(RExt, RInt) / min(RExt, RInt)

        self.Depth = Depth
        self.PI = math.pi
        self.theta = 0.0

        blocks = []
        block = Block(self.name)

        block.append("(External Radius = %g)" % (self.RExt))
        block.append("(Internal Radius = %g)" % (self.RInt))
        block.append("(Offset Radius = %g)" % (self.ROff))

        xi, yi = zip(*(self.calc_dots()))

        block.append(CNC.zsafe())
        block.append(CNC.grapid(xi[0], yi[0]))

        currDepth = 0.
        stepz = CNC.vars['stepz']
        if stepz == 0: stepz = 0.001  #avoid infinite while loop

        while True:
            currDepth -= stepz
            if currDepth < self.Depth: currDepth = self.Depth
            block.append(CNC.zenter(currDepth))
            block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])]))
            for x, y in zip(xi, yi):
                block.append(CNC.gline(x, y))
            block.append(CNC.gline(xi[0], yi[0]))
            if currDepth <= self.Depth: break

        block.append(CNC.zsafe())
        blocks.append(block)
        return blocks
Exemple #52
0
	def GetStitches(self, app, FileName ):
		try:
			from struct import *
		except:
			app.setStatus("Embroidery abort: no module named struct")
			return
		
		print(FileName)
		try:
			f = open(FileName,'rb')
		except:
			app.setStatus(" Embroidery abort: Can't read image file")
			return
		app.setStatus(" Embroidery: file %s sucsessfully opened"%f.name)
		#DST header struct checking - parsing
		format = "3s16sc3s7sc3s3sc3s5sc3s5sc3s5sc3s5sc3s6sc3s6sc"
		data=f.read(94)
		LAN,LA,C,STN,ST,C,CLN,CL,C,POSX,posx,C,NEGX,negx,C,POSY,posy,C,NEGY,negy,C,AX,ax,C,AY,ay,c=unpack(format, data) 
		CL=int(CL)
		ST=int(ST)
		
		if (LAN !='LA:'): 
			app.setStatus(" Embroidery abort: Not a DST")
		print (LA)
		print(" St count: %d color changes=%d"%(ST ,CL))
		f.seek(512);
		coordX=0;coordY=0;#initial coordinates to start sewing
		cnt=0;#just counter
		color = 0;#color code
		format="1b1b1b"# 3 unsigned bytes from data field
		prevCol=self.color
		i=0
		blocks = []
		for ColorCycles  in range (0 , CL+1): #color cycles
			
			block = Block(self.name)
			while prevCol==self.color:
				ff=f.read(3);#read 24 bits
				cnt+=1
				if  len(ff)<3: break
				b0,b1,b2=unpack(format, ff) #data field unpacked with "format" to b0 b1 b2
				dx = decode_dx(b0, b1, b2)
				dy = decode_dy(b0, b1, b2)
				coordX+=dx
				coordY+=dy
				block.color = colors[self.color]
				block.append(self.decode_flags( b2)(coordX,coordY))
				block.append(CNC.zsafe())#safe height
			prevCol = self.color
			print("Stitches read=: %d"%cnt)#counter		
			blocks.append(block)

		
		try:
			dx = float(self["dx"])
		except:
			dx = 0.0

		try:
			dy = float(self["dy"])
		except:
			dy = 0.0

		return blocks
Exemple #53
0
    def make(self, n=2, size=100, depth=0):
        self.n = n
        self.size = size
        self.depth = depth

        blocks = []
        block = Block(self.name)

        xi, yi = zip(*(self.hilbert(0.0, 0.0, size, 0.0, 0.0, size, n)))

        block.append(CNC.zsafe())
        block.append(CNC.grapid(xi[0], yi[0]))

        currDepth = 0.
        stepz = CNC.vars['stepz']
        if stepz == 0: stepz = 0.001  #avoid infinite while loop

        while True:
            currDepth -= stepz
            if currDepth < self.depth: currDepth = self.depth
            block.append(CNC.zenter(currDepth))
            block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])]))
            for x, y in zip(xi, yi):
                block.append(CNC.gline(x, y))
            if currDepth <= self.depth: break

        block.append(CNC.zsafe())
        blocks.append(block)
        return blocks
Exemple #54
0
    def execute(self, app):
        # Try import PIL
        try:
            from PIL import Image
        except:
            app.setStatus(_("Heightmap abort: This plugin requires PIL/Pillow"))
            return

            # Try read image
        fileName = self["File"]
        try:
            img = Image.open(fileName)
            img = img.convert("L")  # Luminance
        except:
            app.setStatus(_("Heightmap abort: Can't read image file"))
            return

        if self["Depth"] >= 0:
            app.setStatus(_("Heightmap abort: depth must be < 0"))
            return

            # Define type of matrix manipulation
        NUMPY = True
        if NUMPY == True:
            try:
                import numpy
            except:
                NUMPY = False

        if NUMPY == True:
            Image_Matrix = Image_Matrix_Numpy
        else:
            Image_Matrix = Image_Matrix_List
            # print "Install NumPy will speed up heightmap creation"

        MAT = Image_Matrix()
        MAT.FromImage(img, True)

        maxSize = self["MaxSize"]
        w, h = img.size

        if w > h:
            ratio = float(w) / float(h)
            image_w = maxSize
            image_h = maxSize / ratio
        else:
            ratio = float(h) / float(w)
            image_w = maxSize / ratio
            image_h = maxSize

            # Calc pixel size
        pixel_size = image_h / (float(MAT.width) - 1.0)

        tolerance = 0.1
        safe_z = CNC.vars["safe"]
        splitstep = 0.0  # Offset Stepover
        toptol = -0.1  # Top Tolerance
        depth = -self["Depth"]
        Cont_Angle = 45.0  # Contact angle , only with "Lace Bounding"

        # Cut perimeter/border
        cutperim = 0
        if self["CutBorder"]:
            cutperim = 1

        ######################################################
        tool = app.tools["EndMill"]
        tool_shape = tool["shape"]

        tool_diameter = CNC.vars["diameter"]
        feed_rate = CNC.vars["cutfeed"]

        zStep = CNC.vars["stepz"]
        rough_offset = 0.0
        rough_feed = CNC.vars["cutfeed"]

        plunge_feed = CNC.vars["cutfeedz"]
        stepover = tool_diameter * CNC.vars["stepover"] / 100.0
        step = max(1, int(math.floor(float(stepover) / pixel_size)))

        edge_offset = 0
        ######################################################
        if tool_shape == "Square End" or tool_shape == "Fishtail" or tool_shape == "Radiused":
            TOOL = make_tool_shape(NUMPY, endmill, tool_diameter, pixel_size)
        elif tool_shape == "V-cutting":
            try:
                v_angle = float(tool["angle"])
            except:
                app.setStatus(_("Heightmap abort: angle not defined for selected End Mill"))
                return
            TOOL = make_tool_shape(NUMPY, vee_common(v_angle), tool_diameter, pixel_size)
        else:  # "Ball End"
            TOOL = make_tool_shape(NUMPY, ball_tool, tool_diameter, pixel_size)

            ######################################################
        rows = 0
        columns = 0
        columns_first = 0
        scanpat = self["Scan"]
        if scanpat != "Columns":
            rows = 1
        if scanpat != "Rows":
            columns = 1
        if scanpat == "C&R":
            columns_first = 1

            ######################################################
            # Options are "Alternating", "Positive"   , "Negative",  "Up Mill", "Down Mill"
        converter = self["ScanDir"]

        if converter == "Positive":
            conv_index = 0

        elif converter == "Negative":
            conv_index = 1

        elif converter == "Alternating":
            conv_index = 2

        elif converter == "Up Mill":
            conv_index = 3

        elif converter == "Down Mill":
            conv_index = 4
        else:
            conv_index = 2

            ######################################################
        convert_makers = [
            Convert_Scan_Increasing,
            Convert_Scan_Decreasing,
            Convert_Scan_Alternating,
            Convert_Scan_Upmill,
            Convert_Scan_Downmill,
        ]
        if rows:
            convert_rows = convert_makers[conv_index]()
        else:
            convert_rows = None

        if columns:
            convert_cols = convert_makers[conv_index]()
        else:
            convert_cols = None

            ######################################################
        lace_bound_val = "None"  # "None","Secondary","Full"
        if lace_bound_val != "None" and rows and columns:
            slope = tan(Cont_Angle * pi / 180)
            if columns_first:
                convert_rows = Reduce_Scan_Lace(convert_rows, slope, step + 1)
            else:
                convert_cols = Reduce_Scan_Lace(convert_cols, slope, step + 1)
            if lace_bound_val == "Full":
                if columns_first:
                    convert_cols = Reduce_Scan_Lace(convert_cols, slope, step + 1)
                else:
                    convert_rows = Reduce_Scan_Lace(convert_rows, slope, step + 1)

                    ######################################################
                    ###              START COMMON STUFF                ###
                    ######################################################
        ##		units = "mm"
        ##		if units == "in":
        ##			units = 'G20'
        ##		else:
        ##			units = 'G21'
        # Units not used
        units = ""

        ######################################################
        cuttop = 1
        if self["CutTop"]:
            cuttop = 0
        if cuttop:
            if rows == 1:
                convert_rows = Reduce_Scan_Lace_new(convert_rows, toptol, 1)
            if columns == 1:
                convert_cols = Reduce_Scan_Lace_new(convert_cols, toptol, 1)

                ######################################################
                # Force disable arcs
        disable_arcs = True  # grbl doesn't like this, G91.1?
        if not disable_arcs:
            Entry_cut = ArcEntryCut(plunge_feed, 0.125)
        else:
            Entry_cut = SimpleEntryCut(plunge_feed)

            ######################################################
            # Force normalize
        normalize = True
        if normalize:
            pass
            a = MAT.min()
            b = MAT.max()
            if a != b:
                MAT.minus(a)
                MAT.mult(1.0 / (b - a))
        else:
            MAT.mult(1 / 255.0)

        xoffset = 0
        yoffset = 0
        ######################################################
        MAT.mult(depth)

        ##########################################
        #         ORIGIN LOCATING STUFF          #
        ##########################################
        minx = 0
        maxx = image_w
        miny = 0
        maxy = image_h
        midx = (minx + maxx) / 2
        midy = (miny + maxy) / 2

        # Force origin, we can move it later
        origin = "Bot-Left"
        CASE = str(origin)
        if CASE == "Top-Left":
            x_zero = minx
            y_zero = maxy
        elif CASE == "Top-Center":
            x_zero = midx
            y_zero = maxy
        elif CASE == "Top-Right":
            x_zero = maxx
            y_zero = maxy
        elif CASE == "Mid-Left":
            x_zero = minx
            y_zero = midy
        elif CASE == "Mid-Center":
            x_zero = midx
            y_zero = midy
        elif CASE == "Mid-Right":
            x_zero = maxx
            y_zero = midy
        elif CASE == "Bot-Left":
            x_zero = minx
            y_zero = miny
        elif CASE == "Bot-Center":
            x_zero = midx
            y_zero = miny
        elif CASE == "Bot-Right":
            x_zero = maxx
            y_zero = miny
        elif CASE == "Arc-Center":
            x_zero = 0
            y_zero = 0
        else:  # "Default"
            x_zero = 0
            y_zero = 0

        xoffset = xoffset - x_zero
        yoffset = yoffset - y_zero

        ######################################################
        invert = self["Invert"]
        if invert:
            MAT.mult(-1.0)
        else:
            MAT.minus(depth)

            ######################################################

        gcode = []
        MAT.pad_w_zeros(TOOL)

        header = ""
        postscript = ""
        gcode = convert(
            self,
            MAT,
            units,
            TOOL,
            pixel_size,
            step,
            safe_z,
            tolerance,
            feed_rate,
            convert_rows,
            convert_cols,
            columns_first,
            cutperim,
            Entry_cut,
            zStep,
            rough_feed,
            xoffset,
            yoffset,
            splitstep,
            header,
            postscript,
            edge_offset,
            disable_arcs,
        )

        # Gcode
        n = self["name"]
        if not n or n == "default":
            n = "Heightmap"
        block = Block(n)
        block.append("(Size: %d x %d x %d)" % (image_w, image_h, depth))
        block.append("(Endmill shape: %s , Diameter: %.3f)" % (tool_shape, tool_diameter))
        for line in gcode:
            block.append(line)

        blocks = []
        blocks.append(block)
        active = app.activeBlock()
        app.gcode.insBlocks(active, blocks, n)
        app.refresh()
        app.setStatus(_("Generated Heightmap %d x %d x %d ") % (image_w, image_h, depth))
Exemple #55
0
    def calc(self, N, phi, Pc):
        N = abs(N)
        # Pitch Circle
        D = N * Pc / math.pi
        R = D / 2.0

        # Diametrical pitch
        Pd = N / D

        # Base Circle
        Db = D * math.cos(phi)
        Rb = Db / 2.0

        # Addendum
        a = 1.0 / Pd

        # Outside Circle
        Ro = R + a
        Do = 2.0 * Ro

        # Tooth thickness
        T = math.pi * D / (2 * N)

        # undercut?
        U = 2.0 / (math.sin(phi) * (math.sin(phi)))
        needs_undercut = N < U
        # sys.stderr.write("N:%s R:%s Rb:%s\n" % (N,R,Rb))

        # Clearance
        c = 0.0
        # Dedendum
        b = a + c

        # Root Circle
        Rr = R - b
        Dr = 2.0 * Rr

        two_pi = 2.0 * math.pi
        half_thick_angle = two_pi / (4.0 * N)
        pitch_to_base_angle = self.involute_intersect_angle(Rb, R)
        pitch_to_outer_angle = self.involute_intersect_angle(
            Rb, Ro)  # pitch_to_base_angle

        points = []
        for x in range(1, N + 1):
            c = x * two_pi / N

            # angles
            pitch1 = c - half_thick_angle
            base1 = pitch1 - pitch_to_base_angle
            outer1 = pitch1 + pitch_to_outer_angle

            pitch2 = c + half_thick_angle
            base2 = pitch2 + pitch_to_base_angle
            outer2 = pitch2 - pitch_to_outer_angle

            # points
            b1 = self.point_on_circle(Rb, base1)
            p1 = self.point_on_circle(R, pitch1)
            o1 = self.point_on_circle(Ro, outer1)
            o2 = self.point_on_circle(Ro, outer2)
            p2 = self.point_on_circle(R, pitch2)
            b2 = self.point_on_circle(Rb, base2)

            if Rr >= Rb:
                pitch_to_root_angle = pitch_to_base_angle - self.involute_intersect_angle(
                    Rb, Rr)
                root1 = pitch1 - pitch_to_root_angle
                root2 = pitch2 + pitch_to_root_angle
                r1 = self.point_on_circle(Rr, root1)
                r2 = self.point_on_circle(Rr, root2)

                points.append(r1)
                points.append(p1)
                points.append(o1)
                points.append(o2)
                points.append(p2)
                points.append(r2)
            else:
                r1 = self.point_on_circle(Rr, base1)
                r2 = self.point_on_circle(Rr, base2)
                points.append(r1)
                points.append(b1)
                points.append(p1)
                points.append(o1)
                points.append(o2)
                points.append(p2)
                points.append(b2)
                points.append(r2)

        first = points[0]
        del points[0]

        blocks = []
        block = Block(self.name)
        blocks.append(block)

        block.append(CNC.grapid(first.x(), first.y()))
        block.append(CNC.zenter(0.0))
        #print first.x(), first.y()
        for v in points:
            block.append(CNC.gline(v.x(), v.y()))
            #print v.x(), v.y()
        #print first.x(), first.y()
        block.append(CNC.gline(first.x(), first.y()))
        block.append(CNC.zsafe())

        #block = Block("%s-center"%(self.name))
        block = Block("%s-basecircle" % (self.name))
        block.enable = False
        block.append(CNC.grapid(Db / 2, 0.))
        block.append(CNC.zenter(0.0))
        block.append(CNC.garc(CW, Db / 2, 0., i=-Db / 2))
        block.append(CNC.zsafe())
        blocks.append(block)
        return blocks
	def execute(self, app):
		try:
			from PIL import Image
		except:
			app.setStatus(_("Pyrograph abort: This plugin requires PIL/Pillow"))
			return

		n = self["name"]
		if not n or n=="default": n="Pyrograph"

		#Calc desired size
		toolSize = self.fromMm("ToolSize")
		maxSize = self.fromMm("MaxSize")
		feedMin = self["FeedMin"]
		feedMax = self["FeedMax"]
		depth = self.fromMm("Depth")
		direction = self["Direction"]
		drawBorder = self["DrawBorder"]

		#Check parameters
		if direction is "":
			app.setStatus(_("Pyrograph abort: please define a scan Direction"))
			return

		if toolSize <=0:
			app.setStatus(_("Pyrograph abort: Tool Size must be > 0"))
			return

		if feedMin <=0 or feedMax <=0 :
			app.setStatus(_("Pyrograph abort: Please check feed rate parameters"))
			return

		#divisions
		divisions = maxSize / toolSize

		fileName = self["File"]
		try:
			img = Image.open(fileName)
			img = img.convert ('RGB') #be sure to have color to calculate luminance
		except:
			app.setStatus(_("Pyrograph abort: Can't read image file"))
			return

		iWidth,iHeight =  img.size
		newWidth = iWidth
		newHeight = iHeight

		ratio = 1
		if (iWidth > iHeight):
			ratio = float(iWidth) / float(iHeight)
			newWidth = int(divisions)
			newHeight = int(divisions / ratio)
		else:
			ratio = float(iHeight) / float(iWidth)
			newWidth = int(divisions / ratio)
			newHeight = int(divisions)

		#Create a thumbnail image to work faster
		img.thumbnail((newWidth,newHeight), Image.ANTIALIAS)
		newWidth,newHeight =  img.size
		#img.save("thumb.png")
		pixels = list(img.getdata())

		#Extract luminance
		gMap = []
		for x in range(0,newWidth):
			gRow = []
			for y in range(0,newHeight):
				R,G,B = pixels[(y * newWidth) + x ]
				L = (0.299*R + 0.587*G + 0.114*B) #Luminance (Rec. 601 standard)
				gRow.append(L)
			gMap.append(gRow)

		#Init blocks
		blocks = []
		block = Block(self.name)
		block.append("(Pyrograph W=%g x H=%g x D=%g)" %
		(newWidth * toolSize , newHeight * toolSize , depth))

		#Create points for vertical scan
		xH = []
		yH = []
		fH = []
		if (direction=="Vertical" or direction=="Both"):
			r = range(0,newHeight)
			for x in range(0,newWidth):
				r = r[::-1]
				fPrec = -1
				for y in r:
					f = int(feedMin + ((feedMax - feedMin) * gMap[x][y] / 255.0))
					if(f != fPrec or y==0 or  y==newHeight-1):
						xH.append(x * toolSize)
						yH.append((newHeight-y) * toolSize)
						fH.append(f)
					fPrec = f

		#Create points for horizontal scan
		xV = []
		yV = []
		fV = []
		if (direction=="Horizontal" or direction=="Both"):
			r = range(0,newWidth)
			for y in reversed(range(0,newHeight)):
				fPrec = -1
				for x in r:
					f = int(feedMin + ((feedMax - feedMin) * gMap[x][y] / 255.0))
					if(f != fPrec or x==0 or x==newWidth-1):
						xV.append(x * toolSize)
						yV.append((newHeight-y) * toolSize)
						fV.append(f)
					fPrec = f
				r = r[::-1]

		#Gcode Horizontal
		if (len(xH)>1 and len(yH)>1):
			block.append(CNC.zsafe())
			block.append(CNC.grapid(xH[0],yH[0]))
			block.append(CNC.zenter(depth))
			for x,y,f in zip(xH,yH,fH):
					v = (x,y,depth)
					block.append(CNC.glinev(1,v,f))

		#Gcode Vertical
		if (len(xV)>1 and len(yV)>1):
			block.append(CNC.zsafe())
			block.append(CNC.grapid(xV[0],yV[0]))
			block.append(CNC.zenter(depth))
			for x,y,f in zip(xV,yV,fV):
					v = (x,y,depth)
					block.append(CNC.glinev(1,v,f))

		#Draw Border if required
		if drawBorder:
			block.append(CNC.zsafe())
			block.append(CNC.grapid(0,0))
			block.append(CNC.zenter(depth))
			block.append(CNC.gcode(1, [("f",feedMin)]))
			block.append(CNC.gline(newWidth * toolSize - toolSize,0))
			block.append(CNC.gline(newWidth * toolSize - toolSize ,newHeight* toolSize))
			block.append(CNC.gline(0,newHeight* toolSize ))
			block.append(CNC.gline(0,0))

		#Gcode Zsafe
		block.append(CNC.zsafe())

		blocks.append(block)
		active = app.activeBlock()
		if active==0: active=1
		app.gcode.insBlocks(active, blocks, "Pyrograph")
		app.refresh()
		app.setStatus(_("Generated Pyrograph W=%g x H=%g x D=%g") %
		(newWidth * toolSize , newHeight * toolSize , depth))
Exemple #57
0
	def execute(self, app):
		feed = self["feed"]
		rdoc = self["rdoc"]
		radius = self["dia"]/2
		cw = self["cw"]
		circ = self["circ"]
		evenspacing = self["evenspacing"]

		if cw: cwtext = 'cw'
		else: cwtext = 'ccw'

		if cw: arcg = 'g2'
		else: arcg = 'g3'

		#print("go!")
		blocks  = []
		for bid in app.editor.getSelectedBlocks():
			#print(blocks[bid])
			path = app.gcode.toPath(bid)[0]
			#print(path)

			block = Block("trochoid "+cwtext+" "+str(radius*2)+"+"+str(rdoc))
			block.append("F"+str(feed))

			entry = self["entry"]

			A=path[0].A
			block.append("g0 x"+str(A[0])+" y"+str(A[1]))
			block.append("G1 Z0")
			for segment in path:
				#print(segment.A)
				#block.append("g0 x0 y0")
				#block.append("g1 x10 y10")
				#block.append("g1 x20 y10")
				#block.append("g0 x0 y0")
				if entry:
					eblock = Block("trochoid-in")
					eblock.append("G0 Z0")
					eblock.append("G0 x"+str(segment.A[0])+" y"+str(segment.A[1]-radius))
					eblock.append("G2 x"+str(segment.A[0])+" y"+str(segment.A[1]-radius)+" i"+str(0)+" j"+str(radius))
					blocks.append(eblock)
					entry = False

				#Continuity BEGINING
				block.append("g1 x"+str(segment.A[0])+" y"+str(segment.A[1]))
				#block.append(arcg+" x"+str(segment.A[0])+" y"+str(segment.A[1])+" r"+str(radius/2))

				phi = atan2(segment.B[1]-segment.A[1], segment.B[0]-segment.A[0])

				#TODO: handle arc segments
				#if segment.type == Segment.LINE:
				#if segment.type in (Segment.CW, Segment.CCW):

				#Compensate for uneven spacing
				srdoc = rdoc
				if evenspacing:
					subsegs = segment.length()//rdoc
					remainder = segment.length()%rdoc
					if remainder != 0:
						srdoc = segment.length()/(subsegs+1)

				#Loop over subsegmnents of segment
				i=0
				while i<(segment.length()+srdoc):
					pos=min(segment.length(), i)

					B = segment.distPoint(pos)
					block.extend(self.trochoid(A,B,radius,cw,circ))
					A = B

					i+=srdoc

				#Continuity END
				#block.append("g1 x"+str(segment.B[0])+" y"+str(segment.B[1]))
				block.append(arcg+" x"+str(segment.B[0])+" y"+str(segment.B[1])+" r"+str(radius/2))

			blocks.append(block)


		active = app.activeBlock()
		app.gcode.insBlocks(active, blocks, "Trochoidal created") #<<< insert blocks over active block in the editor
		app.refresh()                                                                                           #<<< refresh editor
		app.setStatus(_("Generated: Trochoidal"))                           #<<< feed back result
Exemple #58
0
	def paste(self, event=None):
		try: clipboard = self.selection_get(selection='CLIPBOARD')
		except: return

		ypos = self.yview()[0]
		# paste them after the last selected item
		# bid,lid push them to self so it can be accessed from addLines()
		# python3 might fix this with the inner scope
		try:
			self.__bid, self.__lid = self._items[self.curselection()[-1]]
		except:
			try:
				self.__bid, self.__lid = self._items[-1]
			except:
				self.__bid = 0
				self.__lid = None

		selitems = []
		undoinfo = []

		def addLines(lines):
			for line in lines.splitlines():
				# Create a new block
				if self.__lid is None:
					self.__bid += 1
					self.__lid = sys.maxint
					block = Block()
					undoinfo.append(self.gcode.addBlockUndo(self.__bid,block))
					selitems.append((self.__bid, None))
				else:
					block = self.gcode.blocks[self.__bid]

				if self.__lid == sys.maxint:
					selitems.append((self.__bid, len(block)))
				else:
					self.__lid += 1
					selitems.append((self.__bid, self.__lid))
				undoinfo.append(self.gcode.insLineUndo(self.__bid, self.__lid, line))

		try:
			# try to unpickle it
			unpickler = pickle.Unpickler(StringIO(clipboard))
			try:
				while True:
					obj = unpickler.load()
					if isinstance(obj,tuple):
						block = Block.load(obj)
						self.__bid += 1
						undoinfo.append(self.gcode.addBlockUndo(self.__bid, block))
						selitems.append((self.__bid,None))
						self.__lid = None
					else:
						addLines(obj)
			except EOFError:
				pass
		except pickle.UnpicklingError:
			# Paste as text
			addLines(clipboard)

		if not undoinfo: return

		self.gcode.addUndo(undoinfo)

		self.selection_clear(0,END)
		self.fill()
		self.yview_moveto(ypos)
		self.select(selitems, clear=True)

		#self.selection_set(ACTIVE)
		#self.see(ACTIVE)
		self.app.event_generate("<<Modified>>")
Exemple #59
0
    def execute(self, app):
        if Image is None:
            app.setStatus(
                _("Halftone abort: This plugin requires PIL/Pillow to read image data"
                  ))
            return

        n = self["name"]
        if not n or n == "default": n = "Halftone"

        # Calc desired size
        channel = self["Channel"]
        invert = self["Invert"]
        drawSize = self["DrawSize"]
        cellSize = self["CellSize"]
        dMax = self["DiameterMax"]
        dMin = self["DiameterMin"]
        angle = self["Angle"]
        drawBorder = self["DrawBorder"]
        depth = self["Depth"]
        conical = self["Conical"]

        # Check parameters
        if drawSize < 1:
            app.setStatus(
                _("Halftone abort: Size too small to draw anything!"))
            return

        if dMin > dMax:
            app.setStatus(
                _("Halftone abort: Minimum diameter must be minor then Maximum"
                  ))
            return

        if dMax < 1:
            app.setStatus(_("Halftone abort: Maximum diameter too small"))
            return

        if cellSize < 1:
            app.setStatus(_("Halftone abort: Cell size too small"))
            return

        tool = app.tools["EndMill"]
        tool_shape = tool["shape"]
        if conical:
            if tool_shape == "V-cutting":
                try:
                    v_angle = float(tool["angle"])
                except:
                    app.setStatus(
                        _("Halftone abort: Angle in V-Cutting end mill is missing"
                          ))
                    return
            else:
                app.setStatus(
                    _("Halftone abort: Conical path need V-Cutting end mill"))
                return

        # Open picture file
        fileName = self["File"]
        try:
            img = Image.open(fileName)
        except:
            app.setStatus(_("Halftone abort: Can't read image file"))
            return

        # Create a scaled image to work faster with big image and better with small ones
        squareNorm = True
        if channel == 'Blue(sqrt)':
            img = img.convert('RGB')
            img = img.split()[0]
        elif channel == 'Green(sqrt)':
            img = img.convert('RGB')
            img = img.split()[1]
        elif channel == 'Red(sqrt)':
            img = img.convert('RGB')
            img = img.split()[2]
        else:
            img = img.convert('L')  # to calculate luminance
            squareNorm = False

        # flip image to ouput correct coordinates
        img = img.transpose(Image.FLIP_TOP_BOTTOM)

        # Calc divisions for halftone
        divisions = drawSize / cellSize
        # Get image size
        self.imgWidth, self.imgHeight = img.size
        if (self.imgWidth > self.imgHeight):
            scale = drawSize / float(self.imgWidth)
            sample = int(self.imgWidth / divisions)
        else:
            scale = drawSize / float(self.imgHeight)
            sample = int(self.imgHeight / divisions)
        self.ratio = scale

        # Halftone
        circles = self.halftone(img, sample, scale, angle, squareNorm, invert)

        # Init blocks
        blocks = []

        # Border block
        if drawBorder:
            block = Block("%s-border" % (self.name))
            block.append(CNC.zsafe())
            block.append(CNC.grapid(0, 0))
            block.append(CNC.zenter(depth))
            block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])]))
            block.append(CNC.gline(self.imgWidth * self.ratio, 0))
            block.append(
                CNC.gline(self.imgWidth * self.ratio,
                          self.imgHeight * self.ratio))
            block.append(CNC.gline(0, self.imgHeight * self.ratio))
            block.append(CNC.gline(0, 0))
            blocks.append(block)

        # Draw block
        block = Block(self.name)

        # Change color
        if channel == 'Blue(sqrt)':
            block.color = "#0000ff"
        elif channel == 'Green(sqrt)':
            block.color = "#00ff00"
        elif channel == 'Red(sqrt)':
            block.color = "#ff0000"

        block.append("(Halftone size W=%d x H=%d x D=%d ,Total points:%i)" %
                     (self.imgWidth * self.ratio, self.imgHeight * self.ratio,
                      depth, len(circles)))
        block.append("(Channel = %s)" % channel)

        for c in circles:
            x, y, r = c
            r = min(dMax / 2.0, r)
            if (r >= dMin / 2.):
                block.append(CNC.zsafe())
                block.append(CNC.grapid(x + r, y))
                block.append(CNC.zenter(depth))
                block.append(CNC.garc(
                    CW,
                    x + r,
                    y,
                    i=-r,
                ))
        block.append(CNC.zsafe())
        if conical: block.enable = False
        blocks.append(block)

        if conical:
            blockCon = Block("%s-Conical" % (self.name))
            for c in circles:
                x, y, r = c
                blockCon.append(CNC.zsafe())
                blockCon.append(CNC.grapid(x, y))
                dv = r / math.tan(math.radians(v_angle / 2.))
                blockCon.append(CNC.zenter(-dv))
            blockCon.append(CNC.zsafe())
            blocks.append(blockCon)

        # Gcode Zsafe
        active = app.activeBlock()
        app.gcode.insBlocks(active, blocks, "Halftone")
        app.refresh()
        app.setStatus(
            _("Generated Halftone size W=%d x H=%d x D=%d ,Total points:%i" %
              (self.imgWidth * self.ratio, self.imgHeight * self.ratio, depth,
               len(circles))))
Exemple #60
0
	def generate(self, board_width, board_height, number_of_pieces, random_seed = 0, tap_shape = 'basic', threshold = 3.0):
		blocks = []
		block = Block(self.name)
		random.seed(random_seed)
		Arc.reset_used_arcs()
		Arc.set_diff_threshold(threshold)
		puzzle_cuts = self.__class__.make_puzzle_cuts(board_width, board_height, number_of_pieces, tap_shape, threshold)

		
		# Draw puzzle cuts
		x = 0
		y = 0
		for i in range(0, int(self.thickness / self.step_z)):
			for cut in puzzle_cuts:
				block.append(CNC.zsafe())
				block.append(CNC.grapid(x + cut[0].x, y + cut[0].y))
				block.append(CNC.zenter(0.0))
				block.append(CNC.fmt("f", self.cut_feed))
				block.append(CNC.zenter(-(i + 1) * self.step_z))
				for arc in cut:
					if arc.r:
						block.append(CNC.garc(arc.direction, x + arc.x, y + arc.y, r=arc.r))

		blocks.append(block)

		# Draw border
		block = Block(self.name + "_border")

		block.append(CNC.zsafe())
		block.append(CNC.grapid(x, y))

		for i in range(0, int(self.thickness / self.step_z)):
			block.append(CNC.fmt("f",self.cut_feed))
			block.append(CNC.zenter(-(i + 1) * self.step_z))
			block.append(CNC.gline(x + board_width, y))
			block.append(CNC.gline(x + board_width, y + board_height))
			block.append(CNC.gline(x, y + board_height))
			block.append(CNC.gline(x, y))

		block.append(CNC.zsafe())
		blocks.append(block)

		return blocks