Esempio n. 1
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
Esempio n. 2
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
Esempio n. 3
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
Esempio n. 4
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
Esempio n. 5
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)
Esempio n. 6
0
    def create_block(self, holes, name):
        targetDepth = self.fromMm("TargetDepth")
        peck = self.fromMm("Peck")
        dwell = self["Dwell"]
        block = Block(name)
        holesCount = 0

        if self.useCustom:
            block.append("M3 S0")
        else:
            block.append(CNC.zsafe())

        for bid in holes:
            for xH, yH, zH in bid:
                holesCount += 1

                if self.useCustom:
                    block.append(
                        CNC.grapid(x=xH, y=yH) + CNC.fmt(' F', self.rFeed))
                else:
                    #block.append(CNC.zsafe()) # Moved up
                    block.append(CNC.grapid(xH, yH))

                if peck != 0:
                    z = 0
                    while z > targetDepth:
                        z = max(z - peck, targetDepth)
                        if self.useCustom:
                            block.append(
                                "( --- WARNING! Peck is not setup for laser mode --- )"
                            )
                            break
                        else:
                            block.append(CNC.zenter(zH + z))
                            block.append(CNC.zsafe())

                if self.useCustom:
                    block.append("G1 S%s" % (self.spinMax))
                    block.append(CNC.gline(x=xH, y=yH))
                else:
                    block.append(CNC.zenter(zH + targetDepth))

                # Dwell time only on last pass
                if dwell != 0:
                    block.append(CNC.gcode(4, [("P", dwell)]))

                if self.useCustom:
                    block.append("G1 S%s" % (self.spinMin))
                else:
                    block.append(CNC.zsafe())

        # Gcode Zsafe on finish
        if self.useCustom:
            block.append("M5")
        else:
            block.append(CNC.zsafe())
        return (block, holesCount)
Esempio n. 7
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
Esempio n. 8
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)
Esempio n. 9
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>>")
Esempio n. 10
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>>")
Esempio n. 11
0
    def make(self, RExt=50.0, RInt=33.0, ROff=13.0, 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.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
Esempio n. 12
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
Esempio n. 13
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
Esempio n. 14
0
    def _rectangle(self, block, x0, y0, dx, dy, nx, ny, ex=0., ey=0.):
        block.append("(  Location: %g,%g )" % (x0, y0))
        block.append("(  Dimensions: %g,%g )" % (dx, dy))
        block.append("(  Teeth: %d,%d )" % (nx, ny))
        block.append("(  Tool diameter: %g )" % (self.tool))

        # Start with full length
        sx = dx / abs(nx)
        sy = dy / abs(ny)

        # Bottom
        pos = Vector(x0, y0, self.surface)
        pos -= self.r * Vector.Y  # r*V
        block.append(CNC.gcode(0, zip("XY", pos[:2])))

        z = self.surface
        #for z in frange(self.surface-self.stepz, self.surface-self.thick, -self.stepz):
        last = False
        while True:
            if self.cut:
                z -= self.stepz
                if z <= self.surface - self.thick:
                    z = self.surface - self.thick
                    last = True
            else:
                last = True

            pos[2] = z

            # Penetrate
            block.append(CNC.zenter(pos[2]))

            # Bottom
            pos = self.zigZagLine(block, pos, sx, self.thick, Vector.X,
                                  Vector.Y, nx, ex)
            block.append("")

            # Right
            pos = self.zigZagLine(block, pos, sy, self.thick, Vector.Y,
                                  -Vector.X, ny, ey)
            block.append("")

            # Top
            pos = self.zigZagLine(block, pos, sx, self.thick, -Vector.X,
                                  -Vector.Y, nx, ex)
            block.append("")

            # Right
            pos = self.zigZagLine(block, pos, sy, self.thick, -Vector.Y,
                                  Vector.X, ny, ey)
            block.append("")
            if last: break

        # Bring to safe height
        block.append(CNC.zsafe())
Esempio n. 15
0
	def writeGlyphContour(self,block,font,contours,fontSize,depth,xO, yO):
		width = font.header.x_max - font.header.x_min
		height = font.header.y_max - font.header.y_min
		scale = fontSize / font.header.units_per_em
		xO = xO * fontSize
		yO = yO * fontSize
		for cont in contours:
			block.append(CNC.zsafe())
			block.append(CNC.grapid(xO + cont[0].x * scale , yO + cont[0].y * scale))
			block.append(CNC.zenter(depth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			for p in cont:
				block.append(CNC.gline(xO + p.x * scale, yO + p.y * scale))
Esempio n. 16
0
	def writeGlyphContour(self,block,font,contours,fontSize,depth,xO, yO):
		width = font.header.x_max - font.header.x_min
		height = font.header.y_max - font.header.y_min
		scale = fontSize / font.header.units_per_em
		xO = xO * fontSize
		yO = yO * fontSize
		for cont in contours:
			block.append(CNC.zsafe())
			block.append(CNC.grapid(xO + cont[0].x * scale , yO + cont[0].y * scale))
			block.append(CNC.zenter(depth))
			block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])]))
			for p in cont:
				block.append(CNC.gline(xO + p.x * scale, yO + p.y * scale))
