Пример #1
0
class CirDrillPanel(wx.Panel, CNCObject):
	seqNo = 1
	def __init__(self, toolInfo, speedInfo, parent):
		CNCObject.__init__(self, parent, "drill:circle")
		self.toolInfo = toolInfo
		
		self.modified = False
		self.unsaved = False
		self.viewTitle = "Circular Drill Pattern %d" % CirDrillPanel.seqNo
		self.titleText = "G Code Generator: %s" % self.viewTitle
		CirDrillPanel.seqNo += 1
		
		wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		sizer = wx.GridBagSizer(wx.HORIZONTAL)
		sizer.Add(10, 10, wx.GBPosition(0, 4))
		ln = 1
		
		self.setTitleFlag()

		t = wx.StaticText(self, wx.ID_ANY, "Diameter")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teDiameter = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
		self.addWidget(self.teDiameter, "diameter")
		sizer.Add(self.teDiameter, pos=(ln, 1), flag=wx.LEFT, border=10)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
		td = "%6.3f" % toolInfo["diameter"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
		self.addWidget(self.teToolDiam, "tooldiameter")
		sizer.Add(self.teToolDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

		t = wx.StaticText(self, wx.ID_ANY, "Hole Diameter")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teHoleDiam = wx.TextCtrl(self, wx.ID_ANY, "3", style=wx.TE_RIGHT)
		self.addWidget(self.teHoleDiam, "holediameter")
		sizer.Add(self.teHoleDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Stepover")
		so = "%6.3f" % speedInfo["stepover"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teStepover = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
		self.addWidget(self.teStepover, "stepover")
		sizer.Add(self.teStepover, pos=(ln, 1), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=10)

		t = wx.StaticText(self, wx.ID_ANY, "Minimum space between")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teSpacing = wx.TextCtrl(self, wx.ID_ANY, "2", style=wx.TE_RIGHT)
		self.addWidget(self.teSpacing, "spacing")
		sizer.Add(self.teSpacing, pos=(ln, 3), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=10)
		ln += 1
		
		szOpts = wx.BoxSizer(wx.VERTICAL)
		self.cbInside = wx.CheckBox(self, wx.ID_ANY, "Inside Circle")
		self.addWidget(self.cbInside, "inside")
		self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbInside)
		szOpts.Add(self.cbInside)
		
		szOpts.AddSpacer(10)
		
		self.cbStagger = wx.CheckBox(self, wx.ID_ANY, "Staggered rows")
		self.addWidget(self.cbStagger, "stagger")
		self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbStagger)
		szOpts.Add(self.cbStagger)
		
		szOpts2 = wx.BoxSizer(wx.HORIZONTAL)
		szOpts2.AddSpacer(80)
		szOpts2.Add(szOpts)
		
		sizer.Add(szOpts2, pos=(ln, 0), span=(1, 2), border=5, flag=wx.TOP+wx.BOTTOM+wx.LEFT+wx.ALIGN_CENTER_VERTICAL)

		t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		sizer.Add(self.getCuttingDirection(), pos=(ln, 3), border=5, flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_VERTICAL)	
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Depth of Cut")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teDepth = wx.TextCtrl(self, wx.ID_ANY, "1", style=wx.TE_RIGHT)
		self.addWidget(self.teDepth, "depth")
		sizer.Add(self.teDepth, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
		dpp = "%6.3f" % speedInfo["depthperpass"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
		self.addWidget(self.tePassDepth, "passdepth")
		sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1
		
		self.cbRetract = wx.CheckBox(self, wx.ID_ANY, "Retract each pass")
		self.addWidget(self.cbRetract, "retract")
		sizer.Add(self.cbRetract, pos=(ln, 2), span=(1,2),
				flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_HORIZONTAL, border=5)
		self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbRetract)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Center X")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
		self.addWidget(self.teStartX, "centerx")
		sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Center Y")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
		self.addWidget(self.teStartY, "centery")
		sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Center Z")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
		self.addWidget(self.teStartZ, "startz")
		sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
		self.addWidget(self.teSafeZ, "safez")
		sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1
		
		self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
		self.addWidget(self.cbAddSpeed, "addspeed")
		sizer.Add(self.cbAddSpeed, pos=(ln, 0), span=(1,4),
				flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_HORIZONTAL, border=5)
		self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
		self.cbAddSpeed.SetValue(self.settings.addspeed)
		ln += 1
		
		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
		g0xy = "%7.2f" % speedInfo["G0XY"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedXYG0, "feedXYG0")
		sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
		g1xy = "%7.2f" % speedInfo["G1XY"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedXYG1, "feedXYG1")
		sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
		g0z = "%7.2f" % speedInfo["G0Z"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedZG0, "feedZG0")
		sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
		g1z = "%7.2f" % speedInfo["G1Z"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedZG1, "feedZG1")
		sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

		self.teFeedXYG0.Enable(self.settings.addspeed)
		self.teFeedXYG1.Enable(self.settings.addspeed)
		self.teFeedZG0.Enable(self.settings.addspeed)
		self.teFeedZG1.Enable(self.settings.addspeed)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
		self.addWidget(self.teDecimals, "decimals")
		sizer.Add(self.teDecimals, pos=(ln, 1), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=10)

		t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		sizer.Add(self.getMeasurementSystem(), pos=(ln, 3), border=5, flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_VERTICAL)	
		ln += 1

		sizer.Add(20, 20, wx.GBPosition(ln, 0))
		ln += 1
		
		bsz = self.buttons()
		
		sizer.Add(bsz, pos=(ln, 0), span=(1,4),
				flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_HORIZONTAL, border=5)
		ln += 1
		
		sizer.Add(10, 10, wx.GBPosition(ln, 0))
		ln += 1
		
		self.gcl = GCodeList(self)
		sizer.Add(self.gcl, pos=(ln, 0), span=(1, 4), flag=wx.LEFT+wx.EXPAND, border=10)
		ln += 1
		
		sizer.Add(10, 10, wx.GBPosition(ln, 0))

		self.Bind(wx.EVT_TEXT, self.onChange)
		self.Bind(wx.EVT_RADIOBUTTON, self.onChange)
		
		self.SetSizer(sizer)
		self.Layout()
		self.Fit();
		
	def getMeasurementSystem(self):
		labels = ["Metric", "Imperial"]
		self.rbMeas = []
		sz = wx.BoxSizer(wx.VERTICAL)
		for i in range(len(labels)):
			if i == 0:
				style = wx.RB_GROUP
			else:
				style = 0
			r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
			sz.Add(r)
			self.addWidget(r, labels[i])
			self.rbMeas.append(r)
		if self.settings.metric:
			self.setChosen(self.rbMeas, "Metric")
		else:
			self.setChosen(self.rbMeas, "Imperial")
		return sz
	
	def getCuttingDirection(self):
		labels = ["Clockwise", "Counter Clockwise"]
		self.rbCutDir = []
		sz = wx.BoxSizer(wx.VERTICAL)
		for i in range(len(labels)):
			if i == 0:
				style = wx.RB_GROUP
			else:
				style = 0
			r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
			self.addWidget(r, labels[i])
			sz.Add(r)
			self.rbCutDir.append(r)
		return sz
		
	def onCbAddSpeed(self, _):
		self.setState(True, False)
		flag = self.cbAddSpeed.IsChecked()
		self.teFeedXYG0.Enable(flag)
		self.teFeedXYG1.Enable(flag)
		self.teFeedZG0.Enable(flag)
		self.teFeedZG1.Enable(flag)
		
	def bGeneratePressed(self, _):
		self.bSave.Enable(False)
		self.bVisualize.Enable(False)
		self.gcl.clear()
		self.gcode = []

		errs = []
		try:
			dec = int(self.teDecimals.GetValue())
			self.fmt = "%0." + str(dec) + "f"
		except:
			errs.append("Decimal Places")
		try:
			sx = float(self.teStartX.GetValue())
		except:
			errs.append("Center X")
		try:
			sy = float(self.teStartY.GetValue())
		except:
			errs.append("Center Y")
		try:
			sz = float(self.teStartZ.GetValue())
		except:
			errs.append("Center Z")
		try:
			safez = float(self.teSafeZ.GetValue())
		except:
			errs.append("Safe Z")
			
		addspeed = self.cbAddSpeed.IsChecked()
		try:
			feedzG0 = float(self.teFeedZG0.GetValue())
		except:
			errs.append("Z G0 Speed")
		try:
			feedzG1 = float(self.teFeedZG1.GetValue())
		except:
			errs.append("Z G1 Speed")
		try:
			feedxyG0 = float(self.teFeedXYG0.GetValue())
		except:
			errs.append("XY G0 Speed")
		try:
			feedxyG23 = float(self.teFeedXYG1.GetValue())
		except:
			errs.append("XY G1 Speed")
		try:
			cdiam = float(self.teDiameter.GetValue())
		except:
			errs.append("Overall Diameter")
		try:
			depth = float(self.teDepth.GetValue())
		except:
			errs.append("Depth")
		try:
			passdepth = float(self.tePassDepth.GetValue())
		except:
			errs.append("Depth per Pass")
		try:
			tdiam = float(self.teToolDiam.GetValue())
		except:
			errs.append("Tool Diameter")
		try:
			hdiam = float(self.teHoleDiam.GetValue())
		except:
			errs.append("Hole Diameter")
		try:
			spacing = float(self.teSpacing.GetValue())
		except:
			errs.append("Spacing")
		try:
			stepover = float(self.teStepover.GetValue())
		except:
			errs.append("Stepover")

		if not ValidateNoEntryErrors(self, errs):
			return
		
		inside = self.cbInside.IsChecked()
		stagger = self.cbStagger.IsChecked()
		retract = self.cbRetract.IsChecked()
		
		if not ValidateToolSize(self, tdiam, hdiam, "Hole Diameter"):
			return
		
		if not ValidateMinLength(self, cdiam, hdiam + spacing, "Overall diameter", "Hole diameter + spacing"):
			return

		self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam, self.toolInfo, safez)
		
		if inside:
			radlimit = cdiam/2 - hdiam/2
		else:
			radlimit = cdiam/2
			
		minx = sx - cdiam/2
		maxx = sx + cdiam/2
		miny = sy - cdiam/2
		maxy = sy + cdiam/2
			
		cd = self.getChosen(self.rbCutDir)
		if cd == "Clockwise":
			cmd = "G2"
		else:
			cmd = "G3"
		
		nrows = int((maxy - miny)/(hdiam+spacing))
		ncols = int((maxx - minx)/(hdiam+spacing))

		if not ValidateNonZero(self, ncols, "Number of calculated columns"):
			return		
		if not ValidateNonZero(self, nrows, "Number of calculated rows"):
			return		
		
		xstep = (maxx - minx) / float(ncols)
		ystep = (maxy - miny) / float(nrows)
		
		if stagger:
			ystep *= 0.866
			nrows = int((nrows/0.866)+0.5)
		
		if self.settings.annotate:
			self.gcode.append("(Circular drill pattern center (%6.2f,%6.2f) diameter %6.2f depth from %6.2f to %6.2f)" % (sx, sy, cdiam, sz, depth))
			self.gcode.append("(Cut Direction: %s)" % cd)
			self.gcode.append("(Inside Circle: %s)" % str(inside))
			self.gcode.append("(Retract each pass: %s)" % str(retract))
			self.gcode.append("(Hole diameter: %6.2f)" % hdiam)
			self.gcode.append("(Stagger rows: %s)" % str(stagger))
			self.gcode.append("(Calculated step x/y: %6.2f/%6.2f)" % (xstep, ystep))

		self.gcode.append(("G0 Z"+self.fmt+self.speedTerm(addspeed, feedzG0)) % (safez))
		
		points = [(sx, sy)]
		ix = 1
		while sx + ix*xstep <= maxx:
			if ix*xstep <= radlimit:
				points = [(sx - ix*xstep, sy)] + points + [(sx + ix*xstep, sy)]
			ix += 1
			
		iy = 1
		while sy + iy*ystep <= maxy:
			rowu = []
			rowd = []
			ix = 0
			if stagger and iy%2 != 0:
				bx = xstep/2
			else:
				bx = 0
				
			while sx + ix*xstep + bx <= maxx:
				r = triangulate((0,0), (ix*xstep+bx, iy*ystep))
				if r <= radlimit:
					if bx == 0 and ix == 0:
						rowu.append((sx + ix*xstep + bx, sy + iy*ystep))
						rowd.append((sx + ix*xstep + bx, sy - iy*ystep))
					else:
						rowu = [(sx - ix*xstep - bx, sy + iy*ystep)] + rowu + [(sx + ix*xstep + bx, sy + iy*ystep)]
						rowd = [(sx - ix*xstep - bx, sy - iy*ystep)] + rowd + [(sx + ix*xstep + bx, sy - iy*ystep)]
				ix += 1

			points = rowu + points + rowd
			iy += 1
			
		passes = int(math.ceil(depth/passdepth))
		for p in points:
			self.gcode.append(("G0 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG0)) % (p[0], p[1]))
			cz = sz
			for i in range(passes):
				cz -= passdepth
				if cz < -depth:
					cz = -depth
				self.gcode.append(("G1 Z"+self.fmt+self.speedTerm(addspeed, feedzG1)) % (cz))
				if self.settings.annotate:
					self.gcode.append("(Pass number %d at depth %f)" % (i, cz))
				if hdiam > tdiam:
					maxyoff = (hdiam-tdiam)/2.0
					yoff = stepover
					while True:
						if yoff > maxyoff:
							yoff = maxyoff
						self.gcode.append(("G1 Y"+self.fmt+self.speedTerm(addspeed, feedxyG0)) % (p[1]-yoff))
						self.gcode.append((cmd+" J"+self.fmt+" X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG23)) % (yoff, p[0], p[1]-yoff))
						if yoff >= maxyoff:
							break
						yoff += stepover
						
					self.gcode.append(("G1 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG23)) % (p[0], p[1]))

				if retract:
					self.gcode.append(("G0 Z"+self.fmt+self.speedTerm(addspeed, feedzG0)) % (safez))
					
			if not retract:
				self.gcode.append(("G0 Z"+self.fmt+self.speedTerm(addspeed, feedzG0)) % (safez))
		
		if self.settings.annotate:
			self.gcode.append("(End object %s)" % self.viewTitle)
		self.gcl.updateList(self.gcode)
		self.bSave.Enable()
		self.bVisualize.Enable()
		self.setState(False, True)
Пример #2
0
class GridPanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "carve:hatch")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Cross Hatch Pattern %d" % GridPanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        GridPanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Total X Size")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSizeX = wx.TextCtrl(self, wx.ID_ANY, "100", style=wx.TE_RIGHT)
        self.addWidget(self.teSizeX, "sizex")
        sizer.Add(self.teSizeX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Total Y Size")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSizeY = wx.TextCtrl(self, wx.ID_ANY, "100", style=wx.TE_RIGHT)
        self.addWidget(self.teSizeY, "sizey")
        sizer.Add(self.teSizeY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Perpendicular Gap")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teGap = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teGap, "gap")
        sizer.Add(self.teGap, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiam")
        sizer.Add(self.teToolDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Angle")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teAngle = wx.TextCtrl(self, wx.ID_ANY, "45", style=wx.TE_RIGHT)
        self.addWidget(self.teAngle, "angle")
        sizer.Add(self.teAngle, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Y Offset")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teYOffset = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teYOffset, "yoffset")
        sizer.Add(self.teYOffset, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Starting Point")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getStartingPoints(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Add Border")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.cbBorder = wx.CheckBox(self, wx.ID_ANY)
        self.addWidget(self.cbBorder, "border")
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbBorder)
        sizer.Add(self.cbBorder,
                  pos=(ln, 1),
                  flag=wx.LEFT + wx.RIGHT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getStartingPoints(self):
        labels = [
            "Lower Left", "Upper Left", "Lower Right", "Upper Right", "Center"
        ]
        self.rbStartPoints = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbStartPoints.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            sz.Add(r)
            self.addWidget(r, labels[i])
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG1 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            totalx = float(self.teSizeX.GetValue())
        except:
            errs.append("Size X")
        try:
            totaly = float(self.teSizeY.GetValue())
        except:
            errs.append("Size Y")
        try:
            totaldepth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            angle = float(self.teAngle.GetValue())
        except:
            errs.append("Angle")
        try:
            gap = float(self.teGap.GetValue())
        except:
            errs.append("Perpendicular Gap")
        try:
            yoffset = float(self.teYOffset.GetValue())
        except:
            errs.append("Y Offset")
        try:
            self.tDiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")

        if not ValidateNoEntryErrors(self, errs):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), self.tDiam,
                                   self.toolInfo, safez)

        border = self.cbBorder.IsChecked()
        addspeed = self.cbAddSpeed.IsChecked()

        plist = hatch(angle, sx, sy, sx + totalx, sy + totaly, gap, yoffset)

        sp = self.getChosen(self.rbStartPoints)
        adjx = 0
        adjy = 0
        if sp == "Upper Left":
            adjy = -totaly
        elif sp == "Upper Right":
            adjy = -totaly
            adjx = -totalx
        elif sp == "Lower Right":
            adjx = -totalx
        elif sp == "Center":
            adjx = -totalx / 2
            adjy = -totaly / 2

        points = [[[p[0][0] + adjx, p[0][1] + adjy],
                   [p[1][0] + adjx, p[1][1] + adjy]] for p in plist]

        corners = [[sx + adjx, sy + adjy], [sx + adjx, sy + totaly + adjy],
                   [sx + totalx + adjx, sy + totaly + adjy],
                   [sx + totalx + adjx, sy + adjy]]

        passes = int(math.ceil(float(totaldepth) / float(passdepth)))
        if self.settings.annotate:
            self.gcode.append(
                "(Cross Hatch pattern start (%6.2f,%6.2f) width %6.2f height %6.2f depth from %6.2f to %6.2f)"
                % (sx, sy, totalx, totaly, sz, totaldepth))
            self.gcode.append("(Start point: %s)" % sp)
            self.gcode.append("(Y offset: %6.2f)" % yoffset)
            self.gcode.append("(Cut border: %s)" % str(border))
            self.gcode.append("(Gap: %6.2f)" % gap)
            self.gcode.append("(Angle: %6.2f)" % angle)

        depth = 0
        flag = True
        for i in range(passes):
            depth += passdepth
            if depth > totaldepth: depth = totaldepth
            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, depth))

            self.gcode.append(
                ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                safez)
            for p in points:
                if flag:
                    xa = p[0][0]
                    ya = p[0][1]
                    xb = p[1][0]
                    yb = p[1][1]
                else:
                    xa = p[1][0]
                    ya = p[1][1]
                    xb = p[0][0]
                    yb = p[0][1]
                flag = not flag

                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG0)) % (xa, ya))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (sz - depth))
                self.gcode.append(
                    ("G1 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG1)) % (xb, yb))
                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))

            if border:
                self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG0)) %
                                  (corners[0][0], corners[0][1]))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (sz - depth))
                self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG1)) %
                                  (corners[1][0], corners[1][1]))
                self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG1)) %
                                  (corners[2][0], corners[2][1]))
                self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG1)) %
                                  (corners[3][0], corners[3][1]))
                self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG1)) %
                                  (corners[0][0], corners[0][1]))
                self.gcode.append(
                    ("G0 Z" + self.fmt + "" +
                     self.speedTerm(addspeed, feedzG0) + "\n") % (safez))

        self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                           self.speedTerm(addspeed, feedxyG0)) % (sx, sy))
        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)
        self.gcl.updateList(self.gcode)
        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)
