Exemple #1
0
    def __init__(self, obj, viewProvider, jvoVisibility=None):
        self.obj = obj
        self.obj.Proxy.obj = obj
        self.viewProvider = viewProvider
        self.form = QtGui.QWidget()
        self.formTags  = FreeCADGui.PySideUic.loadUi(":/panels/HoldingTagsEdit.ui")
        self.formPoint = FreeCADGui.PySideUic.loadUi(":/panels/PointEdit.ui")
        self.layout = QtGui.QVBoxLayout(self.form)
        #self.form.setGeometry(self.formTags.geometry())
        self.form.setWindowTitle(self.formTags.windowTitle())
        self.form.setSizePolicy(self.formTags.sizePolicy())
        self.formTags.setParent(self.form)
        self.formPoint.setParent(self.form)
        self.layout.addWidget(self.formTags)
        self.layout.addWidget(self.formPoint)
        self.formPoint.hide()
        self.jvo = PathUtils.findParentJob(obj).ViewObject
        if jvoVisibility is None:
            FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_HoldingTags", "Edit HoldingTags Dress-up"))
            self.jvoVisible = self.jvo.isVisible()
            if self.jvoVisible:
                self.jvo.hide()
        else:
            self.jvoVisible = jvoVisibility
        self.pt = FreeCAD.Vector(0, 0, 0)

        closeButton = self.formPoint.buttonBox.button(QtGui.QDialogButtonBox.StandardButton.Close)
        closeButton.setText(translate("PathDressup_HoldingTags", "Done"))

        self.isDirty = True
Exemple #2
0
def adjustWirePlacement(obj, shape, wires):
    job = PathUtils.findParentJob(obj)
    if hasattr(shape, 'MapMode') and 'Deactivated' != shape.MapMode:
        if hasattr(shape, 'Support') and 1 == len(shape.Support) and 1 == len(shape.Support[0][1]):
            pmntShape   = shape.Placement
            pmntSupport = shape.Support[0][0].getGlobalPlacement()
            #pmntSupport = shape.Support[0][0].Placement
            pmntBase    = job.Base.Placement
            pmnt = pmntBase.multiply(pmntSupport.inverse().multiply(pmntShape))
            #PathLog.debug("pmnt = %s" % pmnt)
            newWires = []
            for w in wires:
                edges = []
                for e in w.Edges:
                    e = e.copy()
                    e.Placement = FreeCAD.Placement()
                    edges.append(e)
                w = Part.Wire(edges)
                w.Placement = pmnt
                newWires.append(w)
            wires = newWires
        else:
            PathLog.warning(translate("PathEngrave", "Attachment not supported by engraver"))
    else:
        PathLog.debug("MapMode: %s" % (shape.MapMode if hasattr(shape, 'MapMode') else 'None')) 
    return wires
    def Activated(self):
        FreeCAD.ActiveDocument.openTransaction(
            translate("Path_Post", "Post Process the Selected path(s)"))
        FreeCADGui.addModule("PathScripts.PathPost")
        # select the Path Job that you want to post output from
        selected = FreeCADGui.Selection.getCompleteSelection()
        print "in activated %s" %(selected)

        # try to find the job, if it's not directly selected ...
        jobs = set()
        for obj in selected:
            if hasattr(obj, 'OutputFile') or hasattr(obj, 'PostProcessor'):
                jobs.add(obj)
            elif hasattr(obj, 'Path') or hasattr(obj, 'ToolNumber'):
                job = PathUtils.findParentJob(obj)
                if job:
                    jobs.add(job)

        fail = True
        rc = ''
        if len(jobs) != 1:
            FreeCAD.Console.PrintError("Please select a single job or other path object\n")
        else:
            job = jobs.pop()
            print("Job for selected objects = %s" % job.Name)
            (fail, rc) = self.exportObjectsWith(selected, job)

        if fail:
            FreeCAD.ActiveDocument.abortTransaction()
        else:
            FreeCAD.ActiveDocument.commitTransaction()
        FreeCAD.ActiveDocument.recompute()
    def areaOpOnChanged(self, obj, prop):
        '''areaOpOnChanged(obj, prop) ... facing specific depths calculation.'''
        PathLog.track(prop)
        if prop == "StepOver" and obj.StepOver == 0:
            obj.StepOver = 1

        # default depths calculation not correct for facing
        if prop == "Base":
            job = PathUtils.findParentJob(obj)
            obj.OpStartDepth = job.Stock.Shape.BoundBox.ZMax

            if len(obj.Base) >= 1:
                print('processing')
                sublist = []
                for i in obj.Base:
                    o = i[0]
                    for s in i[1]:
                        sublist.append(o.Shape.getElement(s))

            # If the operation has a geometry identified the Finaldepth
            # is the top of the bboundbox which includes all features.
            # Otherwise, top of part.

                obj.OpFinalDepth = Part.makeCompound(sublist).BoundBox.ZMax
            else:
                obj.OpFinalDepth = job.Base.Shape.BoundBox.ZMax