Esempio n. 17
0
	def _rectangle(self, block, x0, y0, dx, dy, nx, ny, ex=0., ey=0.):
		block.append("(  Location: %g,%g )"%(x0,y0))
		block.append("(  Dimensions: %g,%g )"%(dx,dy))
		block.append("(  Teeth: %d,%d )"%(nx,ny))
		block.append("(  Tool diameter: %g )"%(self.tool))

		# Start with full length
		sx = dx / abs(nx)
		sy = dy / abs(ny)

		# Bottom
		pos = Vector(x0, y0, self.surface)
		pos -= self.r*Vector.Y	# r*V
		block.append(CNC.gcode(0, zip("XY",pos[:2])))

		z = self.surface
		#for z in frange(self.surface-self.stepz, self.surface-self.thick, -self.stepz):
		last = False
		while True:
			if self.cut:
				z -= self.stepz
				if z <= self.surface - self.thick:
					z = self.surface - self.thick
					last = True
			else:
				last = True

			pos[2] = z

			# Penetrate
			block.append(CNC.zenter(pos[2]))

			# Bottom
			pos = self.zigZagLine(block, pos, sx, self.thick, Vector.X, Vector.Y, nx, ex)
			block.append("")

			# Right
			pos = self.zigZagLine(block, pos, sy, self.thick, Vector.Y, -Vector.X, ny, ey)
			block.append("")

			# Top
			pos = self.zigZagLine(block, pos, sx, self.thick, -Vector.X, -Vector.Y, nx, ex)
			block.append("")

			# Right
			pos = self.zigZagLine(block, pos, sy, self.thick, -Vector.Y, Vector.X, ny, ey)
			block.append("")
			if last: break

		# Bring to safe height
		block.append(CNC.zsafe())
Esempio n. 18
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)
Esempio n. 19
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)
Esempio n. 20
0
File: gear.py Progetto: multpix/bCNC
	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
Esempio n. 21
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)
			# Removes vertical offset (centers the ball tool in Z=0, rather than the tip)
			depth  = r * math.sin(-currAngle) - toolRadius
			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
Esempio n. 22
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))
Esempio n. 23
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)
Esempio n. 24
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 == "":
            app.setStatus(_("Flatten abort: Cut Direction is undefined"))
            return

        if PocketType == "":
            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 stress 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
            lastxy = None
            for x, y in zip(xP, yP):
                #				block.append(CNC.gline(x,y))
                if lastxy != CNC.gline(x, y) or None:
                    block.append(CNC.gline(x, y))
                lastxy = 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
Esempio n. 25
0
File: bowl.py Progetto: asm7100/bCNC
	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
Esempio n. 26
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?"))
Esempio n. 27
0
File: text.py Progetto: dogsop/bCNC
    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")