Пример #3
0
class RectanglePanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "contour:rectangle")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Rectangle %d" % RectanglePanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        RectanglePanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Height")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teHeight = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teHeight, "height")
        sizer.Add(self.teHeight, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Width")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teWidth = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teWidth, "width")
        sizer.Add(self.teWidth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Rotation Angle")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teAngle = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teAngle, "angle")
        sizer.Add(self.teAngle, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Starting Point")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getStartingPoints(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Movement")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getToolMovement(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getCuttingDirection(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Pocket")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getPockets(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Stepover")
        so = "%6.3f" % speedInfo["stepover"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStepOver = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
        self.addWidget(self.teStepOver, "stepover")
        sizer.Add(self.teStepOver,
                  pos=(ln, 3),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getStartingPoints(self):
        labels = [
            "Lower Left", "Upper Left", "Lower Right", "Upper Right", "Center"
        ]
        self.rbStartPoints = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbStartPoints.append(r)
        return sz

    def getToolMovement(self):
        labels = ["On Rectangle", "Outside Rectangle", "Inside Rectangle"]
        self.rbToolMove = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbToolMove.append(r)
        return sz

    def getCuttingDirection(self):
        labels = ["Clockwise", "Counter Clockwise"]
        self.rbCutDir = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbCutDir.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def getPockets(self):
        labels = ["None", "Horizontal", "Vertical", "Centered"]
        self.rbPkts = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbPkts.append(r)
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        addspeed = self.cbAddSpeed.IsChecked()
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG1 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            height = float(self.teHeight.GetValue())
        except:
            errs.append("Height")
        try:
            width = float(self.teWidth.GetValue())
        except:
            errs.append("Width")
        try:
            depth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")
        try:
            stepover = float(self.teStepOver.GetValue())
        except:
            errs.append("Stepover")
        try:
            angle = float(self.teAngle.GetValue())
        except:
            errs.append("Angle")

        if not ValidateNoEntryErrors(self, errs):
            return

        rot = Rotator(angle)

        if not ValidateToolSize(self, tdiam, height, "Height"):
            return
        if not ValidateToolSize(self, tdiam, width, "Width"):
            return

        if not ValidateRange(self, stepover, 0.001, 1.0, "Stepover",
                             "0 < x <= 1.0"):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, safez)

        self.tDiam = tdiam
        if self.settings.annotate:
            if angle == 0:
                self.gcode.append(
                    "(Rectangle (%6.2f,%6.2f) to (%6.2f,%6.2f) depth from %6.2f to %6.2f)"
                    % (sx, sy, width, height, sz, depth))
            else:
                rx1, ry1 = rot.rotate(sx, sy)
                rx2, ry2 = rot.rotate(width + sx, height + sy)
                self.gcode.append(
                    "(Rectangle (%6.2f,%6.2f) to (%6.2f,%6.2f) depth from %6.2f to %6.2f rotated %6.2f)"
                    % (rx1, ry1, rx2, ry2, sz, depth, angle))

        points = [[sx, sy], [sx, sy + height], [sx + width, sy + height],
                  [sx + width, sy], [sx, sy]]

        sp = self.getChosen(self.rbStartPoints)
        adjx = 0
        adjy = 0
        if sp == "Upper Left":
            adjy = -height
        elif sp == "Upper Right":
            adjy = -height
            adjx = -width
        elif sp == "Lower Right":
            adjx = -width
        elif sp == "Center":
            adjx = -width / 2
            adjy = -height / 2

        for p in points:
            p[0] += adjx
            p[1] += adjy

        tm = self.getChosen(self.rbToolMove)
        rad = float(tdiam) / 2.0
        if tm == "Inside Rectangle":
            points[0][0] += rad
            points[0][1] += rad
            points[1][0] += rad
            points[1][1] -= rad
            points[2][0] -= rad
            points[2][1] -= rad
            points[3][0] -= rad
            points[3][1] += rad
            points[4][0] += rad
            points[4][1] += rad

        elif tm == "Outside Rectangle":
            points[0][0] -= rad
            points[0][1] -= rad
            points[1][0] -= rad
            points[1][1] += rad
            points[2][0] += rad
            points[2][1] += rad
            points[3][0] += rad
            points[3][1] -= rad
            points[4][0] -= rad
            points[4][1] -= rad

        cd = self.getChosen(self.rbCutDir)
        if cd != "Clockwise":
            np = points[::-1]
            points = np

        pkt = self.getChosen(self.rbPkts)

        if self.settings.annotate:
            self.gcode.append("(Start point: %s)" % sp)
            self.gcode.append("(Cutting direction: %s)" % cd)
            self.gcode.append("(Tool movement: %s)" % tm)
            self.gcode.append("(Pocket: %s)" % pkt)

        if pkt == "None":
            self.gcode.append(
                ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                (safez))
            self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(addspeed, feedxyG0)) %
                              rot.rotate(points[0][0], points[0][1]))

        xmin = min(points[0][0], points[2][0]) + tdiam / 2
        xmax = max(points[0][0], points[2][0]) - tdiam / 2
        ymin = min(points[0][1], points[2][1]) + tdiam / 2
        ymax = max(points[0][1], points[2][1]) - tdiam / 2

        passes = int(math.ceil(depth / passdepth))

        cz = sz
        xlast = 0
        ylast = 0
        for i in range(passes):
            cz -= passdepth
            if cz < -depth:
                cz = -depth
            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, cz))

            if pkt == "Horizontal":
                first = True
                alt = True
                y = ymin
                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG0)) %
                                  rot.rotate(xmin, ymin))

                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))
                while y <= ymax:
                    if not first:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xlast, y))

                    if alt:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xmax, y))
                        xlast = xmax
                    else:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xmin, y))
                        xlast = xmin
                    y += tdiam * stepover
                    first = False
                    alt = not alt

                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG0)) %
                                  rot.rotate(points[0][0], points[0][1]))

            elif pkt == "Vertical":
                first = True
                alt = True
                x = xmin
                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG0)) %
                                  rot.rotate(xmin, ymin))

                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))
                while x <= xmax:
                    if not first:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(x, ylast))

                    if alt:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(x, ymax))
                        ylast = ymax
                    else:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(x, ymin))
                        ylast = ymin
                    x += tdiam * stepover
                    first = False
                    alt = not alt

                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG0)) %
                                  rot.rotate(points[0][0], points[0][1]))

            elif pkt == "Centered":
                vertical = False
                if (xmax - xmin) > (ymax - ymin):
                    ya = (ymax + ymin) / 2.0
                    yb = ya
                    d = ymax - ya
                    xa = xmin + d
                    xb = xmax - d
                elif (xmax - xmin) < (ymax - ymin):
                    vertical = True
                    xa = (xmax + xmin) / 2.0
                    xb = xa
                    d = xmax - xa
                    ya = ymin + d
                    yb = ymax - d
                else:
                    xa = (xmax + xmin) / 2.0
                    xb = xa
                    ya = (ymax + ymin) / 2.0
                    yb = ya

                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG0)) % rot.rotate(xb, yb))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))
                self.gcode.append(
                    ("G1 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG1)) % rot.rotate(xa, ya))

                d = stepover * tdiam
                while (xa - d) >= xmin:
                    if cd == "Clockwise":
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xa - d, ya - d))
                        if vertical:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xa - d, yb + d))
                        else:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xa - d, ya + d))
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xb + d, yb + d))
                        if vertical:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xb + d, ya - d))
                        else:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xb + d, yb - d))
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xa - d, ya - d))
                    else:
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xa - d, ya - d))
                        if vertical:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xb + d, ya - d))
                        else:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xb + d, yb - d))
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xb + d, yb + d))
                        if vertical:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xa - d, yb + d))
                        else:
                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG1)) %
                                rot.rotate(xa - d, ya + d))
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            rot.rotate(xa - d, ya - d))
                    d += stepover * tdiam

                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG0)) %
                                  rot.rotate(points[0][0], points[0][1]))

            self.gcode.append(
                ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) % (cz))
            for p in points[1:]:
                self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                   self.speedTerm(addspeed, feedxyG1)) %
                                  rot.rotate(p[0], p[1]))

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) % (safez))
        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)

        self.gcl.updateList(self.gcode)
        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)