Exemple #5
0
def _OpenCloseResourceEditor(obj, vobj, edit):
    job = PathUtils.findParentJob(obj)
    if job and job.ViewObject and job.ViewObject.Proxy:
        if edit:
            job.ViewObject.Proxy.editObject(obj)
        else:
            job.ViewObject.Proxy.uneditObject(obj)
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return top face'''
        # Facing is done either against base objects
        if obj.Base:
            PathLog.debug("obj.Base: {}".format(obj.Base))
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                    else:
                        PathLog.debug('The base subobject is not a face')
                        return
            planeshape = Part.makeCompound(faces)
            PathLog.debug("Working on a collection of faces {}".format(faces))

        # If no base object, do planing of top surface of entire model
        else:
            planeshape = self.baseobject.Shape
            PathLog.debug("Working on a shape {}".format(self.baseobject.Name))

        # Find the correct shape depending on Boundary shape.
        PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape))
        bb = planeshape.BoundBox
        if obj.BoundaryShape == 'Boundbox':
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Vector(0, 0, 1))
            env = PathUtils.getEnvelope(partshape=bbperim, depthparams=self.depthparams)
        elif obj.BoundaryShape == 'Stock':
            stock = PathUtils.findParentJob(obj).Stock.Shape
            env = stock
        else:
            env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams)

        return [(env, False)]
    def addBaseGeometry(self, selection):
        added = False
        shapes = self.obj.BaseShapes
        for sel in selection:
            job = PathUtils.findParentJob(self.obj)
            base = job.Proxy.resourceClone(job, sel.Object)
            if not base:
                PathLog.notice((translate("Path", "%s is not a Base Model object of the job %s")+"\n") % (sel.Object.Label, job.Label))
                continue
            if base in shapes:
                PathLog.notice((translate("Path", "Base shape %s already in the list")+"\n") % (sel.Object.Label))
                continue
            if base.isDerivedFrom('Part::Part2DObject'):
                if sel.HasSubObjects:
                    # selectively add some elements of the drawing to the Base
                    for sub in sel.SubElementNames:
                        if 'Vertex' in sub:
                            PathLog.info(translate("Path", "Ignoring vertex"))
                        else:
                            self.obj.Proxy.addBase(self.obj, base, sub)
                else:
                    # when adding an entire shape to BaseShapes we can take its sub shapes out of Base
                    self.obj.Base = [(p,el) for p,el in self.obj.Base if p != base]
                    shapes.append(base)
                    self.obj.BaseShapes = shapes
                added = True
            else:
                # user wants us to engrave an edge of face of a base model
                base = self.super().addBaseGeometry(selection)
                added = added or base

        return added
Exemple #8
0
 def onDelete(self, arg1=None, arg2=None):
     '''this makes sure that the base operation is added back to the project and visible'''
     FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
     job = PathUtils.findParentJob(arg1.Object)
     job.Proxy.addOperation(arg1.Object.Base)
     arg1.Object.Base = None
     return True
Exemple #9
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        toolLoad = PathUtils.getLastToolLoad(obj)

        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horizRapid = 100
            self.radius = 0.25
            obj.ToolNumber = 0
            obj.ToolDescription = "UNDEFINED"
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
            if not tool or tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        self.setLabel(obj)

        output += "(" + obj.Label + ")"
        if not obj.UseComp:
            output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"
        else:
            output += "(Uncompensated Tool Path)"

        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return
        baseobject = parentJob.Base
        if baseobject is None:
            return
        contourwire = TechDraw.findShapeOutline(baseobject.Shape,1, Vector(0,0,1))

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)
        try:
            output += self._buildPathLibarea(obj, edgelist)
        except:
            FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            if obj.ViewObject:
                obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
Exemple #10
0
 def opOnChanged(self, obj, prop):
     '''opOnChanged(obj, prop) ... if Locations changed, check if depths should be calculated.'''
     super(self.__class__, self).opOnChanged(obj, prop)
     if prop == 'Locations' and not 'Restore' in obj.State and obj.Locations and not obj.Base:
         if not hasattr(self, 'baseobject'):
             job = PathUtils.findParentJob(obj)
             if job and job.Base:
                 self.setupDepthsFrom(obj, [], job.Base)
Exemple #11
0
 def opSetDefaultValues(self, obj):
     '''opSetDefaultValues(obj) ... set depths for engraving'''
     job = PathUtils.findParentJob(obj)
     if job and job.Base:
         bb = job.Base.Shape.BoundBox
         obj.OpStartDepth = bb.ZMax
         obj.OpFinalDepth = bb.ZMax - max(obj.StepDown.Value, 0.1)
     else:
         obj.OpFinalDepth = -0.1
 def areaOpSetDefaultValues(self, obj):
     '''areaOpSetDefaultValues(obj) ... set default values'''
     obj.StepOver = 100
     obj.ZigZagAngle = 45
     job = PathUtils.findParentJob(obj)
     if job and job.Stock:
         bb = job.Stock.Shape.BoundBox
         obj.OpFinalDepth = bb.ZMin
         obj.OpStartDepth = bb.ZMax
    def opExecute(self, obj):
        '''opExecute(obj) ... process engraving operation'''
        PathLog.track()

        output = ""
        if obj.Comment != "":
            output += '(' + str(obj.Comment)+')\n'


        output += "(" + obj.Label + ")"
        output += "(Compensated Tool Path. Diameter: " + str(obj.ToolController.Tool.Diameter) + ")"


        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return

        print("base object: " + self.baseobject.Name)

        if obj.Algorithm in ['OCL Dropcutter', 'OCL Waterline']:
            try:
                import ocl
            except:
                FreeCAD.Console.PrintError(
                        translate("Path_Surface", "This operation requires OpenCamLib to be installed.\n"))
                return

        if self.baseobject.TypeId.startswith('Mesh'):
            mesh = self.baseobject.Mesh
        else:
            # try/except is for Path Jobs created before GeometryTolerance
            try:
                deflection = parentJob.GeometryTolerance
            except AttributeError:
                from PathScripts.PathPreferences import PathPreferences
                deflection = PathPreferences.defaultGeometryTolerance()
            self.baseobject.Shape.tessellate(0.5)
            mesh = MeshPart.meshFromShape(self.baseobject.Shape, Deflection=deflection)

        bb = mesh.BoundBox

        s = ocl.STLSurf()
        for f in mesh.Facets:
            p = f.Points[0]
            q = f.Points[1]
            r = f.Points[2]
            t = ocl.Triangle(ocl.Point(p[0], p[1], p[2]), ocl.Point(
                q[0], q[1], q[2]), ocl.Point(r[0], r[1], r[2]))
            s.addTriangle(t)

        if obj.Algorithm == 'OCL Dropcutter':
            output = self._dropcutter(obj, s, bb)
        elif obj.Algorithm == 'OCL Waterline':
            output = self._waterline(obj, s, bb)

        self.commandlist.extend(output)
Exemple #14
0
    def updateDepths(self, obj, ignoreErrors=False):
        '''updateDepths(obj) ... base implementation calculating depths depending on base geometry.
        Should not be overwritten.'''

        def faceZmin(bb, fbb):
            if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax:  # top face
                return fbb.ZMin
            elif fbb.ZMax > fbb.ZMin and fbb.ZMax == bb.ZMax: # vertical face, full cut
                return fbb.ZMin
            elif fbb.ZMax > fbb.ZMin and fbb.ZMin > bb.ZMin:  # internal vertical wall
                return fbb.ZMin
            elif fbb.ZMax == fbb.ZMin and fbb.ZMax > bb.ZMin: # face/shelf
                return fbb.ZMin
            return bb.ZMin

        if not self._setBaseAndStock(obj, ignoreErrors):
            return False

        stockBB = self.stock.Shape.BoundBox
        zmin = stockBB.ZMin
        zmax = stockBB.ZMax

        if hasattr(obj, 'Base') and obj.Base:
            for base, sublist in obj.Base:
                bb = base.Shape.BoundBox
                zmax = max(zmax, bb.ZMax)
                for sub in sublist:
                    fbb = base.Shape.getElement(sub).BoundBox
                    zmin = max(zmin, faceZmin(bb, fbb))
                    zmax = max(zmax, fbb.ZMax)
        else:
            # clearing with stock boundaries
            job = PathUtils.findParentJob(obj)
            zmax = stockBB.ZMax
            zmin = job.Base.Shape.BoundBox.ZMax

        if FeatureDepths & self.opFeatures(obj):
            # first set update final depth, it's value is not negotiable
            if not PathGeom.isRoughly(obj.OpFinalDepth.Value, zmin):
                obj.OpFinalDepth = zmin
            zmin = obj.OpFinalDepth.Value

            def minZmax(z):
                if hasattr(obj, 'StepDown') and not PathGeom.isRoughly(obj.StepDown.Value, 0):
                    return z + obj.StepDown.Value
                else:
                    return z + 1

            # ensure zmax is higher than zmin
            if (zmax - 0.0001) <= zmin:
                zmax = minZmax(zmin)

            # update start depth if requested and required
            if not PathGeom.isRoughly(obj.OpStartDepth.Value, zmax):
                obj.OpStartDepth = zmax
    def areaOpSetDefaultValues(self, obj):
        '''areaOpSetDefaultValues(obj) ... initialize mill facing properties'''
       # obj.StepOver = 50
       # obj.ZigZagAngle = 45.0

        # need to overwrite the default depth calculations for facing
        job = PathUtils.findParentJob(obj)
        if job and job.Base:
            d = PathUtils.guessDepths(job.Base.Shape, None)
            obj.OpStartDepth = d.safe_height
            obj.OpFinalDepth = d.start_depth
Exemple #16
0
 def areaOpShapeForDepths(self, obj):
     '''areaOpShapeForDepths(obj) ... returns the shape used to make an initial calculation for the depths being used.
     The default implementation returns the job's Base.Shape'''
     job = PathUtils.findParentJob(obj)
     if job and job.Base:
         PathLog.debug("job=%s base=%s shape=%s" % (job, job.Base, job.Base.Shape))
         return job.Base.Shape
     if job:
         PathLog.warning(translate("PathAreaOp", "job %s has no Base.") % job.Label)
     else:
         PathLog.warning(translate("PathAreaOp", "no job for op %s found.") % obj.Label)
     return None
Exemple #17
0
 def opSetDefaultValues(self, obj):
     '''opSetDefaultValues(obj) ... set depths for engraving'''
     job = PathUtils.findParentJob(obj)
     if job and job.Base:
         bb = job.Base.Shape.BoundBox
         obj.OpStartDepth = bb.ZMax
         obj.OpFinalDepth = bb.ZMin
     else:
         obj.OpFinalDepth = -0.1
     if obj.OpStartDepth.Value != obj.OpFinalDepth.Value:
         # maintain behaviour of a single run
         obj.OpStepDown = obj.OpStartDepth.Value - obj.OpFinalDepth.Value
Exemple #18
0
    def opSetDefaultValues(self, obj, job):
        '''opSetDefaultValues(obj, job) ... initialize defaults'''

        # obj.ZigZagAngle = 45.0
        obj.StepOver = 50
        obj.Optimize = True
        # need to overwrite the default depth calculations for facing
        job = PathUtils.findParentJob(obj)
        if job and job.Stock:
            d = PathUtils.guessDepths(job.Stock.Shape, None)
            obj.OpStartDepth = d.start_depth
            obj.OpFinalDepth = d.final_depth
 def onDelete(self, arg1=None, arg2=None):
     PathLog.track()
     '''this makes sure that the base operation is added back to the job and visible'''
     if self.obj.Base.ViewObject:
         self.obj.Base.ViewObject.Visibility = True
     job = PathUtils.findParentJob(self.obj)
     job.Proxy.addOperation(arg1.Object.Base)
     arg1.Object.Base = None
     # if self.debugDisplay():
     #    self.vobj.Debug.removeObjectsFromDocument()
     #    self.vobj.Debug.Document.removeObject(self.vobj.Debug.Name)
     #    self.vobj.Debug = None
     return True
Exemple #20
0
 def _setBaseAndStock(self, obj, ignoreErrors=False):
     job = PathUtils.findParentJob(obj)
     if not job:
         if not ignoreErrors:
             PathLog.error(translate("Path", "No parent job found for operation."))
         return False
     if not job.Model.Group:
         if not ignoreErrors:
             PathLog.error(translate("Path", "Parent job %s doesn't have a base object") % job.Label)
         return False
     self.job = job
     self.model = job.Model.Group
     self.stock = job.Stock
     return True
Exemple #21
0
    def opOnChanged(self, obj, prop):
        '''opOnChange(obj, prop) ... implements depth calculation if Base changes.
        Do not overwrite.'''
        if 'Base' == prop and not 'Restore' in obj.State and obj.Base:
            features = []
            for base, subs in obj.Base:
                for sub in subs:
                    features.append((base, sub))

            job = PathUtils.findParentJob(obj)
            if not job or not job.Base:
                return

            self.setupDepthsFrom(obj, features, job.Base)
Exemple #22
0
    def opSetDefaultValues(self, obj, job):
        '''opSetDefaultValues(obj, job) ... set default value for RetractHeight'''
        obj.RetractHeight = 10.0
        obj.ReverseDirection = False
        obj.InverseAngle = False
        obj.B_AxisErrorOverride = False
        obj.AttemptInverseAngle = False

        # Initial setting for EnableRotation is taken from Job SetupSheet
        # User may override on per-operation basis as needed.
        parentJob = PathUtils.findParentJob(obj)
        if hasattr(parentJob.SetupSheet, 'SetupEnableRotation'):
            obj.EnableRotation = parentJob.SetupSheet.SetupEnableRotation
        else:
            obj.EnableRotation = 'Off'