Esempio n. 28
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")
Esempio n. 29
0
class Tool(Plugin):
	__doc__ =  _("Create text using a ttf font")
	def __init__(self, master):
		Plugin.__init__(self, master, "Text")
		self.icon  = "text"
		self.group = "Generator"

		self.variables = [("name",      "db" ,    "", _("Name")),
				("Text",        "text", "Write this!", _("Text to generate")),
				("Depth",       "mm",    0.0, _("Working Depth")),
				("FontSize",    "mm",   10.0, _("Font size")),
				("FontFile",    "file",   "", _("Font file")),
                                ("Closed",      "bool", True, _("Close Contours")),
				("ImageToAscii","file",   "", _("Image to Ascii")),
				("CharsWidth",  "int",    80, _("Image chars width"))]
		self.buttons.append("exe")

	# ----------------------------------------------------------------------
	def execute(self, app):

		#Get inputs
		fontSize      = self.fromMm("FontSize")
		depth         = self.fromMm("Depth")
		textToWrite   = self["Text"]
		fontFileName  = self["FontFile"]
        closed        = self["Closed"]
		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,closed)
				if(not gc):
					gc = font.get_glyph_contours(0,closed)#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")
Esempio n. 30
0
def line(self, app, end_depth, mem_0, mem_1):
    """Create GCode for a Line"""
    x_start = min(OCV.WK_mems[mem_0][0], OCV.WK_mems[mem_1][0])
    y_start = min(OCV.WK_mems[mem_0][1], OCV.WK_mems[mem_1][1])

    x_end = max(OCV.WK_mems[mem_0][0], OCV.WK_mems[mem_1][0])
    y_end = max(OCV.WK_mems[mem_0][1], OCV.WK_mems[mem_1][1])

    z_start = OCV.WK_mems[mem_1][2]

    tool_dia = OCV.CD['diameter']
    # tool_rad = tool_dia / 2.
    xy_stepover = tool_dia * OCV.CD['stepover'] / 100.0

    z_stepover = OCV.CD['stepz']

    # avoid infinite while loop
    if z_stepover == 0:
        z_stepover = 0.001

    msg = ("Line Cut Operation: \n",
           "Start: \n\n{0}\n\n".format(OCV.showC(x_start, y_start, z_start)),
           "End: \n\n{0}\n\n".format(OCV.showC(x_end, y_end, end_depth)),
           "Tool diameter: {0:.{1}f} \n\n".format(tool_dia, OCV.digits),
           "StepDown: {0:.{1}f} \n\n".format(z_stepover, OCV.digits),
           "StepOver: {0:.{1}f} \n\n".format(xy_stepover, OCV.digits))

    retval = tkMessageBox.askokcancel("Line Cut", "".join(msg))

    if OCV.DEBUG is True:
        print("RetVal", retval)

    if retval is False:
        return

    # Reset the Gcode in the Editor
    # Loading an empty file

    # Set the Initialization file
    blocks = []
    block = Block("Init")
    # Get the current WCS as the mem are related to it
    block.append(OCV.CD['WCS'])
    blocks.append(block)

    block = Block("Line")
    block.append("(Line Cut)")
    block.append("(From: {0})".format(OCV.gcodeCC(x_start, y_start, z_start)))
    block.append("(To: {0})".format(OCV.gcodeCC(x_end, y_end, end_depth)))
    block.append("(StepDown: {0:.{1}f} )".format(z_stepover, OCV.digits))
    block.append("(StepOver: {0:.{1}f} )".format(xy_stepover, OCV.digits))
    block.append("(Tool diameter = {0:.{1}f})".format(tool_dia, OCV.digits))

    # Safe move to first point
    block.append(CNC.zsafe())
    block.append(CNC.grapid(x_start, y_start))

    # Init Depth corrected by z_stepover
    # for the correctness of the loop
    # the first instruction of the while loop is -= z_stepover
    # the check is done at the final depth

    curr_depth = z_start + z_stepover

    # Create GCode from points
    while True:
        curr_depth -= z_stepover

        if curr_depth < end_depth:
            curr_depth = end_depth

        block.append(CNC.zenter(curr_depth))
        block.append(CNC.gcode_string(1, [("F", OCV.CD["cutfeed"])]))

        block.append(CNC.gline(x_end, y_end))

        # Move to start in a safe way
        block.append(CNC.zsafe())
        block.append(CNC.grapid(x_start, y_start))

        # Check exit condition
        if curr_depth <= end_depth:
            break

    # return to a safe Z
    block.append(CNC.zsafe())
    blocks.append(block)

    if blocks is not None:
        active = OCV.APP.activeBlock()

        if active == 0:
            active = 1

        OCV.APP.gcode.insBlocks(active, blocks, "Line Cut")
        OCV.APP.refresh()
        OCV.APP.setStatus(_("Line Cut: Generated line cut code"))