Пример #4
0
class FileMergeDialog(wx.Dialog):
    def __init__(self, parent, title=DEFAULT_TITLE):
        wx.Dialog.__init__(self, parent, wx.ID_ANY, title)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        
        self.modified = False
        self.title = title
        self.parent = parent
        self.settings = self.parent.settings
        self.images = self.parent.images
        
        self.gCode = []
        
        hsizer=wx.BoxSizer(wx.HORIZONTAL)
        hsizer.AddSpacer(10)
        
        vsizer = wx.BoxSizer(wx.VERTICAL)
        vsizer.AddSpacer(10)
        
        self.gcl = GCodeList(self)
        vsizer.Add(self.gcl)
        
        vsizer.AddSpacer(20)
        
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.bAdd = wx.BitmapButton(self, wx.ID_ANY, self.images.pngAdd, size=BTNDIM)
        self.bAdd.SetToolTip("Add a file to the merge")
        btnSizer.Add(self.bAdd)
        self.Bind(wx.EVT_BUTTON, self.bAddPressed, self.bAdd)
        
        btnSizer.AddSpacer(10)

        self.bSave = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFilesaveas, size=BTNDIM)
        self.bSave.SetToolTip("Save files merged thus far")
        btnSizer.Add(self.bSave)
        self.Bind(wx.EVT_BUTTON, self.bSavePressed, self.bSave)
        self.bSave.Enable(False)
        
        btnSizer.AddSpacer(10)

        self.bView = wx.BitmapButton(self, wx.ID_ANY, self.images.pngView, size=BTNDIM)
        self.bView.SetToolTip("View the merged data")
        btnSizer.Add(self.bView)
        self.Bind(wx.EVT_BUTTON, self.bViewPressed, self.bView)
        self.bView.Enable(False)
        
        btnSizer.AddSpacer(60)

        self.bOK = wx.BitmapButton(self, wx.ID_ANY, self.images.pngExit, size=BTNDIM)
        btnSizer.Add(self.bOK)
        self.Bind(wx.EVT_BUTTON, self.bOKPressed, self.bOK)
          
        vsizer.Add(btnSizer, 1, wx.ALIGN_CENTER_HORIZONTAL)

 
        vsizer.AddSpacer(20)
        hsizer.Add(vsizer)       
        hsizer.AddSpacer(10)
        self.SetSizer(hsizer)
        self.Layout()
        self.Fit();
        
    def setTitle(self):
        t = self.title
        if self.modified:
            t += " *"
        self.SetTitle(t)
        
    def setModified(self, flag=True):
        self.modified = flag
        self.bSave.Enable(flag)
        self.setTitle()
       
    def bOKPressed(self, _):
        self.cancelMerge()
        
    def onClose(self, _):
        self.cancelMerge()
        
    def cancelMerge(self):
        if self.modified:
            dlg = wx.MessageDialog(self, 'Merged G Code not saved',
                               'Proceed?',
                               wx.YES_NO | wx.ICON_WARNING)
            rc = dlg.ShowModal()
            dlg.Destroy()
            if rc == wx.ID_NO:
                return 
            
        self.EndModal(wx.ID_CANCEL)
        
    def bAddPressed(self, _):
        dlg = AddToMergeDialog(self)
        if dlg.ShowModal() != wx.ID_OK:
            dlg.Destroy()
            return 

        self.gCode.extend(dlg.getGCode())
        dlg.Destroy()
            
        self.gcl.updateList(self.gCode)
            
        self.setModified()
        self.bView.Enable(True)
        
    def bViewPressed(self, _):
        self.gcl.visualize("Merged files")
        
    def bSavePressed(self, _):
        if self.gcl.save(self.settings):
            self.setModified(False)
Пример #5
0
class LinDrillPanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "drill:linear")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Linear Drill Pattern %d" % LinDrillPanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        LinDrillPanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safex")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Angle")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teAngle = wx.TextCtrl(self, wx.ID_ANY, "45", style=wx.TE_RIGHT)
        self.addWidget(self.teAngle, "angle")
        sizer.Add(self.teAngle, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Number of Holes")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teNHoles = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teNHoles, "numberholes")
        sizer.Add(self.teNHoles, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Hole Spacing")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSpacing = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teSpacing, "spacing")
        sizer.Add(self.teSpacing, pos=(ln, 1), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Hole Diameter")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teHoleDiam = wx.TextCtrl(self, wx.ID_ANY, "3", style=wx.TE_RIGHT)
        self.addWidget(self.teHoleDiam, "holediameter")
        sizer.Add(self.teHoleDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Step Over")
        so = "%6.3f" % speedInfo["stepover"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStepover = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
        self.addWidget(self.teStepover, "stepover")
        sizer.Add(self.teStepover, pos=(ln, 1), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getCuttingDirection(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        self.cbRetract = wx.CheckBox(self, wx.ID_ANY, "Retract each pass")
        self.addWidget(self.cbRetract, "retract")
        sizer.Add(self.cbRetract,
                  pos=(ln, 2),
                  span=(1, 2),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbRetract)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals,
                  pos=(ln, 1),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def getCuttingDirection(self):
        labels = ["Clockwise", "Counter Clockwise"]
        self.rbCutDir = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            sz.Add(r)
            self.addWidget(r, labels[i])
            self.rbCutDir.append(r)
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        addspeed = self.cbAddSpeed.IsChecked()
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG23 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            totaldepth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")
        try:
            hdiam = float(self.teHoleDiam.GetValue())
        except:
            errs.append("Hole Diameter")
        try:
            spacing = float(self.teSpacing.GetValue())
        except:
            errs.append("Spacing")
        try:
            nholes = int(self.teNHoles.GetValue())
        except:
            errs.append("Number of Holes")
        try:
            angle = float(self.teAngle.GetValue())
        except:
            errs.append("Angle")
        try:
            stepover = float(self.teStepover.GetValue())
        except:
            errs.append("Stepover")

        if not ValidateNoEntryErrors(self, errs):
            return
        if not ValidateToolSize(self, tdiam, hdiam, "Hole Diameter"):
            return
        if not ValidateMinLength(self, spacing, hdiam, "Hole Spacing",
                                 "Hole Diameter"):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, safez)

        retract = self.cbRetract.IsChecked()
        cd = self.getChosen(self.rbCutDir)
        if cd == "Clockwise":
            cmd = "G2"
        else:
            cmd = "G3"

        dy = spacing * math.sin(math.radians(angle))
        dx = spacing * math.cos(math.radians(angle))

        if self.settings.annotate:
            self.gcode.append(
                "(Linear drill pattern start (%6.2f,%6.2f) Number of holes %d depth from %6.2f to %6.2f)"
                % (sx, sy, nholes, sz, totaldepth))
            self.gcode.append("(Cut Direction: %s)" % cd)
            self.gcode.append("(Spacing: %6.2f)" % spacing)
            self.gcode.append("(Angle: %6.2f)" % angle)
            self.gcode.append("(Retract each pass: %s)" % str(retract))
            self.gcode.append("(Hole diameter: %6.2f)" % hdiam)
            self.gcode.append("(Calculated step x/y: %6.2f/%6.2f)" % (dx, dy))

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) % (safez))

        passes = int(math.ceil(totaldepth / passdepth))
        for ix in range(nholes):
            cx = sx + ix * dx
            cy = sy + ix * dy
            self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(addspeed, feedxyG0)) % (cx, cy))
            cz = sz
            for i in range(passes):
                cz -= passdepth
                if cz < -totaldepth:
                    cz = -totaldepth
                if self.settings.annotate:
                    self.gcode.append("(Pass number %d at depth %f)" % (i, cz))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))
                if hdiam > tdiam:
                    maxyoff = (hdiam - tdiam) / 2.0
                    yoff = stepover
                    while True:
                        if yoff > maxyoff:
                            yoff = maxyoff
                        self.gcode.append(
                            ("G1 Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG0)) % (cy - yoff))
                        self.gcode.append(
                            (cmd + " J" + self.fmt + " X" + self.fmt + " Y" +
                             self.fmt + self.speedTerm(addspeed, feedxyG23)) %
                            (yoff, cx, cy - yoff))
                        if yoff >= maxyoff:
                            break
                        yoff += stepover

                    self.gcode.append(
                        ("G1 X" + self.fmt + " Y" + self.fmt +
                         self.speedTerm(addspeed, feedxyG23)) % (cx, cy))

                if retract:
                    self.gcode.append(
                        ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0))
                        % (safez))

            if not retract:
                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))

        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)
        self.gcl.updateList(self.gcode)
        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)