Exemple #23
0
 def areaOpShapeForDepths(self, obj):
     '''areaOpShapeForDepths(obj) ... returns the shape used to make an initial calculation for the depths being used.
     The default implementation returns the job's Base.Shape'''
     job = PathUtils.findParentJob(obj)
     if job and job.Base:
         PathLog.debug("job=%s base=%s shape=%s" %
                       (job, job.Base, job.Base.Shape))
         return job.Base.Shape
     if job:
         PathLog.warning(
             translate("PathAreaOp", "job %s has no Base.") % job.Label)
     else:
         PathLog.warning(
             translate("PathAreaOp", "no job for op %s found.") % obj.Label)
     return None
Exemple #24
0
def Create(base, name='DogboneDressup'):
    '''
    Create(obj, name='DogboneDressup') ... dresses the given PathProfile/PathContour object with dogbones.
    '''
    obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', name)
    dbo = ObjectDressup(obj, base)
    job = PathUtils.findParentJob(base)
    job.Proxy.addOperation(obj, base)

    if FreeCAD.GuiUp:
        obj.ViewObject.Proxy = ViewProviderDressup(obj.ViewObject)
        obj.Base.ViewObject.Visibility = False

    dbo.setup(obj, True)
    return obj
Exemple #25
0
 def execute(self, obj):
     fixlist = ['G53', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1',
                'G59.2', 'G59.3', 'G59.4', 'G59.5', 'G59.6', 'G59.7', 'G59.8', 'G59.9']
     fixture = fixlist.index(obj.Fixture)
     obj.Path = Path.Path(str(obj.Fixture))
     obj.Label = "Fixture" + str(fixture)
     if obj.Active:
         job = PathUtils.findParentJob(obj)
         c1 = Path.Command(str(obj.Fixture))
         c2 = Path.Command("G0" + str(job.Stock.Shape.BoundBox.ZMax))
         obj.Path = Path.Path([c1, c2])
         obj.ViewObject.Visibility = True
     else:
         obj.Path = Path.Path("(inactive operation)")
         obj.ViewObject.Visibility = False
Exemple #26
0
 def onDelete(self, arg1=None, arg2=None):
     '''this makes sure that the base operation is added back to the job and visible'''
     # pylint: disable=unused-argument
     PathLog.track()
     if self.obj.Base.ViewObject:
         self.obj.Base.ViewObject.Visibility = True
     job = PathUtils.findParentJob(self.obj)
     if arg1.Object and arg1.Object.Base and job:
         job.Proxy.addOperation(arg1.Object.Base, arg1.Object)
         arg1.Object.Base = None
     # if self.debugDisplay():
     #    self.vobj.Debug.removeObjectsFromDocument()
     #    self.vobj.Debug.Document.removeObject(self.vobj.Debug.Name)
     #    self.vobj.Debug = None
     return True
def Create(base, name='DogboneDressup'):
    '''
    Create(obj, name='DogboneDressup') ... dresses the given PathProfile/PathContour object with dogbones.
    '''
    obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', 'DogboneDressup')
    dbo = ObjectDressup(obj, base)
    job = PathUtils.findParentJob(base)
    job.Proxy.addOperation(obj)

    if FreeCAD.GuiUp:
        ViewProviderDressup(obj.ViewObject)
        obj.Base.ViewObject.Visibility = False

    dbo.setup(obj, True)
    return obj
Exemple #28
0
    def process_looped_sublist(self, obj, norm, surf):
        '''process_looped_sublist(obj, norm, surf)...
        Process set of looped faces when rotation is enabled.
        '''
        PathLog.debug(translate("Path", "Selected faces form loop. Processing looped faces."))
        rtn = False
        (rtn, angle, axis, praInfo) = self.faceRotationAnalysis(obj, norm, surf)  # pylint: disable=unused-variable

        if rtn is True:
            faceNums = ""
            for f in subsList:
                faceNums += '_' + f.replace('Face', '')
            (clnBase, angle, clnStock, tag) = self.applyRotationalAnalysis(obj, base, angle, axis, faceNums)  # pylint: disable=unused-variable

            # Verify faces are correctly oriented - InverseAngle might be necessary
            PathLog.debug("Checking if faces are oriented correctly after rotation.")
            for sub in subsList:
                face = clnBase.Shape.getElement(sub)
                if type(face.Surface) == Part.Plane:
                    if not PathGeom.isHorizontal(face.Surface.Axis):
                        rtn = False
                        PathLog.warning(translate("PathPocketShape", "Face appears to NOT be horizontal AFTER rotation applied."))
                        break

            if rtn is False:
                PathLog.debug(translate("Path", "Face appears misaligned after initial rotation.") + ' 1')
                if obj.InverseAngle:
                    (clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
                else:
                    if obj.AttemptInverseAngle is True:
                        (clnBase, clnStock, angle) = self.applyInverseAngle(obj, clnBase, clnStock, axis, angle)
                    else:
                        msg = translate("Path", "Consider toggling the 'InverseAngle' property and recomputing.")
                        PathLog.warning(msg)

            if angle < 0.0:
                angle += 360.0

            tup = clnBase, subsList, angle, axis, clnStock
        else:
            if self.warnDisabledAxis(obj, axis) is False:
                PathLog.debug("No rotation used")
            axis = 'X'
            angle = 0.0
            stock = PathUtils.findParentJob(obj).Stock
            tup = base, subsList, angle, axis, stock
        # Eif
        return tup
Exemple #29
0
    def areaOpSetDefaultValues(self, obj):
        '''areaOpSetDefaultValues(obj) ... initialize mill facing properties'''
        obj.StepOver = 50
        obj.ZigZagAngle = 45.0

        job = PathUtils.findParentJob(obj)

        # need to overwrite the default depth calculations for facing
        if job and job.Base:
            obj.OpStartDepth = job.Stock.Shape.BoundBox.ZMax
            obj.OpFinalDepth = job.Base.Shape.BoundBox.ZMax

            # If the operation has a geometry identified the Finaldepth
            # is the top of the bboundbox which includes all features.
            if len(obj.Base) >= 1:
                obj.OpFinalDepth = Part.makeCompound(obj.Base).BoundBox.ZMax
Exemple #30
0
    def areaOpSetDefaultValues(self, obj):
        '''areaOpSetDefaultValues(obj) ... initialize mill facing properties'''
        obj.StepOver = 50
        obj.ZigZagAngle = 45.0

        job = PathUtils.findParentJob(obj)

        # need to overwrite the default depth calculations for facing
        if job and job.Base:
            obj.OpStartDepth = job.Stock.Shape.BoundBox.ZMax
            obj.OpFinalDepth = job.Base.Shape.BoundBox.ZMax

            # If the operation has a geometry identified the Finaldepth
            # is the top of the bboundbox which includes all features.
            if len(obj.Base) >= 1:
                obj.OpFinalDepth = Part.makeCompound(obj.Base).BoundBox.ZMax
Exemple #31
0
    def addFacebase(self, obj, ss, sub=""):
        baselist = obj.Base
        if baselist is None:
            baselist = []
        if len(baselist) == 0:  # When adding the first base object, guess at heights
            self._guessDepths(obj, ss, sub)

        item = (ss, sub)
        if item in baselist:
            FreeCAD.Console.PrintWarning(translate("Path", "this object already in the list" + "\n"))
        elif PathUtils.findParentJob(obj).Base.Name != ss.Name:
            FreeCAD.Console.PrintWarning(translate("Path", "Please select features from the Job model object" + "\n"))
        else:
            baselist.append(item)
        obj.Base = baselist
        self.execute(obj)
Exemple #32
0
def Create(base, name='DogboneDressup'):
    '''
    Create(obj, name='DogboneDressup') ... dresses the given PathProfile/PathContour object with dogbones.
    '''
    obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython',
                                           'DogboneDressup')
    dbo = ObjectDressup(obj, base)
    job = PathUtils.findParentJob(base)
    PathUtils.addObjectToJob(obj, job)

    if FreeCAD.GuiUp:
        ViewProviderDressup(obj.ViewObject)
        obj.Base.ViewObject.Visibility = False

    dbo.setup(obj, True)
    obj.ToolController = base.ToolController
    return obj
Exemple #33
0
 def _setBaseAndStock(self, obj, ignoreErrors=False):
     job = PathUtils.findParentJob(obj)
     if not job:
         if not ignoreErrors:
             PathLog.error(translate("Path", "No parent job found for operation."))
         return False
     if not job.Model.Group:
         if not ignoreErrors:
             PathLog.error(
                 translate("Path", "Parent job %s doesn't have a base object")
                 % job.Label
             )
         return False
     self.job = job
     self.model = job.Model.Group
     self.stock = job.Stock
     return True
Exemple #34
0
    def __init__(self, obj, viewProvider, jvoVisibility=None):
        self.obj = obj
        self.obj.Proxy.obj = obj
        self.viewProvider = viewProvider
        self.form = FreeCADGui.PySideUic.loadUi(":/panels/HoldingTagsEdit.ui")
        self.getPoint = PathGetPoint.TaskPanel(self.form.removeEditAddGroup, True)
        self.jvo = PathUtils.findParentJob(obj).ViewObject
        if jvoVisibility is None:
            FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_HoldingTags", "Edit HoldingTags Dress-up"))
            self.jvoVisible = self.jvo.isVisible()
            if self.jvoVisible:
                self.jvo.hide()
        else:
            self.jvoVisible = jvoVisibility
        self.pt = FreeCAD.Vector(0, 0, 0)

        self.isDirty = True
