def execute(self, app): name = self["name"] if not name or name == "default": name = "Spiral" #Retrive data from user imput Size = self.fromMm("Size") Rotation = self["Rot"] CW = self["CW"] #grwoth per arc if Rotation <= 0: Rotation = 1 grow = Size / Rotation / 4 #Clockwise g = 2 if CW else 3 #Initialize blocks that will contain our gCode blocks = [] block = Block(name) #use some useful bCNC functions to generate gCode movement, see CNC.py for more block.append( "G0 Z3" ) #<<< Move rapid Z axis to the safe height in Stock Material block.append("G0 X0 Y0") #<<< Move rapid to X and Y coordinate block.append( "G1 Z0 F100" ) #<<< Enter in the material with Plunge Feed for current material block.append("F600") #<<< Feedrate x, y = 0, 0 while abs(x) < Size / 2: lx = x #<<< Save last x value x = abs(x) + grow #<<< Add the growing value if lx >= 0: x = -x #<<< Alternate sign dx = x - lx #<<< Calculate delta X (r = i = dx/2) block.append(CNC.garc(g=g, x=x, i=dx / 2)) #Circle with final Size block.append(CNC.garc(g=g, x=-x, i=-x)) block.append(CNC.garc(g=g, x=x, i=x)) blocks.append(block) active = app.activeBlock() app.gcode.insBlocks( active, blocks, "MyPlugins inserted" ) #<<< insert blocks over active block in the editor app.refresh() #<<< refresh editor app.setStatus(_("Generated: Spiral")) #<<< feed back result
def calc(self, xstart, ystart, xend, yend, radius, cw): self.Points = [] self.corners = [ min(float(xstart), float(xend)), min(float(ystart), float(yend)), max(float(xstart), float(xend)), max(float(ystart), float(yend)), ] xmin, ymin, xmax, ymax = self.corners[0], self.corners[ 1], self.corners[2], self.corners[3] r = min(radius, (xmax - xmin) / 2, (ymax - ymin) / 2) blocks = [] block = Block(self.name) block.append(CNC.grapid(x=xmin, y=ymin + r)) block.append(CNC.grapid(z=0.0)) block.append("(entered)") if cw: block.append(CNC.gline(x=xmin, y=ymax - r)) if r > 0: block.append(CNC.garc(2, x=xmin + r, y=ymax, i=r, j=0)) if (xmax - xmin) > 2 * r: block.append(CNC.gline(x=xmax - r, y=ymax)) if r > 0: block.append(CNC.garc(2, x=xmax, y=ymax - r, i=0, j=-r)) if (ymax - ymin) > 2 * r: block.append(CNC.gline(x=xmax, y=ymin + r)) if r > 0: block.append(CNC.garc(2, x=xmax - r, y=ymin, i=-r, j=0)) if (xmax - xmin) > 2 * r: block.append(CNC.gline(x=xmin + r, y=ymin)) if r > 0: block.append(CNC.garc(2, x=xmin, y=ymin + r, i=0, j=r)) else: if r > 0: block.append(CNC.garc(3, x=xmin + r, y=ymin, i=r, j=0)) if (xmax - xmin) > 2 * r: block.append(CNC.gline(x=xmax - r, y=ymin)) if r > 0: block.append(CNC.garc(3, x=xmax, y=ymin + r, i=0, j=r)) if (ymax - ymin) > 2 * r: block.append(CNC.gline(x=xmax, y=ymax - r)) if r > 0: block.append(CNC.garc(3, x=xmax - r, y=ymax, i=-r, j=0)) if (xmax - xmin) > 2 * r: block.append(CNC.gline(x=xmin + r, y=ymax)) if r > 0: block.append(CNC.garc(3, x=xmin, y=ymax - r, i=0, j=-r)) if (ymax - ymin) > 2 * r: block.append(CNC.gline(x=xmin, y=ymin + r)) block.append("(exiting)") block.append(CNC.grapid(z=CNC.vars["safe"])) blocks.append(block) return blocks
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
def appendCircle(block): block.append("m5") block.append(CNC.grapid(x=x0, y=y0 + marksizehalf / 2, f=movefeed)) block.append(self.getPowerLine(app)) block.append( CNC.garc(2, x=x0, y=y0 + marksizehalf / 2, j=-marksizehalf / 2, i=0, f=drawfeed)) block.append("m5")
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
def calc(self, xcenter, ycenter, radius, startangle, endangle): self.Points = [] xcenter, ycenter, radius, startangle, endangle = float(xcenter), float( ycenter), abs(float(radius)), float(startangle), float(endangle) xstart = xcenter + radius * math.cos(startangle * math.pi / 180.0) xend = xcenter + radius * math.cos(endangle * math.pi / 180.0) ystart = ycenter + radius * math.sin(startangle * math.pi / 180.0) yend = ycenter + radius * math.sin(endangle * math.pi / 180.0) i = xcenter - xstart j = ycenter - ystart blocks = [] block = Block(self.name) block.append(CNC.grapid(x=xstart, y=ystart)) block.append(CNC.grapid(z=0.0)) block.append("(entered)") if startangle < endangle: direction = 3 else: direction = 2 block.append(CNC.garc(direction, x=xend, y=yend, i=i, j=j)) block.append("(exiting)") block.append(CNC.grapid(z=CNC.vars["safe"])) blocks.append(block) return blocks
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))))
def calc(self, N, phi, Pc): N = abs(N) # Pitch Circle D = N * Pc / math.pi R = D / 2.0 # Diametrical pitch Pd = N / D # Base Circle Db = D * math.cos(phi) Rb = Db / 2.0 # Addendum a = 1.0 / Pd # Outside Circle Ro = R + a Do = 2.0 * Ro # Tooth thickness T = math.pi * D / (2 * N) # undercut? U = 2.0 / (math.sin(phi) * (math.sin(phi))) needs_undercut = N < U # sys.stderr.write("N:%s R:%s Rb:%s\n" % (N,R,Rb)) # Clearance c = 0.0 # Dedendum b = a + c # Root Circle Rr = R - b Dr = 2.0 * Rr two_pi = 2.0 * math.pi half_thick_angle = two_pi / (4.0 * N) pitch_to_base_angle = self.involute_intersect_angle(Rb, R) pitch_to_outer_angle = self.involute_intersect_angle( Rb, Ro) # pitch_to_base_angle points = [] for x in range(1, N + 1): c = x * two_pi / N # angles pitch1 = c - half_thick_angle base1 = pitch1 - pitch_to_base_angle outer1 = pitch1 + pitch_to_outer_angle pitch2 = c + half_thick_angle base2 = pitch2 + pitch_to_base_angle outer2 = pitch2 - pitch_to_outer_angle # points b1 = self.point_on_circle(Rb, base1) p1 = self.point_on_circle(R, pitch1) o1 = self.point_on_circle(Ro, outer1) o2 = self.point_on_circle(Ro, outer2) p2 = self.point_on_circle(R, pitch2) b2 = self.point_on_circle(Rb, base2) if Rr >= Rb: pitch_to_root_angle = pitch_to_base_angle - self.involute_intersect_angle( Rb, Rr) root1 = pitch1 - pitch_to_root_angle root2 = pitch2 + pitch_to_root_angle r1 = self.point_on_circle(Rr, root1) r2 = self.point_on_circle(Rr, root2) points.append(r1) points.append(p1) points.append(o1) points.append(o2) points.append(p2) points.append(r2) else: r1 = self.point_on_circle(Rr, base1) r2 = self.point_on_circle(Rr, base2) points.append(r1) points.append(b1) points.append(p1) points.append(o1) points.append(o2) points.append(p2) points.append(b2) points.append(r2) first = points[0] del points[0] blocks = [] block = Block(self.name) blocks.append(block) block.append(CNC.grapid(first.x(), first.y())) block.append(CNC.zenter(0.0)) #print first.x(), first.y() for v in points: block.append(CNC.gline(v.x(), v.y())) #print v.x(), v.y() #print first.x(), first.y() block.append(CNC.gline(first.x(), first.y())) block.append(CNC.zsafe()) #block = Block("%s-center"%(self.name)) block = Block("%s-basecircle" % (self.name)) block.enable = False block.append(CNC.grapid(Db / 2, 0.)) block.append(CNC.zenter(0.0)) block.append(CNC.garc(CW, Db / 2, 0., i=-Db / 2)) block.append(CNC.zsafe()) blocks.append(block) return blocks
def calc(self, N, phi, Pc): N = abs(N) # Pitch Circle D = N * Pc / math.pi R = D / 2.0 # Diametrical pitch Pd = N / D # Base Circle Db = D * math.cos(phi) Rb = Db / 2.0 # Addendum a = 1.0 / Pd # Outside Circle Ro = R + a Do = 2.0 * Ro # Tooth thickness T = math.pi*D / (2*N) # undercut? U = 2.0 / (math.sin(phi) * (math.sin(phi))) needs_undercut = N < U # sys.stderr.write("N:%s R:%s Rb:%s\n" % (N,R,Rb)) # Clearance c = 0.0 # Dedendum b = a + c # Root Circle Rr = R - b Dr = 2.0*Rr two_pi = 2.0*math.pi half_thick_angle = two_pi / (4.0*N) pitch_to_base_angle = self.involute_intersect_angle(Rb, R) pitch_to_outer_angle = self.involute_intersect_angle(Rb, Ro) # pitch_to_base_angle points = [] for x in range(1,N+1): c = x * two_pi / N # angles pitch1 = c - half_thick_angle base1 = pitch1 - pitch_to_base_angle outer1 = pitch1 + pitch_to_outer_angle pitch2 = c + half_thick_angle base2 = pitch2 + pitch_to_base_angle outer2 = pitch2 - pitch_to_outer_angle # points b1 = self.point_on_circle(Rb, base1) p1 = self.point_on_circle(R, pitch1) o1 = self.point_on_circle(Ro, outer1) o2 = self.point_on_circle(Ro, outer2) p2 = self.point_on_circle(R, pitch2) b2 = self.point_on_circle(Rb, base2) if Rr >= Rb: pitch_to_root_angle = pitch_to_base_angle - self.involute_intersect_angle(Rb, Rr) root1 = pitch1 - pitch_to_root_angle root2 = pitch2 + pitch_to_root_angle r1 = self.point_on_circle(Rr, root1) r2 = self.point_on_circle(Rr, root2) points.append(r1) points.append(p1) points.append(o1) points.append(o2) points.append(p2) points.append(r2) else: r1 = self.point_on_circle(Rr, base1) r2 = self.point_on_circle(Rr, base2) points.append(r1) points.append(b1) points.append(p1) points.append(o1) points.append(o2) points.append(p2) points.append(b2) points.append(r2) first = points[0] del points[0] blocks = [] block = Block(self.name) blocks.append(block) block.append(CNC.grapid(first.x(), first.y())) block.append(CNC.zenter(0.0)) #print first.x(), first.y() for v in points: block.append(CNC.gline(v.x(), v.y())) #print v.x(), v.y() #print first.x(), first.y() block.append(CNC.gline(first.x(), first.y())) block.append(CNC.zsafe()) #block = Block("%s-center"%(self.name)) block = Block("%s-basecircle"%(self.name)) block.enable = False block.append(CNC.grapid(Db/2, 0.)) block.append(CNC.zenter(0.0)) block.append(CNC.garc(CW, Db/2, 0., i=-Db/2)) block.append(CNC.zsafe()) blocks.append(block) return blocks
def execute(self, app): 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))))
def addCircumference(radius): block.append(CNC.garc(2,radius, 0., i=-radius))
def appendCircle(block): block.append("m5") block.append(CNC.grapid(x=x0, y=y0 + marksizehalf / 2, f=movefeed)) block.append(self.getPowerLine(app)) block.append(CNC.garc(2, x=x0, y=y0 + marksizehalf / 2, j=-marksizehalf / 2, i=0, f=drawfeed)) block.append("m5")