Пример #6
0
class CirclePanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "contour:circle")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Circle %d" % CirclePanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        CirclePanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Circle Diameter")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDiam = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teDiam, "circlediameter")
        sizer.Add(self.teDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Center X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "centerx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Center Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "centery")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Center Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "centerz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G2/3)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getCuttingDirection(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Movement")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getToolMovement(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        self.cbPocket = wx.CheckBox(self, wx.ID_ANY, "Pocket")
        self.addWidget(self.cbPocket, "pocket")
        sizer.Add(self.cbPocket,
                  pos=(ln, 0),
                  span=(1, 2),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbPocket)

        t = wx.StaticText(self, wx.ID_ANY, "Stepover")
        so = "%6.3f" % speedInfo["stepover"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStepOver = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
        self.addWidget(self.teStepOver, "stepover")
        sizer.Add(self.teStepOver, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getToolMovement(self):
        labels = ["On Circle", "Outside Circle", "Inside Circle"]
        self.rbToolMove = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbToolMove.append(r)
        return sz

    def getCuttingDirection(self):
        labels = ["Clockwise", "Counter Clockwise"]
        self.rbCutDir = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbCutDir.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Center X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Center Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Center Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        addspeed = self.cbAddSpeed.IsChecked()
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG23 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            diam = float(self.teDiam.GetValue())
        except:
            errs.append("Diameter")
        try:
            depth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")
        try:
            stepover = float(self.teStepOver.GetValue())
        except:
            errs.append("Stepover")

        if not ValidateNoEntryErrors(self, errs):
            return

        if not ValidateToolSize(self, tdiam, diam, "Circle Diameter"):
            return

        if not ValidateRange(self, stepover, 0.001, 1.0, "Stepover",
                             "0 < x <= 1.0"):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, safez)

        self.tDiam = tdiam
        if self.settings.annotate:
            self.gcode.append(
                "(Circle center (%6.2f,%6.2f) radius %6.2f depth from %6.2f to %6.2f"
                % (sx, sy, diam / 2, sz, depth))

        tm = self.getChosen(self.rbToolMove)
        if tm == "Inside Circle":
            diam -= tdiam

        elif tm == "Outside Circle":
            diam += tdiam

        cd = self.getChosen(self.rbCutDir)
        if cd == "Clockwise":
            cmd = "G2"
        else:
            cmd = "G3"

        passes = int(math.ceil(depth / passdepth))
        pkt = self.cbPocket.IsChecked()

        if self.settings.annotate:
            self.gcode.append("(Cutting direction: %s)" % cd)
            self.gcode.append("(Tool movement: %s)" % tm)
            self.gcode.append("(Pocket: %s)" % pkt)

        if not pkt:
            self.gcode.append(
                ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                (safez))
            self.gcode.append(
                ("G0 X" + self.fmt + " Y" + self.fmt +
                 self.speedTerm(addspeed, feedxyG0)) % (sx, sy - diam / 2))

        cz = sz
        for i in range(passes):
            cz -= passdepth
            if cz < -depth:
                cz = -depth

            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, cz))

            if pkt:
                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG0)) % (sx, sy))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))
                r = tdiam * stepover
                while r < diam / 2:
                    self.gcode.append(
                        ("G1 Y" + self.fmt +
                         self.speedTerm(addspeed, feedxyG23)) % (sy - r))
                    self.gcode.append(
                        (cmd + " J" + self.fmt + " X" + self.fmt + " Y" +
                         self.fmt + self.speedTerm(addspeed, feedxyG23)) %
                        (r, sx, sy - r))
                    r += tdiam * stepover

                self.gcode.append(
                    ("G1 Y" + self.fmt + self.speedTerm(addspeed, feedxyG23)) %
                    (sy - diam / 2))
            else:
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))

            self.gcode.append(
                (cmd + " J" + self.fmt + " X" + self.fmt + " Y" + self.fmt +
                 self.speedTerm(addspeed, feedxyG23)) %
                (diam / 2, sx, sy - diam / 2))

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) % (safez))
        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)
        self.gcl.updateList(self.gcode)
        self.bSave.Enable(True)
        self.bVisualize.Enable()
        self.setState(False, True)
Пример #7
0
class PolyPanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "contour:polygon")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Regular Polygon %d" % PolyPanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        PolyPanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Side length")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSLength = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teSLength, "sidelength")
        sizer.Add(self.teSLength, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Number of Sides")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSides = wx.TextCtrl(self, wx.ID_ANY, "6", style=wx.TE_RIGHT)
        self.addWidget(self.teSides, "numbersides")
        sizer.Add(self.teSides, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Rotation Angle")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teAngle = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teAngle, "angle")
        sizer.Add(self.teAngle, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Center X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "centerx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Center Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "centery")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Center Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "centerz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getCuttingDirection(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Movement")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getToolMovement(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        self.cbPocket = wx.CheckBox(self, wx.ID_ANY, "Pocket")
        self.addWidget(self.cbPocket, "pocket")
        sizer.Add(self.cbPocket,
                  pos=(ln, 0),
                  span=(1, 2),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbPocket)

        t = wx.StaticText(self, wx.ID_ANY, "Stepover")
        so = "%6.3f" % speedInfo["stepover"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStepOver = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
        self.addWidget(self.teStepOver, "stepover")
        sizer.Add(self.teStepOver,
                  pos=(ln, 3),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getToolMovement(self):
        labels = ["On Polygon", "Outside Polygon", "Inside Polygon"]
        self.rbToolMove = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbToolMove.append(r)
        return sz

    def getCuttingDirection(self):
        labels = ["Clockwise", "Counter Clockwise"]
        self.rbCutDir = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbCutDir.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Center X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Center Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Center Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        addspeed = self.cbAddSpeed.IsChecked()
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG1 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            length = float(self.teSLength.GetValue())
        except:
            errs.append("Side Length")
        try:
            angle = float(self.teAngle.GetValue())
        except:
            errs.append("Angle")
        try:
            depth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")
        try:
            stepover = float(self.teStepOver.GetValue())
        except:
            errs.append("Stepover")
        try:
            sides = int(self.teSides.GetValue())
        except:
            errs.append("Number of Sides")

        if not ValidateNoEntryErrors(self, errs):
            return

        if not ValidateRange(self, stepover, 0.001, 1.0, "Stepover",
                             "0 < x <= 1.0"):
            return

        if not ValidateMinLength(self, sides, 3, "Mumber of Sides", "3"):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, safez)

        self.tDiam = tdiam
        if self.settings.annotate:
            self.gcode.append(
                "(Regular Polygon center at (%6.2f,%6.2f) depth from %6.2f to %6.2f"
                % (sx, sy, sz, depth))

        step = 360.0 / sides
        a = 0
        angles = []
        while a < 360:
            angles.append(a + angle)
            a += step

        angles = angles[:
                        sides]  #make sure we didn't get an extra one because of rounding
        angles.append(angles[0])

        cd = self.getChosen(self.rbCutDir)
        if cd == "Clockwise":
            na = angles[::-1]
            angles = na

        pkt = self.cbPocket.IsChecked()

        tm = self.getChosen(self.rbToolMove)
        if tm == "Inside Polygon":
            length -= tdiam / 2.0

        elif tm == "Outside Polygon":
            length += tdiam / 2.0

        passes = int(math.ceil(depth / passdepth))
        if self.settings.annotate:
            self.gcode.append("(Cutting direction: %s)" % cd)
            self.gcode.append("(Tool movement: %s)" % tm)
            self.gcode.append("(Pocket: %s)" % pkt)

        cz = sz
        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) % (safez))
        if not pkt:
            x = length * math.cos(math.radians(angles[0]))
            y = length * math.sin(math.radians(angles[0]))
            self.gcode.append(
                ("G0 X" + self.fmt + " Y" + self.fmt +
                 self.speedTerm(addspeed, feedxyG0)) % (x + sx, y + sy))

        for i in range(passes):
            cz -= passdepth
            if cz < -depth:
                cz = -depth
            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, cz))

            if pkt:
                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG0)) % (sx, sy))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))
                l = tdiam * stepover
                while l < length:
                    self.gcode.append("(pocket pass at radius %f)" % l)
                    for a in angles:
                        x = l * math.cos(math.radians(a))
                        y = l * math.sin(math.radians(a))
                        self.gcode.append(
                            ("G1 X" + self.fmt + " Y" + self.fmt +
                             self.speedTerm(addspeed, feedxyG1)) %
                            (x + sx, y + sy))
                    l += tdiam * stepover

                self.gcode.append("(final pass)")
                for a in angles:
                    x = length * math.cos(math.radians(a))
                    y = length * math.sin(math.radians(a))
                    self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                       self.speedTerm(addspeed, feedxyG1)) %
                                      (x + sx, y + sy))

                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))
            else:
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (cz))

                self.gcode.append("(contour only)")
                for a in angles[1:]:
                    x = length * math.cos(math.radians(a))
                    y = length * math.sin(math.radians(a))
                    self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                                       self.speedTerm(addspeed, feedxyG1)) %
                                      (x + sx, y + sy))

        if not pkt:
            self.gcode.append(
                ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                (safez))
        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)

        self.gcl.updateList(self.gcode)
        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)