Esempio n. 31
0
def pocket(self, app, end_depth, mem_0, mem_1):
    """create GCode for a pocket"""
    x_start = min(OCV.WK_mems[mem_0][0], OCV.WK_mems[mem_1][0])
    y_start = min(OCV.WK_mems[mem_0][1], OCV.WK_mems[mem_1][1])

    x_end = max(OCV.WK_mems[mem_0][0], OCV.WK_mems[mem_1][0])
    y_end = max(OCV.WK_mems[mem_0][1], OCV.WK_mems[mem_1][1])

    z_start = OCV.WK_mems[mem_1][2]

    tool_dia = OCV.CD['diameter']
    tool_rad = tool_dia / 2.

    xy_stepover = tool_dia * OCV.CD['stepover'] / 100.0

    z_stepover = OCV.CD['stepz']

    # avoid infinite while loop
    if z_stepover == 0:
        z_stepover = 0.001

    msg = ("Pocket Cut Operation: \n",
           "Start: \n\n{0}\n\n".format(OCV.showC(x_start, y_start, z_start)),
           "End: \n\n{0}\n\n".format(OCV.showC(x_end, y_end, end_depth)),
           "Tool diameter: {0:.{1}f} \n\n".format(tool_dia, OCV.digits),
           "StepDown: {0:.{1}f} \n\n".format(z_stepover, OCV.digits),
           "StepOver: {0:.{1}f} \n\n".format(xy_stepover, OCV.digits))

    retval = tkMessageBox.askokcancel("Pocket Cut", "".join(msg))

    if retval is False:
        return

    # Set the Initialization file
    blocks = []
    block = Block("Init")
    # Get the current WCS as the mem are related to it
    block.append(OCV.CD['WCS'])
    blocks.append(block)

    block = Block("Pocket")
    block.append("(Pocket)")
    block.append("(Start: {0})".format(OCV.gcodeCC(x_start, y_start, z_start)))
    block.append("(End: {0})".format(OCV.gcodeCC(x_end, y_end, end_depth)))
    block.append("(StepDown: {0:.{1}f} )".format(z_stepover, OCV.digits))
    block.append("(StepOver: {0:.{1}f} )".format(xy_stepover, OCV.digits))
    block.append("(Tool diameter = {0:.{1}f})".format(tool_dia, OCV.digits))

    # Move safe to first point
    block.append(CNC.zsafe())
    block.append(CNC.grapid(x_start, y_start))

    # Init Depth

    f_width = x_end - x_start
    f_heigth = y_end - y_start

    cut_dir = "Conventional"

    x_start_pocket = x_start + tool_rad
    y_start_pocket = y_start + tool_rad

    # Calc space to work with/without border cut
    travel_width = f_width - tool_dia
    travel_height = f_heigth - tool_dia

    if travel_width < tool_rad or travel_height < tool_rad:
        msg = "(Pocket aborted: Pocket area is too small for this End Mill.)"
        retval = tkMessageBox.askokcancel("Pocket Cut", msg)
        return

    # Prepare points for pocketing
    x_p = []
    y_p = []

    # Calc number of pass
    v_count = (int)(travel_height / xy_stepover)
    h_count = (int)(travel_width / xy_stepover)

    # Make them odd
    if v_count % 2 == 0:
        v_count += 1

    if h_count % 2 == 0:
        h_count += 1

    # Calc step minor of Max step
    h_stepover = travel_height / v_count
    w_stepover = travel_width / h_count

    # Start from border to center
    x_s = x_start_pocket
    y_s = y_start_pocket
    w_s = travel_width
    h_s = travel_height
    x_c = 0
    y_c = 0

    while x_c <= h_count / 2 and y_c <= v_count / 2:
        # Pocket offset points
        x_0, y_0 = rect_path(x_s, y_s, w_s, h_s)

        if cut_dir == "Conventional":
            x_0 = x_0[::-1]
            y_0 = y_0[::-1]

        x_p = x_p + x_0
        y_p = y_p + y_0
        x_s += h_stepover
        y_s += w_stepover
        h_s -= 2.0 * h_stepover
        w_s -= 2.0 * w_stepover
        x_c += 1
        y_c += 1

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

    # Move safe to first point
    block.append(CNC.zsafe())
    block.append(CNC.grapid(x_p[0], y_p[0]))

    # Init Depth corrected by z_stepover
    # for the correctness of the loop
    # the first instruction of the while loop is -= z_stepover
    # the check is done at the final depth
    curr_depth = z_start + z_stepover

    # Create GCode from points
    while True:
        curr_depth -= z_stepover

        if curr_depth < end_depth:
            curr_depth = end_depth

        block.append(CNC.zenter(curr_depth))
        block.append(CNC.gcode_string(1, [("F", OCV.CD["cutfeed"])]))

        # Pocketing
        for x_l, y_l in zip(x_p, y_p):
            block.append(CNC.gline(x_l, y_l))

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

        # Verify exit condition
        if curr_depth <= end_depth:
            break

    # end of the loop
    # return to z_safe
    block.append(CNC.zsafe())
    blocks.append(block)

    if blocks is not None:
        active = OCV.APP.activeBlock()

        if active == 0:
            active = 1

        OCV.APP.gcode.insBlocks(active, blocks, "Line Cut")
        OCV.APP.refresh()
        OCV.APP.setStatus(_("Line Cut: Generated line cut code"))