Exemple #35
0
    def Activated(self):
        FreeCAD.ActiveDocument.openTransaction(
            translate("Path_Post", "Post Process the Selected path(s)"))
        FreeCADGui.addModule("PathScripts.PathPost")
        # select the Path Job that you want to post output from
        selected = FreeCADGui.Selection.getCompleteSelection()
        print "in activated %s" % (selected)

        # try to find the job, if it's not directly selected ...
        jobs = set()
        for obj in selected:
            if hasattr(obj, 'OutputFile') or hasattr(obj, 'PostProcessor'):
                jobs.add(obj)
            elif hasattr(obj, 'Path') or hasattr(obj, 'ToolNumber'):
                job = PathUtils.findParentJob(obj)
                if job:
                    jobs.add(job)
        if len(jobs) != 1:
            FreeCAD.Console.PrintError(
                "Please select a single job or other path object\n")
            FreeCAD.ActiveDocument.abortTransaction()
        else:
            job = jobs.pop()
            print("Job for selected objects = %s" % job.Name)

            # check if the user has a project and has set the default post and
            # output filename
            postArgs = PathPreferences.defaultPostProcessorArgs()
            if hasattr(job, "PostProcessorArgs") and job.PostProcessorArgs:
                postArgs = job.PostProcessorArgs
            elif hasattr(job, "PostProcessor") and job.PostProcessor:
                postArgs = ''

            postname = self.resolvePostProcessor(job)
            if postname:
                filename = self.resolveFileName(job)

            if postname and filename:
                print("post: %s(%s, %s)" % (postname, filename, postArgs))
                processor = PostProcessor.load(postname)
                processor.export(selected, filename, postArgs)

                FreeCAD.ActiveDocument.commitTransaction()
            else:
                FreeCAD.ActiveDocument.abortTransaction()
        FreeCAD.ActiveDocument.recompute()
Exemple #36
0
 def execute(self, obj):
     fixlist = [
         'G53', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1', 'G59.2',
         'G59.3', 'G59.4', 'G59.5', 'G59.6', 'G59.7', 'G59.8', 'G59.9'
     ]
     fixture = fixlist.index(obj.Fixture)
     obj.Path = Path.Path(str(obj.Fixture))
     obj.Label = "Fixture" + str(fixture)
     if obj.Active:
         job = PathUtils.findParentJob(obj)
         c1 = Path.Command(str(obj.Fixture))
         c2 = Path.Command("G0" + str(job.Stock.Shape.BoundBox.ZMax))
         obj.Path = Path.Path([c1, c2])
         obj.ViewObject.Visibility = True
     else:
         obj.Path = Path.Path("(inactive operation)")
         obj.ViewObject.Visibility = False
    def Activated(self):
        FreeCAD.ActiveDocument.openTransaction(
            translate("Path_Post", "Post Process the Selected path(s)"))
        FreeCADGui.addModule("PathScripts.PathPost")
        # select the Path Job that you want to post output from
        selected = FreeCADGui.Selection.getCompleteSelection()
        print "in activated %s" %(selected)

        # try to find the job, if it's not directly selected ...
        jobs = set()
        for obj in selected:
            if hasattr(obj, 'OutputFile') or hasattr(obj, 'PostProcessor'):
                jobs.add(obj)
            elif hasattr(obj, 'Path') or hasattr(obj, 'ToolNumber'):
                job = PathUtils.findParentJob(obj)
                if job:
                    jobs.add(job)
        if len(jobs) != 1:
            FreeCAD.Console.PrintError("Please select a single job or other path object\n")
            FreeCAD.ActiveDocument.abortTransaction()
        else:
            job = jobs.pop()
            print("Job for selected objects = %s" % job.Name)

            # check if the user has a project and has set the default post and
            # output filename
            postArgs = PathPreferences.defaultPostProcessorArgs()
            if hasattr(job, "PostProcessorArgs") and job.PostProcessorArgs:
                postArgs = job.PostProcessorArgs
            elif hasattr(job, "PostProcessor") and job.PostProcessor:
                postArgs = ''

            postname = self.resolvePostProcessor(job)
            if postname:
                filename = self.resolveFileName(job)

            if postname and filename:
                print("post: %s(%s, %s)" % (postname, filename, postArgs))
                processor = PostProcessor.load(postname)
                processor.export(selected, filename, postArgs)

                FreeCAD.ActiveDocument.commitTransaction()
            else:
                FreeCAD.ActiveDocument.abortTransaction()
        FreeCAD.ActiveDocument.recompute()
    def get_stock_silhoutte(self, obj):
        '''
        Get Stock Silhoutte
        '''
        stockBB = self.stock.Shape.BoundBox
        stock_z_pos = stockBB.ZMax
        parentJob = PathUtils.findParentJob(obj)

        self.startOffset = obj.StartDepth.Value - stockBB.ZMax + parentJob.SetupSheet.SafeHeightOffset.Value
        self.endOffset = stockBB.ZMin - obj.FinalDepth.Value

        stock_plane_length = obj.StartDepth.Value - obj.FinalDepth.Value
        stock_plane_width = stockBB.XLength / 2
        stock_plane = Part.makePlane(
            stock_plane_length, stock_plane_width,
            FreeCAD.Vector(-stock_plane_width, 0, stock_z_pos),
            FreeCAD.Vector(0, -1, 0))
        return stock_plane
Exemple #39
0
    def setDepths(proxy, obj):
        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return
        baseobject = parentJob.Base
        if baseobject is None:
            return

        try:
            bb = baseobject.Shape.BoundBox  # parent boundbox
            obj.StartDepth = bb.ZMax
            obj.ClearanceHeight = bb.ZMax + 5.0
            obj.SafeHeight = bb.ZMax + 3.0

        except:
            obj.StartDepth = 5.0
            obj.ClearanceHeight = 10.0
            obj.SafeHeight = 8.0
Exemple #40
0
    def setDepths(proxy, obj):
        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return
        baseobject = parentJob.Base
        if baseobject is None:
            return

        try:
            bb = baseobject.Shape.BoundBox  # parent boundbox
            obj.StartDepth = bb.ZMax
            obj.ClearanceHeight = bb.ZMax + 5.0
            obj.SafeHeight = bb.ZMax + 3.0

        except:
            obj.StartDepth = 5.0
            obj.ClearanceHeight = 10.0
            obj.SafeHeight = 8.0
def Create(baseObject, name='DressupTag'):
    '''
    Create(basePath, name='DressupTag') ... create tag dressup object for the given base path.
    '''
    if not baseObject.isDerivedFrom('Path::Feature'):
        PathLog.error(translate('Path_DressupTag', 'The selected object is not a path')+'\n')
        return None

    if baseObject.isDerivedFrom('Path::FeatureCompoundPython'):
        PathLog.error(translate('Path_DressupTag', 'Please select a Profile object'))
        return None

    obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
    dbo = ObjectTagDressup(obj, baseObject)
    job = PathUtils.findParentJob(baseObject)
    job.Proxy.addOperation(obj)
    dbo.setup(obj, True)
    return obj
def Create(baseObject, name='DressupTag'):
    '''
    Create(basePath, name='DressupTag') ... create tag dressup object for the given base path.
    '''
    if not baseObject.isDerivedFrom('Path::Feature'):
        PathLog.error(translate('Path_DressupTag', 'The selected object is not a path')+'\n')
        return None

    if baseObject.isDerivedFrom('Path::FeatureCompoundPython'):
        PathLog.error(translate('Path_DressupTag', 'Please select a Profile object'))
        return None

    obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
    dbo = ObjectTagDressup(obj, baseObject)
    job = PathUtils.findParentJob(baseObject)
    job.Proxy.addOperation(obj, baseObject)
    dbo.setup(obj, True)
    return obj
Exemple #43
0
    def getProps(self, obj):
        # TODO: use the start and final depths
        # print('getProps - Start Depth: ', obj.OpStartDepth.Value, 'Final Depth: ', obj.OpFinalDepth.Value)
        parentJob = PathUtils.findParentJob(obj)

        props = {}
        props['min_dia'] = self.minDia
        props['extra_dia'] = self.maxDia - self.stock.Shape.BoundBox.XLength
        props['start_offset'] = self.startOffset
        props['end_offset'] = self.endOffset
        props['allow_grooving'] = self.allowGrooving
        props['step_over'] = self.stepOver
        props['finish_passes'] = self.finishPasses
        props['stock_to_leave'] = self.stockToLeave
        props['hfeed'] = obj.ToolController.HorizFeed.Value
        props['vfeed'] = obj.ToolController.VertFeed.Value
        props['clearance'] = parentJob.SetupSheet.SafeHeightOffset.Value
        return props
    def opDetermineRotationRadii(self, obj):
        '''opDetermineRotationRadii(obj)
            Determine rotational radii for 4th-axis rotations, for clearance/safe heights '''

        parentJob = PathUtils.findParentJob(obj)
        # bb = parentJob.Stock.Shape.BoundBox
        xlim = 0.0
        ylim = 0.0
        zlim = 0.0
        xRotRad = 0.01
        yRotRad = 0.01
        xRotRad = 0.01

        # Determine boundbox radius based upon xzy limits data
        if math.fabs(self.stockBB.ZMin) > math.fabs(self.stockBB.ZMax):
            zlim = self.stockBB.ZMin
        else:
            zlim = self.stockBB.ZMax

        if obj.EnableRotation != 'B(y)':
            # Rotation is around X-axis, cutter moves along same axis
            if math.fabs(self.stockBB.YMin) > math.fabs(self.stockBB.YMax):
                ylim = self.stockBB.YMin
            else:
                ylim = self.stockBB.YMax

        if obj.EnableRotation != 'A(x)':
            # Rotation is around Y-axis, cutter moves along same axis
            if math.fabs(self.stockBB.XMin) > math.fabs(self.stockBB.XMax):
                xlim = self.stockBB.XMin
            else:
                xlim = self.stockBB.XMax

        if ylim != 0.0:
            xRotRad = math.sqrt(ylim**2 + zlim**2)
        if xlim != 0.0:
            yRotRad = math.sqrt(xlim**2 + zlim**2)
        zRotRad = math.sqrt(xlim**2 + ylim**2)

        clrOfst = parentJob.SetupSheet.ClearanceHeightOffset.Value
        safOfst = parentJob.SetupSheet.SafeHeightOffset.Value

        return [(xRotRad, yRotRad, zRotRad), (clrOfst, safOfst)]
