def tooltableFromAttrs(self, stringattrs): if stringattrs.get('Version') and 1 == int(stringattrs['Version']): tt = Path.Tooltable() tt.Version = 1 tt.Name = self.getNextToolTableName() if stringattrs.get('Version'): tt.Version = stringattrs.get('Version') if stringattrs.get('TableName'): tt.Name = stringattrs.get('TableName') if any(table.Name == tt.Name for table in self.toolTables): tt.Name = self.getNextToolTableName(tt.Name) for key, attrs in PathUtil.keyValueIter(stringattrs['Tools']): tool = Path.Tool() tool.Name = str(attrs["name"]) tool.ToolType = str(attrs["tooltype"]) tool.Material = str(attrs["material"]) tool.Diameter = float(attrs["diameter"]) tool.LengthOffset = float(attrs["lengthOffset"]) tool.FlatRadius = float(attrs["flatRadius"]) tool.CornerRadius = float(attrs["cornerRadius"]) tool.CuttingEdgeAngle = float(attrs["cuttingEdgeAngle"]) tool.CuttingEdgeHeight = float(attrs["cuttingEdgeHeight"]) tt.setTool(int(key), tool) return tt else: PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable template version %s") % stringattrs.get('Version')) return None
def getTools(self, tablename): '''returns the tool data for a given table''' tooldata = [] tableExists = any(table.Name == tablename for table in self.toolTables) if tableExists: self.currentTableName = tablename else: return None tt = self.getTableFromName(tablename) headers = ["","Tool Num.","Name","Tool Type","Diameter"] model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(headers) def unitconv(ivalue): val = FreeCAD.Units.Quantity(ivalue, FreeCAD.Units.Length) displayed_val = val.UserString #just the displayed value-not the internal one return displayed_val if tt: if len(tt.Tools) == 0: tooldata.append([]) for number, t in PathUtil.keyValueIter(tt.Tools): itemcheck = QtGui.QStandardItem() itemcheck.setCheckable(True) itemNumber = QtGui.QStandardItem(str(number)) itemName = QtGui.QStandardItem(t.Name) itemToolType = QtGui.QStandardItem(t.ToolType) itemDiameter = QtGui.QStandardItem(unitconv(t.Diameter)) row = [itemcheck, itemNumber, itemName, itemToolType, itemDiameter] model.appendRow(row) return model
def getTools(self, tablename): '''returns the tool data for a given table''' tooldata = [] tt = self._findList(tablename) headers = ["","Tool Num.","Name","Tool Type","Material","Diameter","Length Offset","Flat Radius","Corner Radius","Cutting Edge Angle","Cutting Edge Height"] model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(headers) def unitconv(ivalue): val = FreeCAD.Units.Quantity(ivalue, FreeCAD.Units.Length) displayed_val = val.UserString #just the displayed value-not the internal one return displayed_val if tt: if len(tt.Tools) == 0: tooldata.append([]) for number, t in PathUtil.keyValueIter(tt.Tools): itemcheck = QtGui.QStandardItem() itemcheck.setCheckable(True) itemNumber = QtGui.QStandardItem(str(number)) itemName = QtGui.QStandardItem(t.Name) itemToolType = QtGui.QStandardItem(t.ToolType) itemMaterial = QtGui.QStandardItem(t.Material) itemDiameter = QtGui.QStandardItem(unitconv(t.Diameter)) itemLengthOffset = QtGui.QStandardItem(unitconv(t.LengthOffset)) itemFlatRadius = QtGui.QStandardItem(unitconv(t.FlatRadius)) itmCornerRadius = QtGui.QStandardItem(unitconv(t.CornerRadius)) itemCuttingEdgeAngle = QtGui.QStandardItem(str(t.CuttingEdgeAngle)) itemCuttingEdgeHeight = QtGui.QStandardItem(unitconv(t.CuttingEdgeHeight)) row = [itemcheck, itemNumber, itemName, itemToolType, itemMaterial, itemDiameter, itemLengthOffset, itemFlatRadius, itmCornerRadius, itemCuttingEdgeAngle, itemCuttingEdgeHeight] model.appendRow(row) return model
def operationsWithSettings(self): """operationsWithSettings() ... returns a list of operations which currently have some settings defined.""" ops = [] for name, value in PathUtil.keyValueIter(_RegisteredOps): for prop in value.registeredPropertyNames(name): if hasattr(self.obj, prop): ops.append(name) break return list(sorted(ops))
def tooltableFromAttrs(self, stringattrs): if stringattrs.get('Version') and 1 == int(stringattrs['Version']): attrs = {} for key, val in PathUtil.keyValueIter(stringattrs['Tools']): attrs[int(key)] = val return Path.Tooltable(attrs) else: PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable template version %s") % stringattrs.get('Version')) return None
def operationsWithSettings(self): '''operationsWithSettings() ... returns a list of operations which currently have some settings defined.''' ops = [] for name,value in PathUtil.keyValueIter(_RegisteredOps): for prop in value.registeredPropertyNames(name): if hasattr(self.obj, prop): ops.append(name) break return list(sorted(ops))
def Attach(vobj, name): '''Attach(vobj, name) ... attach the appropriate view provider to the view object. If no view provider was registered for the given name a default IconViewProvider is created.''' PathLog.track(vobj.Object.Label, name) global _factory for key,value in PathUtil.keyValueIter(_factory): if key == name: return value(vobj, name) PathLog.track(vobj.Object.Label, name, 'PathIconViewProvider') return ViewProvider(vobj, name)
def Attach(vobj, name): """Attach(vobj, name) ... attach the appropriate view provider to the view object. If no view provider was registered for the given name a default IconViewProvider is created.""" PathLog.track(vobj.Object.Label, name) global _factory # pylint: disable=global-statement for key, value in PathUtil.keyValueIter(_factory): if key == name: return value(vobj, name) PathLog.track(vobj.Object.Label, name, "PathIconViewProvider") return ViewProvider(vobj, name)
def tooltableFromAttrs(self, stringattrs): if stringattrs.get('Version') and 1 == int(stringattrs['Version']): attrs = {} for key, val in PathUtil.keyValueIter(stringattrs['Tools']): attrs[int(key)] = val return Path.Tooltable(attrs) else: PathLog.error( translate('PathToolLibraryManager', "Unsupported Path tooltable template version %s") % stringattrs.get('Version')) return None
def __init__(self, obj, form): self.form = form self.obj = obj self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key = lambda op: op.name) if form: parent = form.tabOpDefaults for op in self.ops: form.opDefaultOp.addItem(op.form.windowTitle(), op) op.form.setParent(parent) parent.layout().addWidget(op.form) op.form.hide() self.currentOp = None
def _traverseTemplateAttributes(attrs, codec): coded = {} for key,value in PathUtil.keyValueIter(attrs): if type(value) == dict: PathLog.debug("%s is a dict" % key) coded[key] = _traverseTemplateAttributes(value, codec) elif type(value) == list: PathLog.debug("%s is a list" % key) coded[key] = [_traverseTemplateAttributes(attr, codec) for attr in value] elif PathUtil.isString(value): PathLog.debug("%s is a string" % key) coded[key] = codec(value) else: PathLog.debug("%s is %s" % (key, type(value))) coded[key] = value return coded
def _traverseTemplateAttributes(attrs, codec): coded = {} for key, value in PathUtil.keyValueIter(attrs): if type(value) == dict: PathLog.debug("%s is a dict" % key) coded[key] = _traverseTemplateAttributes(value, codec) elif type(value) == list: PathLog.debug("%s is a list" % key) coded[key] = [_traverseTemplateAttributes(attr, codec) for attr in value] elif PathUtil.isString(value): PathLog.debug("%s is a string" % key) coded[key] = codec(value) else: PathLog.debug("%s is %s" % (key, type(value))) coded[key] = value return coded
def getTools(self, tablename): '''returns the tool data for a given table''' tooldata = [] tt = self._findList(tablename) headers = [ "", "Tool Num.", "Name", "Tool Type", "Material", "Diameter", "Length Offset", "Flat Radius", "Corner Radius", "Cutting Edge Angle", "Cutting Edge Height" ] model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(headers) def unitconv(ivalue): val = FreeCAD.Units.Quantity(ivalue, FreeCAD.Units.Length) displayed_val = val.UserString #just the displayed value-not the internal one return displayed_val if tt: if len(tt.Tools) == 0: tooldata.append([]) for number, t in PathUtil.keyValueIter(tt.Tools): itemcheck = QtGui.QStandardItem() itemcheck.setCheckable(True) itemNumber = QtGui.QStandardItem(str(number)) itemName = QtGui.QStandardItem(t.Name) itemToolType = QtGui.QStandardItem(t.ToolType) itemMaterial = QtGui.QStandardItem(t.Material) itemDiameter = QtGui.QStandardItem(unitconv(t.Diameter)) itemLengthOffset = QtGui.QStandardItem(unitconv( t.LengthOffset)) itemFlatRadius = QtGui.QStandardItem(unitconv(t.FlatRadius)) itmCornerRadius = QtGui.QStandardItem(unitconv(t.CornerRadius)) itemCuttingEdgeAngle = QtGui.QStandardItem( str(t.CuttingEdgeAngle)) itemCuttingEdgeHeight = QtGui.QStandardItem( unitconv(t.CuttingEdgeHeight)) row = [ itemcheck, itemNumber, itemName, itemToolType, itemMaterial, itemDiameter, itemLengthOffset, itemFlatRadius, itmCornerRadius, itemCuttingEdgeAngle, itemCuttingEdgeHeight ] model.appendRow(row) return model
def setFromTemplate(self, attrs): '''setFromTemplate(attrs) ... sets the default values from the given dictionary.''' for name in Template.All: if attrs.get(name) is not None: setattr(self.obj, name, attrs[name]) for opName,op in PathUtil.keyValueIter(_RegisteredOps): opSetting = attrs.get(opName) if opSetting is not None: prototype = op.prototype(opName) for propName in op.properties(): value = opSetting.get(propName) if not value is None: prop = prototype.getProperty(propName) propertyName = OpPropertyName(opName, propName) propertyGroup = OpPropertyGroup(opName) prop.setupProperty(self.obj, propertyName, propertyGroup, prop.valueFromString(value))
def __baseObjectData(self, obj): data = {"baseimage": "", "bases": ""} try: bases = {} for name, count in PathUtil.keyValueIter( Counter([obj.Proxy.baseObject(obj, o).Label for o in obj.Model.Group]) ): bases[name] = str(count) data["baseimage"] = self.__makePicture(obj.Model, "baseimage") data["bases"] = bases except Exception as e: data["errors"] = e self.squawk("PathSanity(__baseObjectData)", e, squawkType="CAUTION") return data
def setFromTemplate(self, attrs): '''setFromTemplate(attrs) ... sets the default values from the given dictionary.''' for name in Template.All: if attrs.get(name) is not None: setattr(self.obj, name, attrs[name]) for opName, op in PathUtil.keyValueIter(_RegisteredOps): opSetting = attrs.get(opName) if opSetting is not None: prototype = op.prototype(opName) for propName in op.properties(): value = opSetting.get(propName) if value is not None: prop = prototype.getProperty(propName) propertyName = OpPropertyName(opName, propName) propertyGroup = OpPropertyGroup(opName) prop.setupProperty(self.obj, propertyName, propertyGroup, prop.valueFromString(value))
def updateBoneList(self): itemList = [] for loc, (enabled, inaccessible, ids) in PathUtil.keyValueIter(self.obj.Proxy.boneStateList(self.obj)): lbl = '(%.2f, %.2f): %s' % (loc[0], loc[1], ','.join(str(id) for id in ids)) item = QtGui.QListWidgetItem(lbl) if enabled: item.setCheckState(QtCore.Qt.CheckState.Checked) else: item.setCheckState(QtCore.Qt.CheckState.Unchecked) flags = QtCore.Qt.ItemFlag.ItemIsSelectable if not inaccessible: flags |= QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable item.setFlags(flags) item.setData(self.DataIds, ids) item.setData(self.DataKey, ids[0]) itemList.append(item) self.form.bones.clear() for item in sorted(itemList, key=lambda item: item.data(self.DataKey)): self.form.bones.addItem(item)
def generateTags(self, obj, count, width=None, height=None, angle=None, radius=None, spacing=None): PathLog.track(count, width, height, angle, spacing) # for e in self.baseWire.Edges: # debugMarker(e.Vertexes[0].Point, 'base', (0.0, 1.0, 1.0), 0.2) if spacing: tagDistance = spacing else: tagDistance = self.baseWire.Length / (count if count else 4) W = width if width else self.defaultTagWidth() H = height if height else self.defaultTagHeight() A = angle if angle else self.defaultTagAngle() R = radius if radius else self.defaultTagRadius() # start assigning tags on the longest segment (shortestEdge, longestEdge) = self.shortestAndLongestPathEdge() startIndex = 0 for i in range(0, len(self.baseWire.Edges)): edge = self.baseWire.Edges[i] PathLog.debug(' %d: %.2f' % (i, edge.Length)) if PathGeom.isRoughly(edge.Length, longestEdge.Length): startIndex = i break startEdge = self.baseWire.Edges[startIndex] startCount = int(startEdge.Length / tagDistance) if (longestEdge.Length - shortestEdge.Length) > shortestEdge.Length: startCount = int(startEdge.Length / tagDistance) + 1 lastTagLength = (startEdge.Length + (startCount - 1) * tagDistance) / 2 currentLength = startEdge.Length minLength = min(2. * W, longestEdge.Length) PathLog.debug("length=%.2f shortestEdge=%.2f(%.2f) longestEdge=%.2f(%.2f) minLength=%.2f" % (self.baseWire.Length, shortestEdge.Length, shortestEdge.Length/self.baseWire.Length, longestEdge.Length, longestEdge.Length / self.baseWire.Length, minLength)) PathLog.debug(" start: index=%-2d count=%d (length=%.2f, distance=%.2f)" % (startIndex, startCount, startEdge.Length, tagDistance)) PathLog.debug(" -> lastTagLength=%.2f)" % lastTagLength) PathLog.debug(" -> currentLength=%.2f)" % currentLength) edgeDict = {startIndex: startCount} for i in range(startIndex + 1, len(self.baseWire.Edges)): edge = self.baseWire.Edges[i] (currentLength, lastTagLength) = self.processEdge(i, edge, currentLength, lastTagLength, tagDistance, minLength, edgeDict) for i in range(0, startIndex): edge = self.baseWire.Edges[i] (currentLength, lastTagLength) = self.processEdge(i, edge, currentLength, lastTagLength, tagDistance, minLength, edgeDict) tags = [] for (i, count) in PathUtil.keyValueIter(edgeDict): edge = self.baseWire.Edges[i] PathLog.debug(" %d: %d" % (i, count)) # debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2) # debugMarker(edge.Vertexes[1].Point, 'base', (0.0, 1.0, 0.0), 0.2) if 0 != count: distance = (edge.LastParameter - edge.FirstParameter) / count for j in range(0, count): tag = edge.Curve.value((j+0.5) * distance) tags.append(Tag(j, tag.x, tag.y, W, H, A, R, True)) return tags
def parse(inputstring): "parse(inputstring): returns a list of parsed output string" print("preprocessing...") # split the input by line lines = inputstring.split("\n") return_output = [] output = "" last = {'X':None,'Y':None,'Z':None,'A':None,'B':None} lastrapidspeed = {'XY':"50", 'Z':"50", 'A':"50", 'B':"50" } #set default rapid speeds lastfeedspeed = {'XY':"50", 'Z':"50", 'A':"50", 'B':"50" } #set default feed speed movecommand = ['G1', 'G0', 'G02', 'G03'] for l in lines: # remove any leftover trailing and preceding spaces l = l.strip() if not l: # discard empty lines continue if l[0] in ["'","&"]: # discard comment and other non strictly gcode lines if l[0:9] == "'New Path": # starting new path if any (x in output for x in movecommand): #make sure the path has at least one move command. return_output.append(output) output = "" continue words = [a.strip() for a in l.split(",")] words[0] = words[0].upper() if words[0] in ["J2","J3","J4","J5","M2","M3","M4","M5"]: #multi-axis jogs and moves if words[0][0] == 'J': #jog move s = "G0 " else: #feed move s = "G1 " speed = lastfeedspeed["XY"] for i in range (1, len(words)): if words [i] == '': if last[AXIS[i-1]] == None: continue else: s += AXIS[i-1] + last[AXIS[i-1]] else: s += AXIS[i-1] + words[i] last[AXIS[i-1]] = words[i] output += s +" F" + speed + '\n' if words[0] in ["JA","JB","JX","JY","JZ","MA","MB","MX","MY","MZ"]: #single axis jogs and moves if words[0][0] == 'J': #jog move s = "G0 " if words[0][1] in ['X','Y']: speed = lastrapidspeed["XY"] else: speed = lastrapidspeed[words[0][1]] else: #feed move s = "G1 " if words[0][1] in ['X','Y']: speed = lastfeedspeed["XY"] else: speed = lastfeedspeed[words[0][1]] last[words[0][1]] = words[1] output += s for key, val in PathUtil.keyValueIter(last): if val is not None: output += key + str(val) + " F" + speed + "\n" if words[0] in ["JS"]: #set jog speed for i in range (1, len(words)): if words [i] == '': continue else: lastrapidspeed[SPEEDS[i-1]] = words[i] if words[0] in ["MD"]: #move distance with distance and angle. #unsupported at this time continue if words[0] in ["MH"]: #move home #unsupported at this time continue if words[0] in ["MS"]: #set move speed for i in range (1, len(words)): if words [i] == '': continue else: lastfeedspeed[SPEEDS[i-1]] = words[i] if words[0] in ["MO"]: #motors off #unsupported at this time continue if words[0] in ["TR"]: #Setting spindle speed if float(words[1]) < 0: s = "M4 S" else: s = "M3 S" s += str(abs(float(words[1]))) output += s + '\n' if words[0] in ["CG"]: #Gcode circle/arc if words[1] != "": # diameter mode print("diameter mode not supported") continue else: if words[7] == "1": #CW s = "G2" else: #CCW s = "G3" s += " X" + words[2] + " Y" + words[3] + " I" + words[4] + " J" + words[5] + " F" + str(lastfeedspeed["XY"]) output += s + '\n' last["X"] = words[2] last["Y"] = words[3] #Make sure all appended paths have at least one move command. if any (x in output for x in movecommand): return_output.append(output) print("done preprocessing.") return return_output
def parse(inputstring): "parse(inputstring): returns a list of parsed output string" print("preprocessing...") # split the input by line lines = inputstring.split("\n") return_output = [] output = "" last = {'X': None, 'Y': None, 'Z': None, 'A': None, 'B': None} lastrapidspeed = { 'XY': "50", 'Z': "50", 'A': "50", 'B': "50" } # set default rapid speeds lastfeedspeed = { 'XY': "50", 'Z': "50", 'A': "50", 'B': "50" } # set default feed speed movecommand = ['G1', 'G0', 'G02', 'G03'] for line in lines: # remove any leftover trailing and preceding spaces line = line.strip() if not line: # discard empty lines continue if line[0] in ["'", "&"]: # discard comment and other non strictly gcode lines if line[0:9] == "'New Path": # starting new path if any(x in output for x in movecommand ): # make sure the path has at least one move command. return_output.append(output) output = "" continue words = [a.strip() for a in line.split(",")] words[0] = words[0].upper() if words[0] in ["J2", "J3", "J4", "J5", "M2", "M3", "M4", "M5"]: # multi-axis jogs and moves if words[0][0] == 'J': # jog move s = "G0 " else: # feed move s = "G1 " speed = lastfeedspeed["XY"] for i in range(1, len(words)): if words[i] == '': if last[AXIS[i - 1]] is None: continue else: s += AXIS[i - 1] + last[AXIS[i - 1]] else: s += AXIS[i - 1] + words[i] last[AXIS[i - 1]] = words[i] output += s + " F" + speed + '\n' if words[0] in [ "JA", "JB", "JX", "JY", "JZ", "MA", "MB", "MX", "MY", "MZ" ]: # single axis jogs and moves if words[0][0] == 'J': # jog move s = "G0 " if words[0][1] in ['X', 'Y']: speed = lastrapidspeed["XY"] else: speed = lastrapidspeed[words[0][1]] else: # feed move s = "G1 " if words[0][1] in ['X', 'Y']: speed = lastfeedspeed["XY"] else: speed = lastfeedspeed[words[0][1]] last[words[0][1]] = words[1] output += s for key, val in PathUtil.keyValueIter(last): if val is not None: output += key + str(val) + " F" + speed + "\n" if words[0] in ["JS"]: # set jog speed for i in range(1, len(words)): if words[i] == '': continue else: lastrapidspeed[SPEEDS[i - 1]] = words[i] if words[0] in ["MD"]: # move distance with distance and angle. # unsupported at this time continue if words[0] in ["MH"]: # move home # unsupported at this time continue if words[0] in ["MS"]: # set move speed for i in range(1, len(words)): if words[i] == '': continue else: lastfeedspeed[SPEEDS[i - 1]] = words[i] if words[0] in ["MO"]: # motors off # unsupported at this time continue if words[0] in ["TR"]: # Setting spindle speed if float(words[1]) < 0: s = "M4 S" else: s = "M3 S" s += str(abs(float(words[1]))) output += s + '\n' if words[0] in ["CG"]: # Gcode circle/arc if words[1] != "": # diameter mode print("diameter mode not supported") continue else: if words[7] == "1": # CW s = "G2" else: # CCW s = "G3" s += " X" + words[2] + " Y" + words[3] + " I" + words[ 4] + " J" + words[5] + " F" + str(lastfeedspeed["XY"]) output += s + '\n' last["X"] = words[2] last["Y"] = words[3] # Make sure all appended paths have at least one move command. if any(x in output for x in movecommand): return_output.append(output) print("done preprocessing.") return return_output