Esempio n. 32
0
def mop(self, app, mem_0, mem_1, mop_type):
    """create GCode for a pocket
    Values are stored in OCV.mop_vars as a dictionary"""

    end_depth = OCV.mop_vars["tdp"]
    x_start = min(OCV.WK_mems[mem_0][0], OCV.WK_mems[mem_1][0])
    y_start = min(OCV.WK_mems[mem_0][1], OCV.WK_mems[mem_1][1])

    x_end = max(OCV.WK_mems[mem_0][0], OCV.WK_mems[mem_1][0])
    y_end = max(OCV.WK_mems[mem_0][1], OCV.WK_mems[mem_1][1])

    z_start = OCV.WK_mems[mem_1][2]

    tool_dia = OCV.mop_vars["tdia"]
    tool_rad = tool_dia / 2.

    xy_stepover = OCV.mop_vars["mso"]

    z_stepover = OCV.mop_vars["msd"]

    # avoid infinite while loop
    if z_stepover == 0:
        z_stepover = 0.001

    if mop_type == "PK":
        # Pocketing
        isSpiral = OCV.mop_vars["pks"]

        isInt = OCV.mop_vars["sin"]

        if isSpiral is True:
            op_name = "Spiral Pocket"
        else:
            op_name = "Rectangular Pocket"

    elif mop_type == "LN":
        op_name = "Line"


    """
    cut_dir passed to the calculation method depends on starting point,
    If we cut from internal we minimize "full stock" cut
    in which the endmill is 'surrounded' by the material.
    For calculation these assumptions are done, maybe is wrong

    Conventionl cut is when piece is cut on left side of the cutter

    Climb cut is when piece is cut on right side
    """

    if mop_type == "PK":
        # Pocketing
        if isInt is True:
            cut_dir = 1
            reverse = True
        else:
            cut_dir = 0
            reverse = False

    msg = (
        "{} Operation: \n\n".format(op_name),
        "Start: \n\n{0}\n\n".format(OCV.showC(x_start, y_start, z_start)),
        "End: \n\n{0}\n\n".format(OCV.showC(x_end, y_end, end_depth)),
        "Tool diameter: {0:.{1}f} \n\n".format(tool_dia, OCV.digits),
        "StepDown: {0:.{1}f} \n\n".format(z_stepover, OCV.digits),
        "StepOver: {0:.{1}f} \n\n".format(xy_stepover, OCV.digits))

    retval = tkMessageBox.askokcancel(
        "MOP {} Cut".format(op_name), "".join(msg))

    if retval is False:
        return

    # Start Calculations

    start = (x_start, y_start)
    end = (x_end, y_end)

    if mop_type == "PK":
            # Pocketing
        # Assign points here
        if isSpiral is True:
            msg,x_p,y_p = spiral_pocket(start, end, tool_rad, xy_stepover, cut_dir)
        else:
            msg,x_p,y_p = spiral_pocket(start, end, tool_rad, xy_stepover, cut_dir)

        if msg != "OK":
            retval = tkMessageBox.askokcancel(op_name, msg)
            return

        if reverse is True:
            x_p.reverse()
            y_p.reverse()

    # Reset the editor and write the Gcode generated Here
    OCV.TK_MAIN.clear_gcode()
    OCV.TK_MAIN.clear_editor()
    OCV.TK_MAIN.reset_canvas()
    blocks = []
    block = Block.Block("Init")
    # Get the current WCS as the mem are related to it
    block.append(OCV.CD['WCS'])
    blocks.append(block)

    block = Block.Block(op_name)
    block.append("({})".format(op_name))
    block.append("(Tool diameter = {0:.{1}f})".format(tool_dia, OCV.digits))
    block.append("(Start: {0})".format(OCV.gcodeCC(x_start, y_start, z_start)))
    block.append("(End: {0})".format(OCV.gcodeCC(x_end, y_end, end_depth)))
    block.append("(StepDown: {0:.{1}f} )".format(z_stepover, OCV.digits))
    block.append("(StepOver: {0:.{1}f} )".format(xy_stepover, OCV.digits))

    if mop_type == "PK":
            # Pocketing
            # Move safe to first point
        block.append(CNC.zsafe())
        block.append(CNC.grapid(x_p[0], y_p[0]))
    elif mop_type == "LN":
        # Move safe to first point
        block.append(CNC.zsafe())
        block.append(CNC.grapid(x_start, y_start))
    else:
        return

    # the check is done at the final depth
    curr_depth = z_start

    print("curr_depth, z_start", curr_depth, z_start)
    # Create GCode from points
    while True:
        curr_depth -= z_stepover

        if curr_depth < end_depth:
            curr_depth = end_depth

        block.append(CNC.zenter(curr_depth))
        block.append(CNC.gcode_string(1, [("F", OCV.CD["cutfeed"])]))

        if mop_type == "PK":
            # Pocketing
            for x_l, y_l in zip(x_p, y_p):
                block.append(CNC.gline(x_l, y_l))

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

        elif mop_type == "LN":
            block.append(CNC.gline(x_end, y_end))
            # Move to the begin in a safe way
            block.append(CNC.zsafe())
            block.append(CNC.grapid(x_start, y_start))

        # Verify exit condition
        if curr_depth <= end_depth:
            break

    # end of the loop
    # return to z_safe
    block.append(CNC.zsafe())
    blocks.append(block)

    if blocks is not None:
        active = OCV.TK_MAIN.activeBlock()

        if active == 0:
            active = 1

        OCV.TK_MAIN.gcode.insBlocks(active, blocks, op_name)
        OCV.TK_MAIN.refresh()
        OCV.TK_MAIN.setStatus(_("{}: GCode Generated".format(op_name)))