Exemple #45
0
    def opExecute(self, obj):
        '''opExecute(obj) ... generate probe locations.'''
        PathLog.track()
        self.commandlist.append(Path.Command("(Begin Probing)"))

        stock = PathUtils.findParentJob(obj).Stock
        bb = stock.Shape.BoundBox

        openstring = '(PROBEOPEN {})'.format(obj.OutputFileName)
        self.commandlist.append(Path.Command(openstring))
        self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))

        for y in self.nextpoint(bb.YMin, bb.YMax, obj.PointCountY):
            for x in self.nextpoint(bb.XMin, bb.XMax, obj.PointCountX):
                self.commandlist.append(Path.Command("G0", {"X": x + obj.Xoffset.Value, "Y": y + obj.Yoffset.Value,  "Z": obj.SafeHeight.Value}))
                self.commandlist.append(Path.Command("G38.2", {"Z": obj.FinalDepth.Value, "F": obj.ToolController.VertFeed.Value}))
                self.commandlist.append(Path.Command("G0", {"Z": obj.SafeHeight.Value}))

        self.commandlist.append(Path.Command("(PROBECLOSE)"))
Exemple #46
0
def Create(baseObject, name="DressupTag"):
    """
    Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path.
    """
    if not baseObject.isDerivedFrom("Path::Feature"):
        PathLog.error(
            translate("Path_DressupTag", "The selected object is not a path") +
            "\n")
        return None

    if baseObject.isDerivedFrom("Path::FeatureCompoundPython"):
        PathLog.error(
            translate("Path_DressupTag", "Please select a Profile object"))
        return None

    obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
    dbo = ObjectDressup(obj, baseObject)
    job = PathUtils.findParentJob(baseObject)
    job.addOperation(obj)
    dbo.assignDefaultValues()
    return obj
Exemple #47
0
def Create(baseObject, name='DressupTag'):
    '''
    Create(basePath, name = 'DressupTag') ... create tag dressup object for the given base path.
    '''
    if not baseObject.isDerivedFrom('Path::Feature'):
        PathLog.error(
            translate('PathDressup_Tag',
                      'The selected object is not a path\n'))
        return None

    if baseObject.isDerivedFrom('Path::FeatureCompoundPython'):
        PathLog.error(
            translate('PathDressup_Tag', 'Please select a Profile object'))
        return None

    obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
    dbo = ObjectDressup(obj, baseObject)
    job = PathUtils.findParentJob(baseObject)
    PathUtils.addObjectToJob(obj, job)
    dbo.assignDefaultValues()
    return obj
Exemple #48
0
    def _extractFaceOffset(self, obj, fcShape, isHole):
        '''_extractFaceOffset(obj, fcShape, isHole) ... internal function.
            Original _buildPathArea() version copied from PathAreaOp.py module.  This version is modified.
            Adjustments made based on notes by @sliptonic - https://github.com/sliptonic/FreeCAD/wiki/PathArea-notes.'''
        PathLog.debug('_extractFaceOffset()')

        areaParams = {}
        JOB = PathUtils.findParentJob(obj)
        tolrnc = JOB.GeometryTolerance.Value
        if self.useComp is True:
            offset = self.ofstRadius  # + tolrnc
        else:
            offset = self.offsetExtra  # + tolrnc

        if isHole is False:
            offset = 0 - offset

        areaParams['Offset'] = offset
        areaParams['Fill'] = 1
        areaParams['Coplanar'] = 0
        areaParams[
            'SectionCount'] = 1  # -1 = full(all per depthparams??) sections
        areaParams['Reorient'] = True
        areaParams['OpenMode'] = 0
        areaParams['MaxArcPoints'] = 400  # 400
        areaParams['Project'] = True
        # areaParams['JoinType'] = 1

        area = Path.Area()  # Create instance of Area() class object
        area.setPlane(PathUtils.makeWorkplane(fcShape))  # Set working plane
        area.add(fcShape)  # obj.Shape to use for extracting offset
        area.setParams(**areaParams)  # set parameters

        # Save parameters for debugging
        # obj.AreaParams = str(area.getParams())
        # PathLog.debug("Area with params: {}".format(area.getParams()))

        offsetShape = area.getShape()

        return offsetShape
Exemple #49
0
    def addBaseGeometry(self, selection):
        PathLog.track(selection)
        added = False
        shapes = self.obj.BaseShapes
        for sel in selection:
            job = PathUtils.findParentJob(self.obj)
            base = job.Proxy.resourceClone(job, sel.Object)
            if not base:
                PathLog.notice((translate(
                    "Path", "%s is not a Base Model object of the job %s") +
                                "\n") % (sel.Object.Label, job.Label))
                continue
            if base in shapes:
                PathLog.notice(
                    (translate("Path", "Base shape %s already in the list") +
                     "\n") % (sel.Object.Label))
                continue
            if base.isDerivedFrom('Part::Part2DObject'):
                if sel.HasSubObjects:
                    # selectively add some elements of the drawing to the Base
                    for sub in sel.SubElementNames:
                        if 'Vertex' in sub:
                            PathLog.info(translate("Path", "Ignoring vertex"))
                        else:
                            self.obj.Proxy.addBase(self.obj, base, sub)
                else:
                    # when adding an entire shape to BaseShapes we can take its sub shapes out of Base
                    self.obj.Base = [(p, el) for p, el in self.obj.Base
                                     if p != base]
                    shapes.append(base)
                    self.obj.BaseShapes = shapes
                added = True

        if not added:
            # user wants us to engrave an edge of face of a base model
            PathLog.info("  call default")
            base = self.super().addBaseGeometry(selection)
            added = added or base

        return added
