def opExecute(self, obj, getsim=False): """opExecute(obj, getsim=False) ... implementation of Path.Area ops. determines the parameters for _buildPathArea(). Do not overwrite, implement areaOpAreaParams(obj, isHole) ... op specific area param dictionary areaOpPathParams(obj, isHole) ... op specific path param dictionary areaOpShapes(obj) ... the shape for path area to process areaOpUseProjection(obj) ... return true if operation can use projection instead.""" PathLog.track() # Instantiate class variables for operation reference self.endVector = None self.leadIn = 2.0 # Initiate depthparams and calculate operation heights for operation self.depthparams = self._customDepthParams(obj, obj.StartDepth.Value, obj.FinalDepth.Value) # Set start point if PathOp.FeatureStartPoint & self.opFeatures( obj) and obj.UseStartPoint: start = obj.StartPoint else: start = None aOS = self.areaOpShapes(obj) # Adjust tuples length received from other PathWB tools/operations shapes = [] for shp in aOS: if len(shp) == 2: (fc, iH) = shp # fc, iH, sub or description tup = fc, iH, "otherOp" shapes.append(tup) else: shapes.append(shp) if len(shapes) > 1: locations = [] for s in shapes: if s[2] == "OpenEdge": shp = Part.makeCompound(s[0]) else: shp = s[0] locations.append({ "x": shp.BoundBox.XMax, "y": shp.BoundBox.YMax, "shape": s }) locations = PathUtils.sort_locations(locations, ["x", "y"]) shapes = [j["shape"] for j in locations] sims = [] for shape, isHole, sub in shapes: profileEdgesIsOpen = False if sub == "OpenEdge": profileEdgesIsOpen = True if (PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint): osp = obj.StartPoint self.commandlist.append( Path.Command("G0", { "X": osp.x, "Y": osp.y, "F": self.horizRapid })) try: if profileEdgesIsOpen: (pp, sim) = self._buildProfileOpenEdges( obj, shape, isHole, start, getsim) else: (pp, sim) = self._buildPathArea(obj, shape, isHole, start, getsim) except Exception as e: FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError( "Something unexpected happened. Check project and tool config." ) raise e else: if profileEdgesIsOpen: ppCmds = pp else: ppCmds = pp.Commands # Save gcode commands to object command list self.commandlist.extend(ppCmds) sims.append(sim) # Eif if (self.areaOpRetractTool(obj) and self.endVector is not None and len(self.commandlist) > 1): self.endVector[2] = obj.ClearanceHeight.Value self.commandlist.append( Path.Command("G0", { "Z": obj.ClearanceHeight.Value, "F": self.vertRapid })) PathLog.debug("obj.Name: " + str(obj.Name) + "\n\n") return sims
def circularHoleExecute(self, obj, holes): """circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.""" PathLog.track() machine = PathMachineState.MachineState() self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height command = Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) machine.addCommand(command) self.commandlist.append(command) self.commandlist.append(Path.Command("G90")) # Absolute distance mode # Calculate offsets to add to target edge endoffset = 0.0 if obj.ExtraOffset == "Drill Tip": endoffset = PathUtils.drillTipLength(self.tool) elif obj.ExtraOffset == "2x Drill Tip": endoffset = PathUtils.drillTipLength(self.tool) * 2 # http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g98-g99 self.commandlist.append(Path.Command(obj.ReturnLevel)) holes = PathUtils.sort_locations(holes, ["x", "y"]) # This section is technical debt. The computation of the # target shapes should be factored out for re-use. # This will likely mean refactoring upstream CircularHoleBase to pass # spotshapes instead of holes. startHeight = obj.StartDepth.Value + self.job.SetupSheet.SafeHeightOffset.Value edgelist = [] for hole in holes: v1 = FreeCAD.Vector(hole["x"], hole["y"], obj.StartDepth.Value) v2 = FreeCAD.Vector(hole["x"], hole["y"], obj.FinalDepth.Value - endoffset) edgelist.append(Part.makeLine(v1, v2)) # iterate the edgelist and generate gcode for edge in edgelist: PathLog.debug(edge) # move to hole location startPoint = edge.Vertexes[0].Point command = Path.Command("G0", { "X": startPoint.x, "Y": startPoint.y }) self.commandlist.append(command) machine.addCommand(command) command = Path.Command("G0", {"Z": startHeight}) self.commandlist.append(command) machine.addCommand(command) # command = Path.Command("G1", {"Z": obj.StartDepth.Value}) # self.commandlist.append(command) # machine.addCommand(command) # Technical Debt: We are assuming the edges are aligned. # This assumption should be corrected and the necessary rotations # performed to align the edge with the Z axis for drilling # Perform drilling dwelltime = obj.DwellTime if obj.DwellEnabled else 0.0 peckdepth = obj.PeckDepth.Value if obj.PeckEnabled else 0.0 repeat = 1 # technical debt: Add a repeat property for user control chipBreak = (obj.chipBreakEnabled and obj.PeckEnabled) try: drillcommands = generator.generate(edge, dwelltime, peckdepth, repeat, obj.RetractHeight.Value, chipBreak=chipBreak) except ValueError as e: # any targets that fail the generator are ignored PathLog.info(e) continue for command in drillcommands: self.commandlist.append(command) machine.addCommand(command) # Cancel canned drilling cycle self.commandlist.append(Path.Command("G80")) command = Path.Command("G0", {"Z": obj.SafeHeight.Value}) self.commandlist.append(command) machine.addCommand(command) # Apply feedrates to commands PathFeedRate.setFeedRate(self.commandlist, obj.ToolController)