Пример #8
0
class RecDrillPanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "drill:rectangle")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Rectangular Drill Pattern %d" % RecDrillPanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        RecDrillPanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Height")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teHeight = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teHeight, "height")
        sizer.Add(self.teHeight, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Width")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teWidth = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teWidth, "width")
        sizer.Add(self.teWidth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Angle")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teAngle = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teAngle, "angle")
        sizer.Add(self.teAngle,
                  pos=(ln, 3),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Hole Diameter")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teHoleDiam = wx.TextCtrl(self, wx.ID_ANY, "3", style=wx.TE_RIGHT)
        self.addWidget(self.teHoleDiam, "holediameter")
        sizer.Add(self.teHoleDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Minimum space between")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSpacing = wx.TextCtrl(self, wx.ID_ANY, "2", style=wx.TE_RIGHT)
        self.addWidget(self.teSpacing, "spacing")
        sizer.Add(self.teSpacing,
                  pos=(ln, 3),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)
        ln += 1

        szOpts = wx.BoxSizer(wx.VERTICAL)
        self.cbInside = wx.CheckBox(self, wx.ID_ANY, "Inside Rectangle")
        self.addWidget(self.cbInside, "inside")
        szOpts.AddSpacer(20)
        szOpts.Add(self.cbInside)
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbInside)

        self.cbPerimeter = wx.CheckBox(self, wx.ID_ANY, "Perimeter Only")
        self.addWidget(self.cbPerimeter, "perimeter")
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbPerimeter)
        self.Bind(wx.EVT_CHECKBOX, self.onCbPerimeter, self.cbPerimeter)

        self.cbStagger = wx.CheckBox(self, wx.ID_ANY, "Staggered rows")
        self.addWidget(self.cbStagger, "stagger")
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbStagger)
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbStagger)

        sizer.Add(szOpts,
                  pos=(ln, 0),
                  span=(2, 2),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)

        t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getCuttingDirection(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Starting Point")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getStartingPoints(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Depth of Cut")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDepth = wx.TextCtrl(self, wx.ID_ANY, "1", style=wx.TE_RIGHT)
        self.addWidget(self.teDepth, "depth")
        sizer.Add(self.teDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbRetract = wx.CheckBox(self, wx.ID_ANY,
                                     "Retract after each pass")
        self.addWidget(self.cbRetract, "retract")
        sizer.Add(self.cbRetract,
                  pos=(ln, 2),
                  span=(1, 2),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbRetract)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Stepover")
        so = "%6.3f" % speedInfo["stepover"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStepover = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
        self.addWidget(self.teStepover, "stepover")
        sizer.Add(self.teStepover,
                  pos=(ln, 1),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals,
                  pos=(ln, 1),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getStartingPoints(self):
        labels = [
            "Lower Left", "Upper Left", "Lower Right", "Upper Right", "Center"
        ]
        self.rbStartPoints = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            sz.Add(r)
            self.addWidget(r, labels[i])
            self.rbStartPoints.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            sz.Add(r)
            self.addWidget(r, labels[i])
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def getCuttingDirection(self):
        labels = ["Clockwise", "Counter Clockwise"]
        self.rbCutDir = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbCutDir.append(r)
        return sz

    def onCbPerimeter(self, _):
        self.setState(True, False)
        flag = self.cbPerimeter.IsChecked()
        self.cbStagger.Enable(not flag)

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bVisualize.Enable(False)
        self.bSave.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            angle = float(self.teAngle.GetValue())
        except:
            errs.append("Angle")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        addspeed = self.cbAddSpeed.IsChecked()
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG23 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            height = float(self.teHeight.GetValue())
        except:
            errs.append("Height")
        try:
            width = float(self.teWidth.GetValue())
        except:
            errs.append("Width")
        try:
            depth = float(self.teDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            stepover = float(self.teStepover.GetValue())
        except:
            errs.append("Stepover")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")
        try:
            hdiam = float(self.teHoleDiam.GetValue())
        except:
            errs.append("Hole Diameter")
        try:
            spacing = float(self.teSpacing.GetValue())
        except:
            errs.append("Spacing")

        if not ValidateNoEntryErrors(self, errs):
            return

        if not ValidateToolSize(self, tdiam, hdiam, "Hole Diameter"):
            return

        if not ValidateMinLength(self, height, hdiam + spacing, "Height",
                                 "Hole Diameter + Spacing"):
            return

        if not ValidateMinLength(self, width, hdiam + spacing, "Width",
                                 "Hole Diameter + Spacing"):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, safez)

        sp = self.getChosen(self.rbStartPoints)
        if sp == "Upper Left":
            sy -= height
        elif sp == "Upper Right":
            sy -= height
            sx -= width
        elif sp == "Lower Right":
            sx -= width
        elif sp == "Center":
            sx -= width / 2
            sy -= height / 2

        perimeteronly = self.cbPerimeter.IsChecked()
        inside = self.cbInside.IsChecked()
        if perimeteronly:
            stagger = False
        else:
            stagger = self.cbStagger.IsChecked()
        retract = self.cbRetract.IsChecked()

        if inside:
            minx = sx + hdiam / 2
            maxx = sx + width - hdiam / 2
            miny = sy + hdiam / 2
            maxy = sy + height - hdiam / 2
        else:
            minx = sx
            maxx = sx + width
            miny = sy
            maxy = sy + height

        cd = self.getChosen(self.rbCutDir)
        if cd == "Clockwise":
            cmd = "G2"
        else:
            cmd = "G3"

        nrows = int((maxy - miny) / (hdiam + spacing))
        ncols = int((maxx - minx) / (hdiam + spacing))

        xstep = (maxx - minx) / float(ncols)
        ystep = (maxy - miny) / float(nrows)

        if stagger:
            ystep *= 0.866
            nrows = int((nrows / 0.866) + 0.5)

        cx = minx
        cy = miny

        rot = None
        if angle != 0:
            rot = Rotator(angle)

        if self.settings.annotate:
            self.gcode.append(
                "(Rectangular drill pattern start (%6.2f,%6.2f) height %6.2f width %6.2f depth from %6.2f to %6.2f)"
                % (sx, sy, height, width, sz, depth))
            self.gcode.append("(Starting point: %s)" % sp)
            self.gcode.append("(Cut Direction: %s)" % cd)
            self.gcode.append("(Inside Circle: %s)" % str(inside))
            self.gcode.append("(Perimeter Only: %s)" % str(perimeteronly))
            self.gcode.append("(Retract each pass: %s)" % str(retract))
            self.gcode.append("(Hole diameter: %6.2f)" % hdiam)
            self.gcode.append("(Stagger rows: %s)" % str(stagger))
            self.gcode.append("(Calculated step x/y: %6.2f/%6.2f)" %
                              (xstep, ystep))

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) % (safez))

        passes = int(math.ceil(depth / passdepth))
        maxyoff = hdiam / 2 - tdiam / 2
        for iy in range(nrows + 1):
            for ix in range(ncols + 1):
                includeHole = False
                if not perimeteronly:
                    if cx <= maxx and cy <= maxy:
                        includeHole = True
                else:
                    if ix == 0 or ix == ncols or iy == 0 or iy == nrows:
                        includeHole = True

                if includeHole:
                    if rot is None:
                        nx = cx
                        ny = cy
                    else:
                        nx, ny = rot.rotate(cx, cy)

                    self.gcode.append(
                        ("G0 X" + self.fmt + " Y" + self.fmt +
                         self.speedTerm(addspeed, feedxyG0)) % (nx, ny))
                    cz = sz
                    for i in range(passes):
                        cz -= passdepth
                        if cz < -depth:
                            cz = -depth
                        if self.settings.annotate:
                            self.gcode.append("(Pass number %d at depth %f)" %
                                              (i, cz))
                        self.gcode.append(
                            ("G1 Z" + self.fmt +
                             self.speedTerm(addspeed, feedzG1)) % (cz))
                        if hdiam > tdiam:
                            maxyoff = (hdiam - tdiam) / 2.0
                            yoff = stepover
                            while True:
                                if yoff > maxyoff:
                                    yoff = maxyoff
                                self.gcode.append(
                                    ("G1 Y" + self.fmt +
                                     self.speedTerm(addspeed, feedxyG0)) %
                                    (ny - yoff))
                                self.gcode.append(
                                    (cmd + " J" + self.fmt + " X" + self.fmt +
                                     " Y" + self.fmt +
                                     self.speedTerm(addspeed, feedxyG23)) %
                                    (yoff, nx, ny - yoff))
                                if yoff >= maxyoff:
                                    break
                                yoff += stepover

                            self.gcode.append(
                                ("G1 X" + self.fmt + " Y" + self.fmt +
                                 self.speedTerm(addspeed, feedxyG23)) %
                                (nx, ny))

                        if retract:
                            self.gcode.append(
                                ("G0 Z" + self.fmt +
                                 self.speedTerm(addspeed, feedzG0)) % (safez))

                    if not retract:
                        self.gcode.append(
                            ("G0 Z" + self.fmt +
                             self.speedTerm(addspeed, feedzG0)) % (safez))

                cx += xstep
            cy += ystep
            if stagger and iy % 2 == 0:
                cx = minx + xstep / 2
            else:
                cx = minx

        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)
        self.gcl.updateList(self.gcode)
        self.setState(False, True)
        self.bVisualize.Enable()
        self.bSave.Enable()