Esempio n. 33
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
Esempio n. 34
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
Esempio n. 35
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
Esempio n. 36
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)
Esempio n. 37
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"]
        casual = self["Casual"]
        fading = self["Fading"]
        max_light = self["Max_light"]
        repetition = self["Repetition"]

        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 max_light > 256:
            app.setStatus(
                _("The maximum illumination shouldn't be more than 250!"))
            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 = []

        #Info block
        block = Block("Info")
        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))
        blocks.append(block)

        #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)

        #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, casual)

        #startAll = time.time()
        total_line = 0
        total_length = 0
        for c in range(squiggleTotal):
            x, y = self.findFirst(pix, False, casual)
            if pix[x, y] > max_light:
                continue
            block = Block(self.name)
            #print c,x,y
            #start = time.time()

            total_line += 1
            total_length += 1
            #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)
                if pix[x, y] > max_light:
                    break
                s += max(1, distance * self.ratio)  #add traveled distance
                total_length += 1
                #move there
                block.append(CNC.gline(x * self.ratio, y * self.ratio))
                self.fadePixel(
                    x, y, pix, fading,
                    repetition)  #adjustbrightness int the bright map
            #tool up
            #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 line:%i, Total length:%d"
              ) % (self.imgWidth * self.ratio, self.imgHeight * self.ratio,
                   depth, total_line, total_length))
Esempio n. 38
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)
Esempio n. 39
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))))
Esempio n. 40
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?"))
Esempio n. 41
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)
Esempio n. 42
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
Esempio n. 43
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)
Esempio n. 44
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
Esempio n. 45
0
    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))
Esempio n. 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))))
Esempio n. 47
0
	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))