Exemple #50
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return top face'''
        # Facing is done either against base objects
        if obj.Base:
            PathLog.debug("obj.Base: {}".format(obj.Base))
            faces = []
            for b in obj.Base:
                for sub in b[1]:
                    shape = getattr(b[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                    else:
                        PathLog.debug('The base subobject is not a face')
                        return
            planeshape = Part.makeCompound(faces)
            PathLog.debug("Working on a collection of faces {}".format(faces))

        # If no base object, do planing of top surface of entire model
        else:
            planeshape = self.baseobject.Shape
            PathLog.debug("Working on a shape {}".format(self.baseobject.Name))

        # Find the correct shape depending on Boundary shape.
        PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape))
        bb = planeshape.BoundBox
        if obj.BoundaryShape == 'Boundbox':
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1,
                                   FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin),
                                   FreeCAD.Vector(0, 0, 1))
            env = PathUtils.getEnvelope(partshape=bbperim,
                                        depthparams=self.depthparams)
        elif obj.BoundaryShape == 'Stock':
            stock = PathUtils.findParentJob(obj).Stock.Shape
            env = stock
        else:
            env = PathUtils.getEnvelope(partshape=planeshape,
                                        depthparams=self.depthparams)

        return [(env, False)]
def create(baseFace):

	model = baseFace[0]
	job = PathUtils.findParentJob(model)
	doc = model.Document
	helperGrpName = job.Name + '_HelperGeometry'
	helperGrp = doc.getObject(helperGrpName)
	
	if not helperGrp:
		helperGrp = doc.addObject("App::DocumentObjectGroup", helperGrpName)

	objName = model.Name
	faceName = baseFace[1]
	modelFaceName = objName + '.' + faceName 	

	helperFaceName = modelFaceName + '_Helper'
	obj = helperGrp.newObject('Part::FeaturePython', helperFaceName)
	
	HelperFace(obj, baseFace)
	ViewProviderHelperFace(obj.ViewObject)
	FreeCAD.ActiveDocument.recompute()
	return obj
Exemple #52
0
 def cloneBaseAndStock(self, obj, base, angle, axis, subCount):
     '''cloneBaseAndStock(obj, base, angle, axis, subCount)
         Method called to create a temporary clone of the base and parent Job stock.
         Clones are destroyed after usage for calculations related to rotational operations.'''
     # Create a temporary clone and stock of model for rotational use.
     rndAng = round(angle, 8)
     if rndAng < 0.0:  # neg sign is converted to underscore in clone name creation.
         tag = axis + '_' + axis + '_' + str(math.fabs(rndAng)).replace(
             '.', '_')
     else:
         tag = axis + str(rndAng).replace('.', '_')
     clnNm = obj.Name + '_base_' + '_' + str(subCount) + '_' + tag
     stckClnNm = obj.Name + '_stock_' + '_' + str(subCount) + '_' + tag
     if clnNm not in self.cloneNames:
         self.cloneNames.append(clnNm)
         self.cloneNames.append(stckClnNm)
         if FreeCAD.ActiveDocument.getObject(clnNm):
             FreeCAD.ActiveDocument.removeObject(clnNm)
         if FreeCAD.ActiveDocument.getObject(stckClnNm):
             FreeCAD.ActiveDocument.removeObject(stckClnNm)
         FreeCAD.ActiveDocument.addObject('Part::Feature',
                                          clnNm).Shape = base.Shape
         FreeCAD.ActiveDocument.addObject(
             'Part::Feature',
             stckClnNm).Shape = PathUtils.findParentJob(obj).Stock.Shape
         if FreeCAD.GuiUp:
             FreeCADGui.ActiveDocument.getObject(
                 stckClnNm).Transparency = 90
             FreeCADGui.ActiveDocument.getObject(clnNm).ShapeColor = (1.000,
                                                                      0.667,
                                                                      0.000)
         self.useTempJobClones(clnNm)
         self.useTempJobClones(stckClnNm)
     clnBase = FreeCAD.ActiveDocument.getObject(clnNm)
     clnStock = FreeCAD.ActiveDocument.getObject(stckClnNm)
     tag = base.Name + '_' + tag
     return (clnBase, clnStock, tag)
Exemple #53
0
def mkHeader(selection):
    job = PathUtils.findParentJob(selection[0])
  # this is within a function, because otherwise filename and time don't change when changing the FreeCAD project
    #  now = datetime.datetime.now()
    now = time.strftime("%Y-%m-%d %H:%M")
    originfile = FreeCAD.ActiveDocument.FileName
    headerNoNumber = "%PM\n"     # this line gets no linenumber
    if hasattr(job, "Description"):
        description = job.Description
    else:
        description = ""
    # this line gets no linenumber, it is already a specially numbered
    headerNoNumber += "N9XXX (" + description + ", " + now + ")\n"
    header = ""
#  header += "(Output Time:" + str(now) + ")\n"
    header += "(" + originfile + ")\n"
#    header += "(Exported by FreeCAD)\n"
    header += "(Post Processor: " + __name__ + ")\n"
#    header += "(Target machine: " + MACHINE_NAME + ")\n"
    header += "G18\n"                 # Select XY plane
    header += "G90\n"                 # Absolute coordinates
    header += "G51\n"                 # Reset Zero
    header += "G52 (ersetze G55-G59)" # set zero
    return headerNoNumber + linenumberify(header)
Exemple #54
0
def mkHeader(selection):
    job = PathUtils.findParentJob(selection[0])
    # this is within a function, because otherwise filename and time don't change when changing the FreeCAD project
    #  now = datetime.datetime.now()
    now = time.strftime("%Y-%m-%d %H:%M")
    originfile = FreeCAD.ActiveDocument.FileName
    headerNoNumber = "%PM\n"  # this line gets no linenumber
    if hasattr(job, "Description"):
        description = job.Description
    else:
        description = ""
    # this line gets no linenumber, it is already a specially numbered
    headerNoNumber += "N9XXX (" + description + ", " + now + ")\n"
    header = ""
    #  header += "(Output Time:" + str(now) + ")\n"
    header += "(" + originfile + ")\n"
    #    header += "(Exported by FreeCAD)\n"
    header += "(Post Processor: " + __name__ + ")\n"
    #    header += "(Target machine: " + MACHINE_NAME + ")\n"
    header += "G18\n"  # Select XY plane
    header += "G90\n"  # Absolute coordinates
    header += "G51\n"  # Reset Zero
    header += "G52 (ersetze G55-G59)"  # set zero
    return headerNoNumber + linenumberify(header)
Exemple #55
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        PathLog.track()
        PathLog.debug("----- areaOpShapes() in PathProfileFaces.py")

        if obj.UseComp:
            self.commandlist.append(
                Path.Command("(Compensated Tool Path. Diameter: " +
                             str(self.radius * 2) + ")"))
        else:
            self.commandlist.append(Path.Command("(Uncompensated Tool Path)"))

        shapes = []
        self.profileshape = []
        finalDepths = []

        baseSubsTuples = []
        subCount = 0
        allTuples = []

        if obj.Base:  # The user has selected subobjects from the base.  Process each.
            if obj.EnableRotation != 'Off':
                for p in range(0, len(obj.Base)):
                    (base, subsList) = obj.Base[p]
                    for sub in subsList:
                        subCount += 1
                        shape = getattr(base.Shape, sub)
                        if isinstance(shape, Part.Face):
                            rtn = False
                            (norm, surf) = self.getFaceNormAndSurf(shape)
                            (rtn, angle, axis,
                             praInfo) = self.faceRotationAnalysis(
                                 obj, norm, surf)
                            if rtn is True:
                                (clnBase, angle, clnStock,
                                 tag) = self.applyRotationalAnalysis(
                                     obj, base, angle, axis, subCount)
                                # Verify faces are correctly oriented - InverseAngle might be necessary
                                faceIA = getattr(clnBase.Shape, sub)
                                (norm, surf) = self.getFaceNormAndSurf(faceIA)
                                (rtn, praAngle, praAxis,
                                 praInfo) = self.faceRotationAnalysis(
                                     obj, norm, surf)
                                if rtn is True:
                                    PathLog.error(
                                        translate(
                                            "Path",
                                            "Face appears misaligned after initial rotation."
                                        ))
                                    if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
                                        (clnBase, clnStock,
                                         angle) = self.applyInverseAngle(
                                             obj, clnBase, clnStock, axis,
                                             angle)
                                    else:
                                        msg = translate(
                                            "Path",
                                            "Consider toggling the 'InverseAngle' property and recomputing."
                                        )
                                        PathLog.error(msg)
                                        # title = translate("Path", 'Rotation Warning')
                                        # self.guiMessage(title, msg, False)
                                else:
                                    PathLog.debug(
                                        "Face appears to be oriented correctly."
                                    )

                                tup = clnBase, sub, tag, angle, axis, clnStock
                            else:
                                if self.warnDisabledAxis(obj, axis) is False:
                                    PathLog.debug(
                                        str(sub) + ": No rotation used")
                                axis = 'X'
                                angle = 0.0
                                tag = base.Name + '_' + axis + str(
                                    angle).replace('.', '_')
                                stock = PathUtils.findParentJob(obj).Stock
                                tup = base, sub, tag, angle, axis, stock
                            # Eif
                            allTuples.append(tup)
                        # Eif
                    # Efor
                # Efor
                if subCount > 1:
                    msg = translate('Path',
                                    "Multiple faces in Base Geometry.") + "  "
                    msg += translate(
                        'Path', "Depth settings will be applied to all faces.")
                    PathLog.warning(msg)
                    # title = translate("Path", "Depth Warning")
                    # self.guiMessage(title, msg)
                (Tags, Grps) = self.sortTuplesByIndex(
                    allTuples, 2)  # return (TagList, GroupList)
                subList = []
                for o in range(0, len(Tags)):
                    subList = []
                    for (base, sub, tag, angle, axis, stock) in Grps[o]:
                        subList.append(sub)
                    pair = base, subList, angle, axis, stock
                    baseSubsTuples.append(pair)
                # Efor
            else:
                PathLog.info(
                    translate("Path", "EnableRotation property is 'Off'."))
                stock = PathUtils.findParentJob(obj).Stock
                for (base, subList) in obj.Base:
                    baseSubsTuples.append((base, subList, 0.0, 'X', stock))

            # for base in obj.Base:
            for (base, subsList, angle, axis, stock) in baseSubsTuples:
                holes = []
                faces = []

                for sub in subsList:
                    shape = getattr(base.Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z),
                                         1):  # horizontal face
                            for wire in shape.Wires[1:]:
                                holes.append((base.Shape, wire))
                    else:
                        ignoreSub = base.Name + '.' + sub
                        msg = translate(
                            'Path',
                            "Found a selected object which is not a face. Ignoring: {}"
                            .format(ignoreSub))
                        PathLog.error(msg)
                        FreeCAD.Console.PrintWarning(msg)
                        # return

                for shape, wire in holes:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                    drillable = PathUtils.isDrillable(shape, wire)
                    if (drillable
                            and obj.processCircles) or (not drillable
                                                        and obj.processHoles):
                        PathLog.track()
                        # Recalculate depthparams
                        (strDep, finDep) = self.calculateStartFinalDepths(
                            obj, shape, stock)
                        finalDepths.append(finDep)
                        PathLog.debug(
                            "Adjusted face depths strDep: {}, and finDep: {}".
                            format(self.strDep, self.finDep))
                        finish_step = obj.FinishDepth.Value if hasattr(
                            obj, "FinishDepth") else 0.0
                        self.depthparams = PathUtils.depth_params(
                            clearance_height=obj.ClearanceHeight.Value,
                            safe_height=obj.SafeHeight.Value,
                            start_depth=strDep,  # obj.StartDepth.Value,
                            step_down=obj.StepDown.Value,
                            z_finish_step=finish_step,
                            final_depth=finDep,  # obj.FinalDepth.Value,
                            user_depths=None)
                        env = PathUtils.getEnvelope(
                            shape, subshape=f, depthparams=self.depthparams)
                        # shapes.append((env, True))
                        tup = env, True, 'pathProfileFaces', angle, axis, strDep, finDep
                        shapes.append(tup)

                if len(faces) > 0:
                    profileshape = Part.makeCompound(faces)
                    self.profileshape.append(profileshape)

                if obj.processPerimeter:
                    PathLog.track()
                    if profileshape:
                        # Recalculate depthparams
                        (strDep, finDep) = self.calculateStartFinalDepths(
                            obj, profileshape, stock)
                        finalDepths.append(finDep)
                        PathLog.debug(
                            "Adjusted face depths strDep: {}, and finDep: {}".
                            format(self.strDep, self.finDep))
                        finish_step = obj.FinishDepth.Value if hasattr(
                            obj, "FinishDepth") else 0.0
                        self.depthparams = PathUtils.depth_params(
                            clearance_height=obj.ClearanceHeight.Value,
                            safe_height=obj.SafeHeight.Value,
                            start_depth=strDep,  # obj.StartDepth.Value,
                            step_down=obj.StepDown.Value,
                            z_finish_step=finish_step,
                            final_depth=finDep,  # obj.FinalDepth.Value,
                            user_depths=None)
                    else:
                        strDep = obj.StartDepth.Value
                        finDep = obj.FinalDepth.Value
                    try:
                        env = PathUtils.getEnvelope(
                            base.Shape,
                            subshape=profileshape,
                            depthparams=self.depthparams)
                    except Exception:
                        # PathUtils.getEnvelope() failed to return an object.
                        PathLog.error(
                            translate('Path',
                                      'Unable to create path for face(s).'))
                    else:
                        # shapes.append((env, False))
                        tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep
                        shapes.append(tup)
                else:
                    for shape in faces:
                        # Recalculate depthparams
                        (strDep, finDep) = self.calculateStartFinalDepths(
                            obj, shape, stock)
                        finalDepths.append(finDep)
                        finish_step = obj.FinishDepth.Value if hasattr(
                            obj, "FinishDepth") else 0.0
                        self.depthparams = PathUtils.depth_params(
                            clearance_height=obj.ClearanceHeight.Value,
                            safe_height=obj.SafeHeight.Value,
                            start_depth=strDep,  # obj.StartDepth.Value,
                            step_down=obj.StepDown.Value,
                            z_finish_step=finish_step,
                            final_depth=finDep,  # obj.FinalDepth.Value,
                            user_depths=None)
                        env = PathUtils.getEnvelope(
                            base.Shape,
                            subshape=shape,
                            depthparams=self.depthparams)
                        tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep
                        shapes.append(tup)
                # Eif

            # adjust FinalDepth as needed
            finalDepth = min(finalDepths)
            if obj.FinalDepth.Value < finalDepth:
                obj.FinalDepth.Value = finalDepth
        else:  # Try to build targets from the job base
            if 1 == len(self.model) and hasattr(self.model[0], "Proxy"):
                if isinstance(self.model[0].Proxy,
                              ArchPanel.PanelSheet):  # process the sheet
                    if obj.processCircles or obj.processHoles:
                        for shape in self.model[0].Proxy.getHoles(
                                self.model[0], transform=True):
                            for wire in shape.Wires:
                                drillable = PathUtils.isDrillable(
                                    self.model[0].Proxy, wire)
                                if (drillable and obj.processCircles) or (
                                        not drillable and obj.processHoles):
                                    f = Part.makeFace(wire,
                                                      'Part::FaceMakerSimple')
                                    env = PathUtils.getEnvelope(
                                        self.model[0].Shape,
                                        subshape=f,
                                        depthparams=self.depthparams)
                                    # shapes.append((env, True))
                                    tup = env, True, 'pathProfileFaces', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value
                                    shapes.append(tup)

                    if obj.processPerimeter:
                        for shape in self.model[0].Proxy.getOutlines(
                                self.model[0], transform=True):
                            for wire in shape.Wires:
                                f = Part.makeFace(wire,
                                                  'Part::FaceMakerSimple')
                                env = PathUtils.getEnvelope(
                                    self.model[0].Shape,
                                    subshape=f,
                                    depthparams=self.depthparams)
                                # shapes.append((env, False))
                                tup = env, False, 'pathProfileFaces', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value
                                shapes.append(tup)

        self.removalshapes = shapes
        PathLog.debug("%d shapes" % len(shapes))

        return shapes
Exemple #56
0
    def execute(self, obj):
        PathLog.track()

        if not obj.Active:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
            return

        output = ""
        if obj.Comment != "":
            output += '(' + str(obj.Comment) + ')\n'

        toolLoad = obj.ToolController
        if toolLoad is None or toolLoad.ToolNumber == 0:
            FreeCAD.Console.PrintError(
                "No Tool Controller is selected. We need a tool to build a Path."
            )
            return
        else:
            self.vertFeed = toolLoad.VertFeed.Value
            self.horizFeed = toolLoad.HorizFeed.Value
            self.vertRapid = toolLoad.VertRapid.Value
            self.horizRapid = toolLoad.HorizRapid.Value
            tool = toolLoad.Proxy.getTool(toolLoad)
            if not tool or tool.Diameter == 0:
                FreeCAD.Console.PrintError(
                    "No Tool found or diameter is zero. We need a tool to build a Path."
                )
                return
            else:
                self.radius = tool.Diameter / 2

        tiplength = 0.0
        if obj.AddTipLength:
            tiplength = PathUtils.drillTipLength(tool)

        if len(obj.Names) == 0:
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return

            # Arch PanelSheet
            if hasattr(baseobject, "Proxy"):
                holes = []
                if isinstance(baseobject.Proxy, ArchPanel.PanelSheet):
                    baseobject.Proxy.execute(baseobject)
                    i = 0
                    holeshapes = baseobject.Proxy.getHoles(baseobject,
                                                           transform=True)
                    tooldiameter = obj.ToolController.Proxy.getTool(
                        obj.ToolController).Diameter
                    for holeshape in holeshapes:
                        PathLog.debug('Entering new HoleShape')
                        for wire in holeshape.Wires:
                            PathLog.debug('Entering new Wire')
                            for edge in wire.Edges:
                                if PathUtils.isDrillable(
                                        baseobject, edge, tooldiameter):
                                    PathLog.debug(
                                        'Found drillable hole edges: {}'.
                                        format(edge))
                                    x = edge.Curve.Center.x
                                    y = edge.Curve.Center.y
                                    diameter = edge.BoundBox.XLength
                                    holes.append({
                                        'x':
                                        x,
                                        'y':
                                        y,
                                        'featureName':
                                        baseobject.Name + '.' + 'Drill' +
                                        str(i),
                                        'd':
                                        diameter
                                    })
                                    i = i + 1
            else:
                holes = self.findHoles(obj, baseobject.Shape)
                for i in range(len(holes)):
                    holes[i]['featureName'] = baseobject.Name + '.' + holes[i][
                        'featureName']
            names = []
            positions = []
            enabled = []
            diameters = []
            for h in holes:
                if len(names) == 0:
                    self.setDepths(obj, baseobject, h)
                names.append(h['featureName'])
                positions.append(FreeCAD.Vector(h['x'], h['y'], 0))
                enabled.append(1)
                diameters.append(h['d'])
            obj.Names = names
            obj.Positions = positions
            obj.Enabled = enabled
            obj.Diameters = diameters

        locations = []
        output = "(Begin Drilling)\n"

        for i in range(len(obj.Names)):
            if obj.Enabled[i] > 0:
                locations.append({
                    'x': obj.Positions[i].x,
                    'y': obj.Positions[i].y
                })
        if len(locations) > 0:
            locations = PathUtils.sort_jobs(locations, ['x', 'y'])
            output += "G90 " + obj.ReturnLevel + "\n"
            # rapid to clearance height
            output += "G0 Z" + str(
                obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(
                    self.vertRapid) + "\n"
            # rapid to first hole location, with spindle still retracted:

            p0 = locations[0]
            output += "G0 X" + fmt(p0['x']) + " Y" + fmt(
                p0['y']) + "F " + PathUtils.fmt(self.horizRapid) + "\n"
            # move tool to clearance plane
            output += "G0 Z" + fmt(
                obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(
                    self.vertRapid) + "\n"
            pword = ""
            qword = ""
            if obj.PeckDepth.Value > 0 and obj.PeckEnabled:
                cmd = "G83"
                qword = " Q" + fmt(obj.PeckDepth.Value)
            elif obj.DwellTime > 0 and obj.DwellEnabled:
                cmd = "G82"
                pword = " P" + fmt(obj.DwellTime)
            else:
                cmd = "G81"
            for p in locations:
                output += cmd + \
                    " X" + fmt(p['x']) + \
                    " Y" + fmt(p['y']) + \
                    " Z" + fmt(obj.FinalDepth.Value - tiplength) + qword + pword + \
                    " R" + str(obj.RetractHeight.Value) + \
                    " F" + str(self.vertFeed) + "\n" \

            output += "G80\n"

        path = Path.Path(output)
        obj.Path = path
Exemple #57
0
    def opExecute(self, obj):
        '''opExecute(obj) ... process engraving operation'''
        PathLog.track()

        job = PathUtils.findParentJob(obj)
        if job and job.Base:
            obj.BaseObject = job.Base

        zValues = []
        if obj.StepDown.Value != 0:
            z = obj.StartDepth.Value - obj.StepDown.Value

            while z > obj.FinalDepth.Value:
                zValues.append(z)
                z -= obj.StepDown.Value
        zValues.append(obj.FinalDepth.Value)
        self.zValues = zValues

        try:
            if self.baseobject.isDerivedFrom('Sketcher::SketchObject') or \
                    self.baseobject.isDerivedFrom('Part::Part2DObject') or \
                    hasattr(self.baseobject, 'ArrayType'):
                PathLog.track()

                self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))

                # we only consider the outer wire if this is a Face
                wires = []
                for w in self.baseobject.Shape.Wires:
                    wires.append(Part.Wire(w.Edges))
                self.buildpathocc(obj, wires, zValues)
                self.wires = wires

            elif isinstance(self.baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                PathLog.track()
                wires = []
                for tag in self.baseobject.Proxy.getTags(self.baseobject, transform=True):
                    self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
                    tagWires = []
                    for w in tag.Wires:
                        tagWires.append(Part.Wire(w.Edges))
                    self.buildpathocc(obj, tagWires, zValues)
                    wires.extend(tagWires)
                self.wires = wires
            elif obj.Base:
                PathLog.track()
                wires = []
                for base, subs in obj.Base:
                    #edges = []
                    #for sub in subs:
                    #    edges.extend(base.Shape.getElement(sub).Edges)
                    #shapeWires = adjustWirePlacement(obj, base, TechDraw.edgeWalker(edges))
                    #wires.extend(shapeWires)
                    for feature in subs:
                        sub = base.Shape.getElement(feature)
                        if sub.Wires:
                            shapeWires = sub.Wires
                        else:
                            shapeWires = [Part.Wire(sub.Edges)]
                    wires.extend(adjustWirePlacement(obj, base, shapeWires))
                self.buildpathocc(obj, wires, zValues)
                self.wires = wires
            elif not obj.BaseShapes:
                PathLog.track()
                raise ValueError(translate('PathEngrave', "Unknown baseobject type for engraving (%s)") % (obj.Base))

            if obj.BaseShapes:
                PathLog.track()
                wires = []
                for shape in obj.BaseShapes:
                    shapeWires = adjustWirePlacement(obj, shape, shape.Shape.Wires)
                    self.buildpathocc(obj, shapeWires, zValues)
                    wires.extend(shapeWires)
                self.wires = wires

        except Exception as e:
            PathLog.error(e)
            traceback.print_exc()
            PathLog.error(translate('PathEngrave', 'The Job Base Object has no engraveable element.  Engraving operation will produce no output.'))
Exemple #58
0
	def Activated(self):
		PathLog.track()
		FreeCAD.ActiveDocument.openTransaction(
			translate("Path_Post", "Post Process the Selected path(s)"))
		FreeCADGui.addModule("PathScripts.PathPost")

		# Attempt to figure out what the user wants to post-process
		# If a job is selected, post that.
		# If there's only one job in a document, post it.
		# If a user has selected a subobject of a job, post the job.
		# If multiple jobs and can't guess, ask them.

		selected = FreeCADGui.Selection.getSelectionEx()
		if len(selected) > 1:
			FreeCAD.Console.PrintError(
			"Please select a single job or other path object\n")
			return

		elif len(selected) == 1:
			sel = selected[0].Object
			if sel.Name[:3] == "Job":
				job = sel
			elif hasattr(sel, "Path"):
				try:
					job = PathUtils.findParentJob(sel)
				except Exception:  # pylint: disable=broad-except
					job = None
			else:
				job = None
		if job is None:
			targetlist = []
			for o in FreeCAD.ActiveDocument.Objects:
				if hasattr(o, "Proxy"):
					if isinstance(o.Proxy, PathJob.ObjectJob):
						targetlist.append(o.Label)
			PathLog.debug("Possible post objects: {}".format(targetlist))
			if len(targetlist) > 1:
				form = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobChooser.ui")
				form.cboProject.addItems(targetlist)
				r = form.exec_()
				if r is False:
					return
				else:
					jobname = form.cboProject.currentText()
			else:
				jobname = targetlist[0]
			job = FreeCAD.ActiveDocument.getObject(jobname)

		PathLog.debug("about to postprocess job: {}".format(job.Name))

		# Build up an ordered list of operations and tool changes.
		# Then post-the ordered list
		if hasattr(job, "Fixtures"):
			wcslist = job.Fixtures
		else:
			wcslist = ['G54']

		if hasattr(job, "OrderOutputBy"):
			orderby = job.OrderOutputBy
		else:
			orderby = "Operation"

		if hasattr(job, "SplitOutput"):
			split = job.SplitOutput
		else:
			split = False

		if hasattr(job, "OperatorSetupsheet"):
			ossheet = job.OperatorSetupsheet
		else:
			ossheet = False

		postlist = []

		if orderby == 'Fixture':
			PathLog.debug("Ordering by Fixture")
			# Order by fixture means all operations and tool changes will be completed in one
			# fixture before moving to the next.

			currTool = None
			for index, f in enumerate(wcslist):
				# create an object to serve as the fixture path
				fobj = _TempObject()
				c1 = Path.Command(f)
				fobj.Path = Path.Path([c1])
				if index != 0:
					c2 = Path.Command("G0 Z" + str(job.Stock.Shape.BoundBox.ZMax
					+ job.SetupSheet.ClearanceHeightOffset.Value))
					fobj.Path.addCommands(c2)
				fobj.InList.append(job)
				sublist = [fobj]

				# Now generate the gcode
				for obj in job.Operations.Group:
					tc = PathUtil.toolControllerForOp(obj)
					if tc is not None and PathUtil.opProperty(obj, 'Active'):
						if tc.ToolNumber != currTool:
							sublist.append(tc)
							PathLog.debug("Appending TC: {}".format(tc.Name))
							currTool = tc.ToolNumber
						sublist.append(obj)
					postlist.append(sublist)

		elif orderby == 'Tool':
			PathLog.debug("Ordering by Tool")
			# Order by tool means tool changes are minimized.
			# all operations with the current tool are processed in the current
			# fixture before moving to the next fixture.

			currTool = None
			fixturelist = []
			for f in wcslist:
				# create an object to serve as the fixture path
				fobj = _TempObject()
				c1 = Path.Command(f)
				c2 = Path.Command("G0 Z" + str(job.Stock.Shape.BoundBox.ZMax + job.SetupSheet.ClearanceHeightOffset.Value))

				fobj.Path = Path.Path([c1, c2])
				fobj.InList.append(job)
				fixturelist.append(fobj)

			# Now generate the gcode
			curlist = []  # list of ops for tool, will repeat for each fixture
			sublist = []  # list of ops for output splitting

			for idx, obj in enumerate(job.Operations.Group):

				# check if the operation is active
				active = PathUtil.opProperty(obj, 'Active')

				tc = PathUtil.toolControllerForOp(obj)
				if tc is None or tc.ToolNumber == currTool and active:
					curlist.append(obj)
				elif tc.ToolNumber != currTool and currTool is None and active:  # first TC
					sublist.append(tc)
					curlist.append(obj)
					currTool = tc.ToolNumber
				elif tc.ToolNumber != currTool and currTool is not None and active:  # TC
					for fixture in fixturelist:
						sublist.append(fixture)
						sublist.extend(curlist)
					postlist.append(sublist)
					sublist = [tc]
					curlist = [obj]
					currTool = tc.ToolNumber

				if idx == len(job.Operations.Group) - 1:  # Last operation.
					for fixture in fixturelist:
						sublist.append(fixture)
						sublist.extend(curlist)
					postlist.append(sublist)

		elif orderby == 'Operation':
			PathLog.debug("Ordering by Operation")
			# Order by operation means ops are done in each fixture in
			# sequence.
			currTool = None
			firstFixture = True

			# Now generate the gcode
			for obj in job.Operations.Group:
				if PathUtil.opProperty(obj, 'Active'):
					sublist = []
					PathLog.debug("obj: {}".format(obj.Name))
					for f in wcslist:
						fobj = _TempObject()
						c1 = Path.Command(f)
						fobj.Path = Path.Path([c1])
						if not firstFixture:
							c2 = Path.Command("G0 Z" + str(job.Stock.Shape.BoundBox.ZMax + job.SetupSheet.ClearanceHeightOffset.Value))
							fobj.Path.addCommands(c2)
						fobj.InList.append(job)
						sublist.append(fobj)
						firstFixture = False
						tc = PathUtil.toolControllerForOp(obj)
						if tc is not None:
							if tc.ToolNumber != currTool:
								sublist.append(tc)
								currTool = tc.ToolNumber
						sublist.append(obj)
					postlist.append(sublist)

		fail = True
		rc = '' # pylint: disable=unused-variable
		if split:
			for slist in postlist:
				(fail, rc) = self.exportObjectsWith(slist, job)
		else:
			finalpostlist = [item for slist in postlist for item in slist]
			(fail, rc) = self.exportObjectsWith(finalpostlist, job)

		self.subpart = 1

		if fail:
			FreeCAD.ActiveDocument.abortTransaction()
		else:
			FreeCAD.ActiveDocument.commitTransaction()

		if ossheet:
			FreeCAD.Console.PrintLog("Create OperatorSetupsheet\n")
		else:
			FreeCAD.Console.PrintLog("Do not create OperatorSetupsheet\n")

		FreeCAD.ActiveDocument.recompute()