Пример #9
0
class PolyPanel(wx.Panel, CNCObject):
	seqNo = 1
	def __init__(self, toolInfo, speedInfo, parent):
		CNCObject.__init__(self, parent, "contour:polyline")
		self.toolInfo = toolInfo
		
		self.modified = False
		self.unsaved = False
		self.viewTitle = "Polyline %d" % PolyPanel.seqNo
		self.titleText = "G Code Generator: %s" % self.viewTitle
		PolyPanel.seqNo += 1

		wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
		self.Bind(wx.EVT_CLOSE, self.onClose)
		sizer = wx.GridBagSizer(wx.HORIZONTAL)
		sizer.Add(10, 10, wx.GBPosition(0, 4))
		ln = 1
		
		self.setTitleFlag()

		t = wx.StaticText(self, wx.ID_ANY, "Point List")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.tePoints = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_RIGHT + wx.TE_READONLY)
		self.addWidget(self.tePoints, "pointlist")
		sizer.Add(self.tePoints, pos=(ln, 1), span=(1,2), flag=wx.EXPAND, border=10)
		self.bEditPoints = wx.Button(self, wx.ID_ANY, "...", size=(30, 20))
		self.bEditPoints.SetToolTip("Edit Point List")
		
		bsz = wx.BoxSizer(wx.HORIZONTAL)
		bsz.AddSpacer(20)
		bsz.Add(self.bEditPoints)
		
		sizer.Add(bsz, pos=(ln, 3))
		self.Bind(wx.EVT_BUTTON, self.bEditPointsPressed, self.bEditPoints)
		ln += 1
		
		self.cbClosePath = wx.CheckBox(self, wx.ID_ANY, "Close Path")
		self.addWidget(self.cbClosePath, "closepath")
		sizer.Add(self.cbClosePath, pos=(ln, 0), span=(1,4),
				flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_HORIZONTAL, border=5)
		self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbClosePath)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Start Z")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
		self.addWidget(self.teStartZ, "startz")
		sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
		self.addWidget(self.teSafeZ, "safez")
		sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teTotalDepth = wx.TextCtrl(self, wx.ID_ANY, "1", style=wx.TE_RIGHT)
		self.addWidget(self.teTotalDepth, "totaldepth")
		sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
		dpp = "%6.3f" % speedInfo["depthperpass"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
		self.addWidget(self.tePassDepth, "passdepth")
		sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1
		
		self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
		self.addWidget(self.cbAddSpeed, "addspeed")
		sizer.Add(self.cbAddSpeed, pos=(ln, 0), span=(1,4),
				flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_HORIZONTAL, border=5)
		self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
		self.cbAddSpeed.SetValue(self.settings.addspeed)
		ln += 1
		
		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
		g0xy = "%7.2f" % speedInfo["G0XY"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedXYG0, "feedXYG0")
		sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
		g1xy = "%7.2f" % speedInfo["G1XY"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedXYG1, "feedXYG1")
		sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
		g0z = "%7.2f" % speedInfo["G0Z"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedZG0, "feedZG0")
		sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)
		
		t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
		g1z = "%7.2f" % speedInfo["G1Z"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
		self.addWidget(self.teFeedZG1, "feedZG1")
		sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

		self.teFeedXYG0.Enable(self.settings.addspeed)
		self.teFeedXYG1.Enable(self.settings.addspeed)
		self.teFeedZG0.Enable(self.settings.addspeed)
		self.teFeedZG1.Enable(self.settings.addspeed)
		ln += 1

		t = wx.StaticText(self, wx.ID_ANY, "Tool Movement")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		sizer.Add(self.getToolMovement(), pos=(ln, 1), border=5, flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_VERTICAL)	

		t = wx.StaticText(self, wx.ID_ANY, "Tracks")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		
		self.scTracks = wx.SpinCtrl(self, wx.ID_ANY, "", size=(50, -1), style=wx.ALIGN_RIGHT)
		self.addWidget(self.scTracks, "tracks")
		self.scTracks.SetRange(1,20)
		self.scTracks.SetValue(1)
		self.Bind(wx.EVT_SPINCTRL, self.onTracks, self.scTracks)
		sz = wx.BoxSizer(wx.HORIZONTAL)
		sz.AddSpacer(30)
		sz.Add(self.scTracks)
		sizer.Add(sz, pos=(ln, 3), border=5, flag=wx.LEFT+wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_VERTICAL)	

		ln += 1
		t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
		td = "%6.3f" % toolInfo["diameter"]
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
		self.addWidget(self.teToolDiam, "tooldiameter")
		sizer.Add(self.teToolDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

		t = wx.StaticText(self, wx.ID_ANY, "Stepover")
		so = "%6.3f" % speedInfo["stepover"]
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teStepOver = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
		self.addWidget(self.teStepOver, "stepover")
		sizer.Add(self.teStepOver, pos=(ln, 3), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=10)
		ln += 1
		
		t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
		sizer.Add(t, pos=(ln, 0), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		sizer.Add(self.getMeasurementSystem(), pos=(ln, 1), border=5, flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_VERTICAL)	
		
		t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
		sizer.Add(t, pos=(ln, 2), flag=wx.LEFT+wx.ALIGN_CENTER_VERTICAL, border=20)		
		self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
		self.addWidget(self.teDecimals, "decimals")
		sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
		ln += 1

		sizer.Add(20, 20, wx.GBPosition(ln, 0))
		ln += 1
		
		bsz = self.buttons()
		
		sizer.Add(bsz, pos=(ln, 0), span=(1,4),
				flag=wx.TOP+wx.BOTTOM+wx.ALIGN_CENTER_HORIZONTAL, border=5)
		ln += 1
		
		sizer.Add(10, 10, wx.GBPosition(ln, 0))
		ln += 1
		
		self.gcl = GCodeList(self)
		sizer.Add(self.gcl, pos=(ln, 0), span=(1, 4), flag=wx.LEFT+wx.EXPAND, border=10)
		ln += 1
		
		sizer.Add(10, 10, wx.GBPosition(ln, 0))

		self.Bind(wx.EVT_TEXT, self.onChange)
		self.Bind(wx.EVT_RADIOBUTTON, self.onChange)
		
		self.SetSizer(sizer)
		self.Layout()
		self.Fit();
		
	def getToolMovement(self):
		labels = ["On Polyline", "Left of Forward", "Right of Forward"]
		self.rbToolMove = []
		sz = wx.BoxSizer(wx.VERTICAL)
		for i in range(len(labels)):
			if i == 0:
				style = wx.RB_GROUP
			else:
				style = 0
			r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
			self.addWidget(r, labels[i])
			sz.Add(r)
			self.rbToolMove.append(r)
		return sz
	
	def getMeasurementSystem(self):
		labels = ["Metric", "Imperial"]
		self.rbMeas = []
		sz = wx.BoxSizer(wx.VERTICAL)
		for i in range(len(labels)):
			if i == 0:
				style = wx.RB_GROUP
			else:
				style = 0
			r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
			self.addWidget(r, labels[i])
			sz.Add(r)
			self.rbMeas.append(r)
		if self.settings.metric:
			self.setChosen(self.rbMeas, "Metric")
		else:
			self.setChosen(self.rbMeas, "Imperial")
		return sz
		
	def onCbAddSpeed(self, _):
		self.setState(True, False)
		flag = self.cbAddSpeed.IsChecked()
		self.teFeedXYG0.Enable(flag)
		self.teFeedXYG1.Enable(flag)
		self.teFeedZG0.Enable(flag)
		self.teFeedZG1.Enable(flag)
		
	def onTracks(self, _):
		self.setState(True, False)
		
	def bEditPointsPressed(self, _):
		try:
			data = eval(self.tePoints.GetValue())
		except:
			data = None
			
		minVal = 2
		if self.cbClosePath.IsChecked():
			minVal = 3
			
		dlg = PointListEditDialog(self, data, minVal)
		rc = dlg.ShowModal()
		if rc == wx.ID_OK:
			self.tePoints.SetValue(str(dlg.getValues()))
			self.setState(True, False)
			
		dlg.Destroy()
				
	def bGeneratePressed(self, _):
		self.bSave.Enable(False)
		self.bVisualize.Enable(False)
		self.gcl.clear()
		self.gcode = []
		
		errs = []
		try:
			dec = int(self.teDecimals.GetValue())
			self.fmt = "%0." + str(dec) + "f"
		except:
			errs.append("Decimal Places")
		try:
			data = eval(self.tePoints.GetValue())
		except:
			errs.append("Point List")
		try:
			sz = float(self.teStartZ.GetValue())
		except:
			errs.append("Start Z")
		try:
			safez = float(self.teSafeZ.GetValue())
		except:
			errs.append("Safe Z")
			
		closePath = self.cbClosePath.IsChecked()
		addspeed = self.cbAddSpeed.IsChecked()
		try:
			feedzG0 = float(self.teFeedZG0.GetValue())
		except:
			errs.append("Z G0 Speed")
		try:
			feedzG1 = float(self.teFeedZG1.GetValue())
		except:
			errs.append("Z G1 Speed")
		try:
			feedxyG0 = float(self.teFeedXYG0.GetValue())
		except:
			errs.append("XY G0 Speed")
		try:
			feedxyG1 = float(self.teFeedXYG1.GetValue())
		except:
			errs.append("XY G1 Speed")
		try:
			depth = float(self.teTotalDepth.GetValue())
		except:
			errs.append("Depth")
		try:
			passdepth = float(self.tePassDepth.GetValue())
		except:
			errs.append("Depth per Pass")
		try:
			tdiam = float(self.teToolDiam.GetValue())
		except:
			errs.append("Tool Diameter")
		try:
			stepover = float(self.teStepOver.GetValue())
		except:
			errs.append("Stepover")
			
		if not ValidateNoEntryErrors(self, errs):
			return
		
		if closePath and len(data) < 3:
			ValidateTrue(self, False, "Need >2 points for a closed path")
			return
		
		if not ValidateRange(self, stepover, 0.001, 1.0, "Stepover", "0 < x <= 1.0"):
			return

		self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam, self.toolInfo, safez)
			
		self.tDiam = tdiam
		if self.settings.annotate:
			self.gcode.append("(Polyline depth from %6.2f to %6.2f" % (sz, depth))	
		
		tracks = self.scTracks.GetValue()
		
		tm = self.getChosen(self.rbToolMove)

		passes = int(math.ceil(depth/passdepth))
			
		if tm == "Left of Forward":
			offset = tdiam/2.0
			offset2 = stepover
		elif tm == "Right of Forward":
			offset = -tdiam/2.0
			offset2 = -stepover
		else:
			offset = 0
			offset2 = 0
			if tracks != 1:
				dlg = wx.MessageDialog(self, "Cannot have more than 1 track when tool movement is \"On Polyline\".\nAssuming a value of 1.",
							'Only 1 Track permitted', wx.OK | wx.ICON_WARNING)
				dlg.ShowModal()
				dlg.Destroy()
				
			tracks = 1
			
		if offset != 0:
			data = offsetPath(data, offset, closePath)
			if data is None:
				ValidateTrue(self, False, "Unable to calculate offset path for track 0")
				return
			
		if self.settings.annotate:
			self.gcode.append("(Tool movement: %s)" % tm)
			self.gcode.append("(Tracks: %d)" % tracks)
			
		cz = sz - passdepth
		if cz < -depth:
			cz = -depth
		self.gcode.append(("G0 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG0)) % (data[0][0], data[0][1]))
		saveData = [x for x in data]
		
		for p in range(passes):
			if self.settings.annotate:
				self.gcode.append("(pass %d at depth %6.2f)" % (p, cz))
			self.gcode.append(("G1 Z"+self.fmt+self.speedTerm(addspeed, feedzG1)) % (cz))
			for trk in range(tracks):
				for pt in data[1:]:
					self.gcode.append(("G1 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG1)) % (pt[0], pt[1]))
				
				if closePath:
					self.gcode.append(("G1 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG1)) % (data[0][0], data[0][1]))
				else:
					self.gcode.append(("G0 Z"+self.fmt+self.speedTerm(addspeed, feedzG0)) % (safez))
					self.gcode.append(("G0 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG1)) % (data[0][0], data[0][1]))
					self.gcode.append(("G1 Z"+self.fmt+self.speedTerm(addspeed, feedzG1)) % (cz))
					
				if trk+1 < tracks: # if not last track
					data = offsetPath(data, offset2, closePath)
					if data is None:
						ValidateTrue(self, False, "Unable to calculate offset path for track %d" % (trk+1))
						return
					self.gcode.append(("G1 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG1)) % (data[0][0], data[0][1]))
			
			data = [x for x in saveData]
			self.gcode.append(("G1 X"+self.fmt+" Y"+self.fmt+self.speedTerm(addspeed, feedxyG1)) % (data[0][0], data[0][1]))
			cz -= passdepth
			if cz < -depth:
				cz = -depth
		
		self.gcode.append(("G0 Z"+self.fmt+self.speedTerm(addspeed, feedzG0)) % (safez))
		if self.settings.annotate:
			self.gcode.append("(End object %s)" % self.viewTitle)
			
		self.gcl.updateList(self.gcode)
		self.bSave.Enable()
		self.bVisualize.Enable()
		self.setState(False, True)
Пример #10
0
class GridPanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "carve:grid")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Grid Pattern %d" % GridPanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        GridPanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Total X Size")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSizeX = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teSizeX, "sizex")
        sizer.Add(self.teSizeX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Total Y Size")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSizeY = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teSizeY, "sizey")
        sizer.Add(self.teSizeY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "X Segments")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teXSegments = wx.TextCtrl(self,
                                       wx.ID_ANY,
                                       "10",
                                       style=wx.TE_RIGHT)
        self.addWidget(self.teXSegments, "xsegments")
        sizer.Add(self.teXSegments, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Y Segments")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teYSegments = wx.TextCtrl(self,
                                       wx.ID_ANY,
                                       "10",
                                       style=wx.TE_RIGHT)
        self.addWidget(self.teYSegments, "ysegments")
        sizer.Add(self.teYSegments, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 1), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Starting Point")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getStartingPoints(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getStartingPoints(self):
        labels = [
            "Lower Left", "Upper Left", "Lower Right", "Upper Right", "Center"
        ]
        self.rbStartPoints = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbStartPoints.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            sz.Add(r)
            self.addWidget(r, labels[i])
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")

        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG1 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            sizex = float(self.teSizeX.GetValue())
        except:
            errs.append("Size X")
        try:
            sizey = float(self.teSizeY.GetValue())
        except:
            errs.append("Size Y")
        try:
            totaldepth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            segmentx = int(self.teXSegments.GetValue())
        except:
            errs.append("X Segments")
        try:
            segmenty = int(self.teYSegments.GetValue())
        except:
            errs.append("Y Segments")
        try:
            self.tDiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")

        if not ValidateNoEntryErrors(self, errs):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), self.tDiam,
                                   self.toolInfo, safez)

        addspeed = self.cbAddSpeed.IsChecked()

        segszx = sizex / segmentx
        segszy = sizey / segmenty

        sp = self.getChosen(self.rbStartPoints)
        adjx = 0
        adjy = 0
        if sp == "Upper Left":
            adjy = -sizey
        elif sp == "Upper Right":
            adjy = -sizey
            adjx = -sizex
        elif sp == "Lower Right":
            adjx = -sizex
        elif sp == "Center":
            adjx = -sizex / 2
            adjy = -sizey / 2

        xvals = [sx + i * segszx + adjx for i in range(segmentx + 1)]
        yvals = [sy + i * segszy + adjy for i in range(segmenty + 1)]

        points = []

        flag = False
        for i in range(0, segmentx + 1):
            if not flag:
                points.append([xvals[i], yvals[0], xvals[i], yvals[-1]])
            else:
                points.append([xvals[i], yvals[-1], xvals[i], yvals[0]])
            flag = not flag

        flag = False
        for i in range(0, segmenty + 1):
            if not flag:
                points.append([xvals[0], yvals[i], xvals[-1], yvals[i]])
            else:
                points.append([xvals[-1], yvals[i], xvals[0], yvals[i]])
            flag = not flag

        passes = int(math.ceil(float(totaldepth) / float(passdepth)))
        if self.settings.annotate:
            self.gcode.append(
                "(Grid pattern start (%6.2f,%6.2f) width %6.2f height %6.2f segments %d,%d depth from %6.2f to %6.2f)"
                % (sx, sy, sizex, sizey, segmentx, segmenty, sz, totaldepth))
            self.gcode.append("(Start point: %s)" % sp)

        depth = 0
        for i in range(passes):
            depth += passdepth
            if depth > totaldepth: depth = totaldepth
            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, depth))

            self.gcode.append(
                ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                safez)
            for p in points:
                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG0)) % (p[0], p[1]))
                self.gcode.append(
                    ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) %
                    (sz - depth))
                self.gcode.append(
                    ("G1 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(addspeed, feedxyG1)) % (p[2], p[3]))
                self.gcode.append(
                    ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                    (safez))

        self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                           self.speedTerm(addspeed, feedxyG0)) % (sx, sy))
        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)
        self.gcl.updateList(self.gcode)
        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)
Пример #11
0
class AddToMergeDialog(wx.Dialog):
    def __init__(self, parent, title=DEFAULT_TITLE):
        wx.Dialog.__init__(self, parent, wx.ID_ANY, title)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        
        self.modified = False
        self.title = title
        self.parent = parent
        self.settings = self.parent.settings
        self.images = self.parent.images
        
        self.gCode = []
        
        hsizer=wx.BoxSizer(wx.HORIZONTAL)
        hsizer.AddSpacer(10)
        
        vsizer = wx.BoxSizer(wx.VERTICAL)
        vsizer.AddSpacer(10)
        
        self.gcl = GCodeList(self)
        vsizer.Add(self.gcl)
        
        vsizer.AddSpacer(20)
        
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.bAdd = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFileopen, size=BTNDIM)
        self.bAdd.SetToolTip("Choose a file to add")
        btnSizer.Add(self.bAdd)
        self.Bind(wx.EVT_BUTTON, self.bAddPressed, self.bAdd)
        
        btnSizer.AddSpacer(10)

        self.bEdit = wx.BitmapButton(self, wx.ID_ANY, self.images.pngEdit, size=BTNDIM)
        self.bEdit.SetToolTip("Modify file before merging")
        btnSizer.Add(self.bEdit)
        self.Bind(wx.EVT_BUTTON, self.bEditPressed, self.bEdit)
        self.bEdit.Enable(False)
        
        btnSizer.AddSpacer(10)

        self.bView = wx.BitmapButton(self, wx.ID_ANY, self.images.pngView, size=BTNDIM)
        self.bView.SetToolTip("Examine file and applied edits before merge")
        btnSizer.Add(self.bView)
        self.Bind(wx.EVT_BUTTON, self.bViewPressed, self.bView)
        self.bView.Enable(False)
        
        btnSizer.AddSpacer(10)

        self.bOK = wx.BitmapButton(self, wx.ID_ANY, self.images.pngMerge, size=BTNDIM)
        self.bOK.SetToolTip("Commit this file to the merge")
        btnSizer.Add(self.bOK)
        self.Bind(wx.EVT_BUTTON, self.bOKPressed, self.bOK)
        self.bOK.Enable(False)
        
        btnSizer.AddSpacer(20)

        self.bCancel = wx.BitmapButton(self, wx.ID_ANY, self.images.pngCancel, size=BTNDIM)
        self.bCancel.SetToolTip("Cancel without adding this file to the merge")
        btnSizer.Add(self.bCancel)
        self.Bind(wx.EVT_BUTTON, self.bCancelPressed, self.bCancel)
        
        vsizer.Add(btnSizer, 1, wx.ALIGN_CENTER_HORIZONTAL)
 
        vsizer.AddSpacer(20)
        hsizer.Add(vsizer)       
        hsizer.AddSpacer(10)
        self.SetSizer(hsizer)
        self.Layout()
        self.Fit();
        
    def setTitle(self):
        self.SetTitle(self.title)
        
    def setModified(self, flag=True):
        self.modified = flag
        self.setTitle()
       
    def bOKPressed(self, _):
        self.EndModal(wx.ID_OK)
        
    def bCancelPressed(self, _):
        self.doCancel()
        
    def onClose(self, _):
        self.doCancel()
        
    def doCancel(self):
        if self.modified:
            dlg = wx.MessageDialog(self, 'File will not be added to merge',
                               'Proceed?',
                               wx.YES_NO | wx.ICON_WARNING)
            rc = dlg.ShowModal()
            dlg.Destroy()
            if rc == wx.ID_NO:
                return 
            
        self.EndModal(wx.ID_CANCEL)
        
    def bAddPressed(self, _):
        if self.modified:
            dlg = wx.MessageDialog(self, "File \"%s\" has not been added to merge" % self.title,
                'Proceed?',
                wx.YES_NO | wx.ICON_WARNING)
            rc = dlg.ShowModal()
            dlg.Destroy()
            if rc == wx.ID_NO:
                return 
            
        dlg = wx.FileDialog(
            self, message="Choose a file",
            defaultDir=self.settings.lastloaddir,
            defaultFile="",
            wildcard=wildcard,
            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_PREVIEW)
        if dlg.ShowModal() != wx.ID_OK:
            dlg.Destroy()
            return 

        path = dlg.GetPath()
        dlg.Destroy()
        
        pdir, self.title = os.path.split(path)

        if pdir != self.settings.lastloaddir:
            self.settings.lastloaddir = pdir
            self.settings.setModified()
        
        with open(path, "r") as fp:
            self.gCode = fp.readlines()
            
        self.gcl.updateList(self.gCode)
            
        self.setModified()
        self.bView.Enable()
        self.bEdit.Enable()
        self.bOK.Enable()
        
    def bEditPressed(self, _):
        dlg = editModel(self)
        rc = dlg.ShowModal()
        if rc != wx.ID_OK:
            dlg.Destroy()
            return 
        
        dx, dy, mx, my = dlg.getEditValues()
        dlg.Destroy()
        
        if mx:
            mir = gMirror()
            self.gCode = [mir.mirrorX(x) for x in self.gCode]
            self.gcl.updateList(self.gCode)
        elif my:
            mir = gMirror()
            self.gCode = [mir.mirrorY(x) for x in self.gCode]
            self.gcl.updateList(self.gCode)
        else:
            shft = gShifter(dx, dy)
            self.gCode = [shft.shift(x) for x in self.gCode]
            self.gcl.updateList(self.gCode)
            
        self.setModified()
       
    def getGCode(self):
        return self.gCode
        
    def bViewPressed(self, _):
        self.gcl.visualize(title=self.title)
Пример #12
0
class SlotPanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "contour:slot")
        self.toolInfo = toolInfo

        self.modified = False
        self.unsaved = False
        self.viewTitle = "Rounded Slot %d" % SlotPanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        SlotPanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        self.setTitleFlag()

        t = wx.StaticText(self, wx.ID_ANY, "Length")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teLength = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teLength, "length")
        sizer.Add(self.teLength, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Width")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teWidth = wx.TextCtrl(self, wx.ID_ANY, "10", style=wx.TE_RIGHT)
        self.addWidget(self.teWidth, "width")
        sizer.Add(self.teWidth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Rotation Angle")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teAngle = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teAngle, "angle")
        sizer.Add(self.teAngle, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Starting Point")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getStartingPoints(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Tool Movement")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getToolMovement(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Cutting Direction")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getCuttingDirection(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        self.cbPocket = wx.CheckBox(self, wx.ID_ANY, "Pocket")
        self.addWidget(self.cbPocket, "pocket")
        sizer.Add(self.cbPocket,
                  pos=(ln, 0),
                  span=(1, 2),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onChange, self.cbPocket)

        t = wx.StaticText(self, wx.ID_ANY, "Stepover")
        so = "%6.3f" % speedInfo["stepover"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStepOver = wx.TextCtrl(self, wx.ID_ANY, so, style=wx.TE_RIGHT)
        self.addWidget(self.teStepOver, "stepover")
        sizer.Add(self.teStepOver,
                  pos=(ln, 3),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getStartingPoints(self):
        labels = [
            "Lower Left", "Upper Left", "Lower Right", "Upper Right", "Center"
        ]
        self.rbStartPoints = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbStartPoints.append(r)
        return sz

    def getToolMovement(self):
        labels = ["On Perimeter", "Outside", "Inside"]
        self.rbToolMove = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbToolMove.append(r)
        return sz

    def getCuttingDirection(self):
        labels = ["Clockwise", "Counter Clockwise"]
        self.rbCutDir = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbCutDir.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []

        errs = []
        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")
        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            self.safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        self.addspeed = self.cbAddSpeed.IsChecked()
        try:
            self.feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            self.feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            self.feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            self.feedxyG1 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            length = float(self.teLength.GetValue())
        except:
            errs.append("Length")
        try:
            width = float(self.teWidth.GetValue())
        except:
            errs.append("Width")
        try:
            self.depth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            self.passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")
        try:
            stepover = float(self.teStepOver.GetValue())
        except:
            errs.append("Stepover")
        try:
            angle = float(self.teAngle.GetValue())
        except:
            errs.append("Angle")

        if not ValidateNoEntryErrors(self, errs):
            return

        if not ValidateToolSize(self, tdiam, length, "Length"):
            return
        if not ValidateToolSize(self, tdiam, width, "Width"):
            return

        if not ValidateRange(self, stepover, 0.001, 1.0, "Stepover",
                             "0 < x <= 1.0"):
            return

        if not ValidateMinLength(self, length, width, "Length", "Width"):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, self.safez)

        self.tDiam = tdiam
        if self.settings.annotate:
            self.gcode.append(
                "(Rounded slot start (%6.2f,%6.2f) length %6.2f width %6.2f depth from %6.2f to %6.2f)"
                % (sx, sy, width, length, sz, self.depth))

        length -= width

        points = [[sx, sy], [sx, sy + width], [sx + length, sy + width],
                  [sx + length, sy]]
        centers = [[sx, sy + width / 2], [sx + length, sy + width / 2]]

        sp = self.getChosen(self.rbStartPoints)
        adjx = 0
        adjy = 0
        if sp == "Upper Left":
            adjy = -width
        elif sp == "Upper Right":
            adjy = -width
            adjx = -length
        elif sp == "Lower Right":
            adjx = -length
        elif sp == "Center":
            adjx = -length / 2
            adjy = -width / 2

        for p in points:
            p[0] += adjx
            p[1] += adjy
        for c in centers:
            c[0] += adjx
            c[1] += adjy

        tm = self.getChosen(self.rbToolMove)
        rad = float(tdiam) / 2.0
        if tm == "Inside":
            points[0][1] += rad
            points[1][1] -= rad
            points[2][1] -= rad
            points[3][1] += rad

        elif tm == "Outside":
            points[0][1] -= rad
            points[1][1] += rad
            points[2][1] += rad
            points[3][1] -= rad

        np = []
        nc = []
        cosv = math.cos(math.radians(angle))
        sinv = math.sin(math.radians(angle))
        for p in points:
            np.append([p[0] * cosv - p[1] * sinv, p[0] * sinv + p[1] * cosv])
        for c in centers:
            nc.append([c[0] * cosv - c[1] * sinv, c[0] * sinv + c[1] * cosv])

        cd = self.getChosen(self.rbCutDir)
        clockwise = True
        if cd != "Clockwise":
            clockwise = False

        pkt = self.cbPocket.IsChecked()

        if self.settings.annotate:
            self.gcode.append("(Start point: %s)" % sp)
            self.gcode.append("(Cutting direction: %s)" % cd)
            self.gcode.append("(Tool movement: %s)" % tm)
            self.gcode.append("(Pocket: %s)" % pkt)

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(self.addspeed, self.feedzG0)) %
            (self.safez))

        passes = int(math.ceil(self.depth / self.passdepth))

        cz = sz
        for i in range(passes):
            cz -= self.passdepth
            if cz < -self.depth:
                cz = -self.depth
            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, cz))

            if pkt:
                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(self.addspeed, self.feedxyG0)) %
                    (nc[1][0], nc[1][1]))
                self.gcode.append(
                    ("G1 Z" + self.fmt +
                     self.speedTerm(self.addspeed, self.feedzG1)) % (cz))
                self.gcode.append(
                    ("G1 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(self.addspeed, self.feedxyG1)) %
                    (nc[0][0], nc[0][1]))

                d = centers[0][1] - points[0][1]
                cd = stepover * tdiam
                while cd < d:
                    pc = [p for p in centers]
                    pp = [[pc[0][0], pc[0][1] - cd], [pc[0][0], pc[0][1] + cd],
                          [pc[1][0], pc[1][1] + cd], [pc[1][0], pc[1][1] - cd]]
                    npp = []
                    npc = []
                    for p in pp:
                        npp.append([
                            p[0] * cosv - p[1] * sinv,
                            p[0] * sinv + p[1] * cosv
                        ])
                    for c in pc:
                        npc.append([
                            c[0] * cosv - c[1] * sinv,
                            c[0] * sinv + c[1] * cosv
                        ])
                    self.gcode.append(
                        ("G1 X" + self.fmt + " Y" + self.fmt +
                         self.speedTerm(self.addspeed, self.feedxyG1)) %
                        (npp[0][0], npp[0][1]))
                    self.loop(npp, npc, clockwise)
                    cd += stepover * tdiam

                self.gcode.append(
                    ("G1 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(self.addspeed, self.feedxyG1)) %
                    (np[0][0], np[0][1]))
            else:
                self.gcode.append(
                    ("G0 X" + self.fmt + " Y" + self.fmt +
                     self.speedTerm(self.addspeed, self.feedxyG0)) %
                    (np[0][0], np[0][1]))
                self.gcode.append(
                    ("G1 Z" + self.fmt +
                     self.speedTerm(self.addspeed, self.feedzG1)) % (cz))

            self.loop(np, nc, clockwise)

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(self.addspeed, self.feedzG0)) %
            (self.safez))
        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)

        self.gcl.updateList(self.gcode)
        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)

    def loop(self, points, centers, clockwise):
        cmd = "G3"
        if clockwise:
            cmd = "G2"

        if clockwise:
            self.gcode.append(
                (cmd + " I" + self.fmt + " J" + self.fmt + " X" + self.fmt +
                 " Y" + self.fmt +
                 self.speedTerm(self.addspeed, self.feedxyG1)) %
                (centers[0][0] - points[0][0], centers[0][1] - points[0][1],
                 points[1][0], points[1][1]))
            self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(self.addspeed, self.feedxyG1)) %
                              (points[2][0], points[2][1]))
            self.gcode.append(
                (cmd + " I" + self.fmt + " J" + self.fmt + " X" + self.fmt +
                 " Y" + self.fmt +
                 self.speedTerm(self.addspeed, self.feedxyG1)) %
                (centers[1][0] - points[2][0], centers[1][1] - points[2][1],
                 points[3][0], points[3][1]))
            self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(self.addspeed, self.feedxyG1)) %
                              (points[0][0], points[0][1]))
        else:
            self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(self.addspeed, self.feedxyG1)) %
                              (points[3][0], points[3][1]))
            self.gcode.append(
                (cmd + " I" + self.fmt + " J" + self.fmt + " X" + self.fmt +
                 " Y" + self.fmt +
                 self.speedTerm(self.addspeed, self.feedxyG1)) %
                (centers[1][0] - points[3][0], centers[1][1] - points[3][1],
                 points[2][0], points[2][1]))
            self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(self.addspeed, self.feedxyG1)) %
                              (points[1][0], points[1][1]))
            self.gcode.append(
                (cmd + " I" + self.fmt + " J" + self.fmt + " X" + self.fmt +
                 " Y" + self.fmt +
                 self.speedTerm(self.addspeed, self.feedxyG1)) %
                (centers[0][0] - points[1][0], centers[0][1] - points[1][1],
                 points[0][0], points[0][1]))
Пример #13
0
class LinePanel(wx.Panel, CNCObject):
    seqNo = 1

    def __init__(self, toolInfo, speedInfo, parent):
        CNCObject.__init__(self, parent, "contour:line")
        self.toolInfo = toolInfo
        self.modified = False
        self.unsaved = False
        self.viewTitle = "Line %d" % LinePanel.seqNo
        self.titleText = "G Code Generator: %s" % self.viewTitle
        self.setTitleFlag()
        LinePanel.seqNo += 1

        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        sizer = wx.GridBagSizer(wx.HORIZONTAL)
        sizer.Add(10, 10, wx.GBPosition(0, 4))
        ln = 1

        t = wx.StaticText(self, wx.ID_ANY, "Start X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartX = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartX, "startx")
        sizer.Add(self.teStartX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Start Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartY = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartY, "starty")
        sizer.Add(self.teStartY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "End X")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teEndX = wx.TextCtrl(self, wx.ID_ANY, "100", style=wx.TE_RIGHT)
        self.addWidget(self.teEndX, "endx")
        sizer.Add(self.teEndX, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "End Y")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teEndY = wx.TextCtrl(self, wx.ID_ANY, "100", style=wx.TE_RIGHT)
        self.addWidget(self.teEndY, "endy")
        sizer.Add(self.teEndY, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Start Z")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teStartZ = wx.TextCtrl(self, wx.ID_ANY, "0", style=wx.TE_RIGHT)
        self.addWidget(self.teStartZ, "startz")
        sizer.Add(self.teStartZ, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Safe Z above surface")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teSafeZ = wx.TextCtrl(self, wx.ID_ANY, "0.5", style=wx.TE_RIGHT)
        self.addWidget(self.teSafeZ, "safez")
        sizer.Add(self.teSafeZ, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Total Depth")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teTotalDepth = wx.TextCtrl(self,
                                        wx.ID_ANY,
                                        "1",
                                        style=wx.TE_RIGHT)
        self.addWidget(self.teTotalDepth, "depth")
        sizer.Add(self.teTotalDepth, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Depth/Pass")
        dpp = "%6.3f" % speedInfo["depthperpass"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.tePassDepth = wx.TextCtrl(self, wx.ID_ANY, dpp, style=wx.TE_RIGHT)
        self.addWidget(self.tePassDepth, "passdepth")
        sizer.Add(self.tePassDepth, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        self.cbAddSpeed = wx.CheckBox(self, wx.ID_ANY, "Add Speed Parameter")
        self.addWidget(self.cbAddSpeed, "addspeed")
        sizer.Add(self.cbAddSpeed,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        self.Bind(wx.EVT_CHECKBOX, self.onCbAddSpeed, self.cbAddSpeed)
        self.cbAddSpeed.SetValue(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G0)")
        g0xy = "%7.2f" % speedInfo["G0XY"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG0 = wx.TextCtrl(self, wx.ID_ANY, g0xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG0, "feedXYG0")
        sizer.Add(self.teFeedXYG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate XY (G1)")
        g1xy = "%7.2f" % speedInfo["G1XY"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedXYG1 = wx.TextCtrl(self, wx.ID_ANY, g1xy, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedXYG1, "feedXYG1")
        sizer.Add(self.teFeedXYG1, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G0)")
        g0z = "%7.2f" % speedInfo["G0Z"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG0 = wx.TextCtrl(self, wx.ID_ANY, g0z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG0, "feedZG0")
        sizer.Add(self.teFeedZG0, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Feed Rate Z (G1)")
        g1z = "%7.2f" % speedInfo["G1Z"]
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teFeedZG1 = wx.TextCtrl(self, wx.ID_ANY, g1z, style=wx.TE_RIGHT)
        self.addWidget(self.teFeedZG1, "feedZG1")
        sizer.Add(self.teFeedZG1, pos=(ln, 3), flag=wx.LEFT, border=10)

        self.teFeedXYG0.Enable(self.settings.addspeed)
        self.teFeedXYG1.Enable(self.settings.addspeed)
        self.teFeedZG0.Enable(self.settings.addspeed)
        self.teFeedZG1.Enable(self.settings.addspeed)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Tool Diameter")
        td = "%6.3f" % toolInfo["diameter"]
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teToolDiam = wx.TextCtrl(self, wx.ID_ANY, td, style=wx.TE_RIGHT)
        self.addWidget(self.teToolDiam, "tooldiameter")
        sizer.Add(self.teToolDiam, pos=(ln, 1), flag=wx.LEFT, border=10)

        t = wx.StaticText(self, wx.ID_ANY, "Decimal Places")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        self.teDecimals = wx.TextCtrl(self, wx.ID_ANY, "4", style=wx.TE_RIGHT)
        self.addWidget(self.teDecimals, "decimals")
        sizer.Add(self.teDecimals, pos=(ln, 3), flag=wx.LEFT, border=10)
        ln += 1

        t = wx.StaticText(self, wx.ID_ANY, "Tool Movement")
        sizer.Add(t,
                  pos=(ln, 0),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getToolMovement(),
                  pos=(ln, 1),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)

        t = wx.StaticText(self, wx.ID_ANY, "Measurement System")
        sizer.Add(t,
                  pos=(ln, 2),
                  flag=wx.LEFT + wx.ALIGN_CENTER_VERTICAL,
                  border=20)
        sizer.Add(self.getMeasurementSystem(),
                  pos=(ln, 3),
                  border=5,
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_VERTICAL)
        ln += 1

        sizer.Add(20, 20, wx.GBPosition(ln, 0))
        ln += 1

        bsz = self.buttons()

        sizer.Add(bsz,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.TOP + wx.BOTTOM + wx.ALIGN_CENTER_HORIZONTAL,
                  border=5)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))
        ln += 1

        self.gcl = GCodeList(self)
        sizer.Add(self.gcl,
                  pos=(ln, 0),
                  span=(1, 4),
                  flag=wx.LEFT + wx.EXPAND,
                  border=10)
        ln += 1

        sizer.Add(10, 10, wx.GBPosition(ln, 0))

        self.Bind(wx.EVT_TEXT, self.onChange)
        self.Bind(wx.EVT_RADIOBUTTON, self.onChange)

        self.SetSizer(sizer)
        self.Layout()
        self.Fit()

    def getToolMovement(self):
        labels = [
            "Centered", "Left of forward motion", "Right of forward motion"
        ]
        self.rbToolMove = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbToolMove.append(r)
        return sz

    def getMeasurementSystem(self):
        labels = ["Metric", "Imperial"]
        self.rbMeas = []
        sz = wx.BoxSizer(wx.VERTICAL)
        for i in range(len(labels)):
            if i == 0:
                style = wx.RB_GROUP
            else:
                style = 0
            r = wx.RadioButton(self, wx.ID_ANY, labels[i], style=style)
            self.addWidget(r, labels[i])
            sz.Add(r)
            self.rbMeas.append(r)
        if self.settings.metric:
            self.setChosen(self.rbMeas, "Metric")
        else:
            self.setChosen(self.rbMeas, "Imperial")
        return sz

    def onCbAddSpeed(self, _):
        self.setState(True, False)
        flag = self.cbAddSpeed.IsChecked()
        self.teFeedXYG0.Enable(flag)
        self.teFeedXYG1.Enable(flag)
        self.teFeedZG0.Enable(flag)
        self.teFeedZG1.Enable(flag)

    def bGeneratePressed(self, _):
        self.bSave.Enable(False)
        self.bVisualize.Enable(False)
        self.gcl.clear()
        self.gcode = []
        errs = []

        try:
            dec = int(self.teDecimals.GetValue())
            self.fmt = "%0." + str(dec) + "f"
        except:
            errs.append("Decimal Places")

        try:
            sx = float(self.teStartX.GetValue())
        except:
            errs.append("Start X")
        try:
            sy = float(self.teStartY.GetValue())
        except:
            errs.append("Start Y")
        try:
            ex = float(self.teEndX.GetValue())
        except:
            errs.append("End X")
        try:
            ey = float(self.teEndY.GetValue())
        except:
            errs.append("End Y")
        try:
            sz = float(self.teStartZ.GetValue())
        except:
            errs.append("Start Z")
        try:
            safez = float(self.teSafeZ.GetValue())
        except:
            errs.append("Safe Z")

        addspeed = self.cbAddSpeed.IsChecked()
        try:
            feedzG0 = float(self.teFeedZG0.GetValue())
        except:
            errs.append("Z G0 Speed")
        try:
            feedzG1 = float(self.teFeedZG1.GetValue())
        except:
            errs.append("Z G1 Speed")
        try:
            feedxyG0 = float(self.teFeedXYG0.GetValue())
        except:
            errs.append("XY G0 Speed")
        try:
            feedxyG1 = float(self.teFeedXYG1.GetValue())
        except:
            errs.append("XY G1 Speed")
        try:
            depth = float(self.teTotalDepth.GetValue())
        except:
            errs.append("Depth")
        try:
            passdepth = float(self.tePassDepth.GetValue())
        except:
            errs.append("Depth per Pass")
        try:
            tdiam = float(self.teToolDiam.GetValue())
        except:
            errs.append("Tool Diameter")

        if not ValidateNoEntryErrors(self, errs):
            return

        self.gcode = self.preamble(self.getChosen(self.rbMeas), tdiam,
                                   self.toolInfo, safez)
        self.tDiam = tdiam

        rise = float(ey) - float(sy)
        run = float(ex) - float(sx)

        sign = 1
        if run < 0:
            sign = -1

        if run == 0:
            trise = 0
            if rise > 0:
                trun = -tdiam / 2
            else:
                trun = tdiam / 2
        else:
            angler = math.atan(rise / run)
            trise = sign * math.cos(angler) * tdiam / 2
            trun = sign * (-(math.sin(angler) * tdiam / 2))

        tm = self.getChosen(self.rbToolMove)

        if tm == "Left of forward motion":
            sx += trun
            ex += trun
            sy += trise
            ey += trise
        elif tm == "Right of forward motion":
            sx -= trun
            ex -= trun
            sy -= trise
            ey -= trise

        if self.settings.annotate:
            self.gcode.append("(Tool movement: %s)" % tm)

        self.gcode.append(
            ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) % (safez))

        passes = int(math.ceil(depth / passdepth))
        if self.settings.annotate:
            self.gcode.append(
                "(Line (%6.2f,%6.2f) to (%6.2f,%6.2f) depth from %6.2f to %6.2f)"
                % (sx, sy, ex, ey, sz, depth))

        cz = sz
        for i in range(passes):

            cz -= passdepth
            if cz < -depth:
                cz = -depth

            if self.settings.annotate:
                self.gcode.append("(Pass number %d at depth %f)" % (i, cz))

            self.gcode.append(("G0 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(addspeed, feedxyG0)) % (sx, sy))
            self.gcode.append(
                ("G1 Z" + self.fmt + self.speedTerm(addspeed, feedzG1)) % (cz))
            self.gcode.append(("G1 X" + self.fmt + " Y" + self.fmt +
                               self.speedTerm(addspeed, feedxyG1)) % (ex, ey))
            self.gcode.append(
                ("G0 Z" + self.fmt + self.speedTerm(addspeed, feedzG0)) %
                (safez))

        if self.settings.annotate:
            self.gcode.append("(End object %s)" % self.viewTitle)
        self.gcl.updateList(self.gcode)

        self.bSave.Enable()
        self.bVisualize.Enable()
        self.setState(False, True)