Exemplo n.º 1
0
 def initOperation(self, obj):
     """initOperation(obj) ... create vcarve specific properties."""
     obj.addProperty(
         "App::PropertyFloat",
         "Discretize",
         "Path",
         QT_TRANSLATE_NOOP("App::Property",
                           "The deflection value for discretizing arcs"),
     )
     obj.addProperty(
         "App::PropertyFloat",
         "Colinear",
         "Path",
         QT_TRANSLATE_NOOP(
             "App::Property",
             "Cutoff for removing colinear segments (degrees). \
                     default=10.0.",
         ),
     )
     obj.addProperty(
         "App::PropertyFloat",
         "Tolerance",
         "Path",
         QT_TRANSLATE_NOOP("App::Property", "Vcarve Tolerance"),
     )
     obj.Colinear = 10.0
     obj.Discretize = 0.01
     obj.Tolerance = PathPreferences.defaultGeometryTolerance()
     self.setupAdditionalProperties(obj)
Exemplo n.º 2
0
    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:
                import PathScripts.PathPreferences as 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)
Exemplo n.º 3
0
    def loadSettings(self):
        self.form.leDefaultFilePath.setText(PathPreferences.defaultFilePath())
        self.form.leDefaultJobTemplate.setText(PathPreferences.defaultJobTemplate())

        blacklist = PathPreferences.postProcessorBlacklist()
        for processor in PathPreferences.allAvailablePostProcessors():
            item = QtGui.QListWidgetItem(processor)
            if processor in blacklist:
                item.setCheckState(QtCore.Qt.CheckState.Unchecked)
            else:
                item.setCheckState(QtCore.Qt.CheckState.Checked)
            item.setFlags( QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable)
            self.form.postProcessorList.addItem(item)
        self.verifyAndUpdateDefaultPostProcessorWith(PathPreferences.defaultPostProcessor())

        self.form.defaultPostProcessorArgs.setText(PathPreferences.defaultPostProcessorArgs())

        geomTol = Units.Quantity(PathPreferences.defaultGeometryTolerance(), Units.Length)
        self.form.geometryTolerance.setText(geomTol.UserString)
        self.form.curveAccuracy.setText(Units.Quantity(PathPreferences.defaultLibAreaCurveAccuracy(), Units.Length).UserString)

        self.form.leOutputFile.setText(PathPreferences.defaultOutputFile())
        self.selectComboEntry(self.form.cboOutputPolicy, PathPreferences.defaultOutputPolicy())

        self.form.tbDefaultFilePath.clicked.connect(self.browseDefaultFilePath)
        self.form.tbDefaultJobTemplate.clicked.connect(self.browseDefaultJobTemplate)
        self.form.postProcessorList.itemEntered.connect(self.setProcessorListTooltip)
        self.form.postProcessorList.itemChanged.connect(self.verifyAndUpdateDefaultPostProcessor)
        self.form.defaultPostProcessor.currentIndexChanged.connect(self.updateDefaultPostProcessorToolTip)
        self.form.tbOutputFile.clicked.connect(self.browseOutputFile)

        self.loadStockSettings()
Exemplo n.º 4
0
    def __init__(self, obj, models, templateFile = None):
        self.obj = obj
        obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","The NC output file for this project"))
        obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","Select the Post Processor"))
        obj.addProperty("App::PropertyString", "PostProcessorArgs", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Arguments for the Post Processor (specific to the script)"))

        obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("PathJob","An optional description for this job"))
        obj.addProperty("App::PropertyString", "CycleTime", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "Operations Cycle Time Estimation"))
        obj.setEditorMode('CycleTime', 1)  # read-only
        obj.addProperty("App::PropertyDistance", "GeometryTolerance", "Geometry", QtCore.QT_TRANSLATE_NOOP("PathJob", "For computing Paths; smaller increases accuracy, but slows down computation"))

        obj.addProperty("App::PropertyLink", "Stock", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock."))
        obj.addProperty("App::PropertyLink", "Operations", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Compound path of all operations in the order they are processed."))
        obj.addProperty("App::PropertyLinkList", "ToolController", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of tool controllers available for this job."))

        obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","Split output into multiple gcode files"))
        obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
        obj.addProperty("App::PropertyStringList", "Fixtures", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "The Work Coordinate Systems for the Job"))
        obj.OrderOutputBy = ['Fixture', 'Tool', 'Operation']
        obj.Fixtures = ['G54']
        
        obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
        #obj.setEditorMode("PostProcessorOutputFile", 0)  # set to default mode
        obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors()
        defaultPostProcessor = PathPreferences.defaultPostProcessor()
        # Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed)
        if defaultPostProcessor in postProcessors:
            obj.PostProcessor = defaultPostProcessor
        else:
            obj.PostProcessor = postProcessors[0]
        obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
        obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()

        ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
        if ops.ViewObject:
            ops.ViewObject.Proxy = 0
            ops.ViewObject.Visibility = False

        obj.Operations = ops
        obj.setEditorMode('Operations', 2) # hide
        obj.setEditorMode('Placement', 2)

        self.setupSetupSheet(obj)
        self.setupBaseModel(obj, models)

        self.tooltip = None
        self.tooltipArgs = None

        obj.Proxy = self

        self.setFromTemplateFile(obj, templateFile)
        if not obj.Stock:
            stockTemplate = PathPreferences.defaultStockTemplate()
            if stockTemplate:
                obj.Stock = PathStock.CreateFromTemplate(obj, json.loads(stockTemplate))
            if not obj.Stock:
                obj.Stock = PathStock.CreateFromBase(obj)
        if obj.Stock.ViewObject:
            obj.Stock.ViewObject.Visibility = False
Exemplo n.º 5
0
    def __init__(self, obj, models, templateFile = None):
        self.obj = obj
        obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","The NC output file for this project"))
        obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","Select the Post Processor"))
        obj.addProperty("App::PropertyString", "PostProcessorArgs", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Arguments for the Post Processor (specific to the script)"))

        obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("PathJob","An optional description for this job"))
        obj.addProperty("App::PropertyDistance", "GeometryTolerance", "Geometry", QtCore.QT_TRANSLATE_NOOP("PathJob", "For computing Paths; smaller increases accuracy, but slows down computation"))

        obj.addProperty("App::PropertyLink", "Stock", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock."))
        obj.addProperty("App::PropertyLink", "Operations", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Compound path of all operations in the order they are processed."))
        obj.addProperty("App::PropertyLinkList", "ToolController", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of tool controllers available for this job."))

        obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob","Split output into multiple gcode files"))
        obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
        obj.addProperty("App::PropertyStringList", "Fixtures", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "The Work Coordinate Systems for the Job"))
        obj.OrderOutputBy = ['Fixture', 'Tool', 'Operation']
        obj.Fixtures = ['G54']

        obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
        #obj.setEditorMode("PostProcessorOutputFile", 0)  # set to default mode
        obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors()
        defaultPostProcessor = PathPreferences.defaultPostProcessor()
        # Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed)
        if defaultPostProcessor in postProcessors:
            obj.PostProcessor = defaultPostProcessor
        else:
            obj.PostProcessor = postProcessors[0]
        obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
        obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()

        ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
        if ops.ViewObject:
            ops.ViewObject.Proxy = 0
            ops.ViewObject.Visibility = False

        obj.Operations = ops
        obj.setEditorMode('Operations', 2) # hide
        obj.setEditorMode('Placement', 2)

        self.setupSetupSheet(obj)
        self.setupBaseModel(obj, models)

        obj.Proxy = self

        self.setFromTemplateFile(obj, templateFile)
        if not obj.Stock:
            stockTemplate = PathPreferences.defaultStockTemplate()
            if stockTemplate:
                obj.Stock = PathStock.CreateFromTemplate(obj, json.loads(stockTemplate))
            if not obj.Stock:
                obj.Stock = PathStock.CreateFromBase(obj)
        if obj.Stock.ViewObject:
            obj.Stock.ViewObject.Visibility = False
Exemplo n.º 6
0
 def initOperation(self, obj):
     '''initOperation(obj) ... create vcarve specific properties.'''
     obj.addProperty("App::PropertyFloat", "Discretize", "Path",
                     QtCore.QT_TRANSLATE_NOOP("PathVcarve",
                     "The deflection value for discretizing arcs"))
     obj.addProperty("App::PropertyFloat", "Threshold", "Path",
                     QtCore.QT_TRANSLATE_NOOP("PathVcarve",
                     "cutoff for removing colinear segments (degrees). \
                     default=10.0."))
     obj.addProperty("App::PropertyFloat", "Tolerance", "Path",
             QtCore.QT_TRANSLATE_NOOP("PathVcarve", ""))
     obj.Threshold = 10.0
     obj.Discretize = 0.01
     obj.Tolerance = PathPreferences.defaultGeometryTolerance()
     self.setupAdditionalProperties(obj)
Exemplo n.º 7
0
    def __init__(self, obj, models, templateFile=None):
        self.obj = obj
        self.tooltip = None
        self.tooltipArgs = None
        obj.Proxy = self

        obj.addProperty(
            "App::PropertyFile",
            "PostProcessorOutputFile",
            "Output",
            QT_TRANSLATE_NOOP("App::Property",
                              "The NC output file for this project"),
        )
        obj.addProperty(
            "App::PropertyEnumeration",
            "PostProcessor",
            "Output",
            QT_TRANSLATE_NOOP("App::Property", "Select the Post Processor"),
        )
        obj.addProperty(
            "App::PropertyString",
            "PostProcessorArgs",
            "Output",
            QT_TRANSLATE_NOOP(
                "App::Property",
                "Arguments for the Post Processor (specific to the script)",
            ),
        )
        obj.addProperty(
            "App::PropertyString",
            "LastPostProcessDate",
            "Output",
            QT_TRANSLATE_NOOP("App::Property",
                              "Last Time the Job was post-processed"),
        )
        obj.setEditorMode("LastPostProcessDate", 2)  # Hide
        obj.addProperty(
            "App::PropertyString",
            "LastPostProcessOutput",
            "Output",
            QT_TRANSLATE_NOOP("App::Property",
                              "Last Time the Job was post-processed"),
        )
        obj.setEditorMode("LastPostProcessOutput", 2)  # Hide

        obj.addProperty(
            "App::PropertyString",
            "Description",
            "Path",
            QT_TRANSLATE_NOOP("App::Property",
                              "An optional description for this job"),
        )
        obj.addProperty(
            "App::PropertyString",
            "CycleTime",
            "Path",
            QT_TRANSLATE_NOOP("App::Property", "Job Cycle Time Estimation"),
        )
        obj.setEditorMode("CycleTime", 1)  # read-only
        obj.addProperty(
            "App::PropertyDistance",
            "GeometryTolerance",
            "Geometry",
            QT_TRANSLATE_NOOP(
                "App::Property",
                "For computing Paths; smaller increases accuracy, but slows down computation",
            ),
        )

        obj.addProperty(
            "App::PropertyLink",
            "Stock",
            "Base",
            QT_TRANSLATE_NOOP("App::Property",
                              "Solid object to be used as stock."),
        )
        obj.addProperty(
            "App::PropertyLink",
            "Operations",
            "Base",
            QT_TRANSLATE_NOOP(
                "App::Property",
                "Compound path of all operations in the order they are processed.",
            ),
        )

        obj.addProperty(
            "App::PropertyEnumeration",
            "JobType",
            "Base",
            QT_TRANSLATE_NOOP("App::Property", "Select the Type of Job"),
        )
        obj.setEditorMode("JobType", 2)  # Hide

        obj.addProperty(
            "App::PropertyBool",
            "SplitOutput",
            "Output",
            QT_TRANSLATE_NOOP("App::Property",
                              "Split output into multiple gcode files"),
        )
        obj.addProperty(
            "App::PropertyEnumeration",
            "OrderOutputBy",
            "WCS",
            QT_TRANSLATE_NOOP("App::Property",
                              "If multiple WCS, order the output this way"),
        )
        obj.addProperty(
            "App::PropertyStringList",
            "Fixtures",
            "WCS",
            QT_TRANSLATE_NOOP("App::Property",
                              "The Work Coordinate Systems for the Job"),
        )

        obj.Fixtures = ["G54"]

        for n in self.propertyEnumerations():
            setattr(obj, n[0], n[1])

        obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
        obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors(
        )
        defaultPostProcessor = PathPreferences.defaultPostProcessor()
        # Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed)
        if defaultPostProcessor in postProcessors:
            obj.PostProcessor = defaultPostProcessor
        else:
            obj.PostProcessor = postProcessors[0]
        obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
        obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()

        self.setupOperations(obj)
        self.setupSetupSheet(obj)
        self.setupBaseModel(obj, models)
        self.setupToolTable(obj)
        self.setFromTemplateFile(obj, templateFile)
        self.setupStock(obj)
Exemplo n.º 8
0
    def __init__(self, obj, base, templateFile=None):
        self.obj = obj
        obj.addProperty(
            "App::PropertyFile", "PostProcessorOutputFile", "Output",
            QtCore.QT_TRANSLATE_NOOP("App::Property",
                                     "The NC output file for this project"))
        obj.addProperty(
            "App::PropertyEnumeration", "PostProcessor", "Output",
            QtCore.QT_TRANSLATE_NOOP("App::Property",
                                     "Select the Post Processor"))
        obj.addProperty(
            "App::PropertyString", "PostProcessorArgs", "Output",
            QtCore.QT_TRANSLATE_NOOP(
                "App::Property",
                "Arguments for the Post Processor (specific to the script)"))

        obj.addProperty(
            "App::PropertyString", "Description", "Path",
            QtCore.QT_TRANSLATE_NOOP("App::Property",
                                     "An optional description for this job"))
        obj.addProperty(
            "App::PropertyDistance", "GeometryTolerance", "Geometry",
            QtCore.QT_TRANSLATE_NOOP(
                "App::Property",
                "For computing Paths; smaller increases accuracy, but slows down computation"
            ))

        obj.addProperty(
            "App::PropertyLink", "Base", "Base",
            QtCore.QT_TRANSLATE_NOOP("PathJob",
                                     "The base object for all operations"))
        obj.addProperty(
            "App::PropertyLink", "Stock", "Base",
            QtCore.QT_TRANSLATE_NOOP("PathJob",
                                     "Solid object to be used as stock."))
        obj.addProperty(
            "App::PropertyLink", "Operations", "Base",
            QtCore.QT_TRANSLATE_NOOP(
                "PathJob",
                "Compound path of all operations in the order they are processed."
            ))
        obj.addProperty(
            "App::PropertyLinkList", "ToolController", "Base",
            QtCore.QT_TRANSLATE_NOOP(
                "PathJob",
                "Collection of tool controllers available for this job."))

        obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
        #obj.setEditorMode("PostProcessorOutputFile", 0)  # set to default mode
        obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors(
        )
        defaultPostProcessor = PathPreferences.defaultPostProcessor()
        # Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed)
        if defaultPostProcessor in postProcessors:
            obj.PostProcessor = defaultPostProcessor
        else:
            obj.PostProcessor = postProcessors[0]
        obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
        obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()

        ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython",
                                               "Operations")
        if ops.ViewObject:
            ops.ViewObject.Proxy = 0
            ops.ViewObject.Visibility = False
        obj.Operations = ops
        obj.setEditorMode('Operations', 2)  # hide
        obj.setEditorMode('Placement', 2)

        self.setupSetupSheet(obj)

        obj.Base = createResourceClone(obj, base, 'Base', 'BaseGeometry')
        obj.Proxy = self

        self.setFromTemplateFile(obj, templateFile)
        if not obj.Stock:
            stockTemplate = PathPreferences.defaultStockTemplate()
            if stockTemplate:
                obj.Stock = PathStock.CreateFromTemplate(
                    obj, json.loads(stockTemplate))
            if not obj.Stock:
                obj.Stock = PathStock.CreateFromBase(obj)
        if obj.Stock.ViewObject:
            obj.Stock.ViewObject.Visibility = False
Exemplo n.º 9
0
    def opExecute(self, obj):
        '''opExecute(obj) ... process surface operation'''
        PathLog.track()

        # OCL must be installed
        try:
            import ocl
        except:
            FreeCAD.Console.PrintError(
                translate("Path_Surface", "This operation requires OpenCamLib to be installed.") + "\n")
            return

        print("StepOver is  " + str(obj.StepOver))
        if obj.StepOver > 100:
            obj.StepOver = 100
        if obj.StepOver < 1:
            obj.StepOver = 1
        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 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:
                import PathScripts.PathPreferences as PathPreferences
                deflection = PathPreferences.defaultGeometryTolerance()
            self.baseobject.Shape.tessellate(0.5)
            mesh = MeshPart.meshFromShape(self.baseobject.Shape, Deflection=deflection)
        if obj.BoundBox == "BaseBoundBox":
            bb = mesh.BoundBox
        else:
            bb = parentJob.Stock.Shape.BoundBox

        s = ocl.STLSurf()
        for f in mesh.Facets:
            p = f.Points[0]
            q = f.Points[1]
            r = f.Points[2]
            # offset the triangle in Z with DepthOffset
            t = ocl.Triangle(ocl.Point(p[0], p[1], p[2] + obj.DepthOffset.Value),
                             ocl.Point(q[0], q[1], q[2] + obj.DepthOffset.Value),
                             ocl.Point(r[0], r[1], r[2] + obj.DepthOffset.Value))
            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)
Exemplo n.º 10
0
    def opExecute(self, obj):
        '''opExecute(obj) ... process surface operation'''
        PathLog.track()

        # OCL must be installed
        try:
            import ocl
        except:
            FreeCAD.Console.PrintError(
                translate(
                    "Path_Surface",
                    "This operation requires OpenCamLib to be installed.") +
                "\n")
            return

        print("StepOver is  " + str(obj.StepOver))
        if obj.StepOver > 100:
            obj.StepOver = 100
        if obj.StepOver < 1:
            obj.StepOver = 1
        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

        for base in self.model:
            print("base object: " + base.Name)

            if base.TypeId.startswith('Mesh'):
                mesh = base.Mesh
            else:
                # try/except is for Path Jobs created before GeometryTolerance
                try:
                    deflection = parentJob.GeometryTolerance
                except AttributeError:
                    import PathScripts.PathPreferences as PathPreferences
                    deflection = PathPreferences.defaultGeometryTolerance()
                base.Shape.tessellate(0.5)
                mesh = MeshPart.meshFromShape(base.Shape,
                                              Deflection=deflection)
            if obj.BoundBox == "BaseBoundBox":
                bb = mesh.BoundBox
            else:
                bb = parentJob.Stock.Shape.BoundBox

            s = ocl.STLSurf()
            for f in mesh.Facets:
                p = f.Points[0]
                q = f.Points[1]
                r = f.Points[2]
                # offset the triangle in Z with DepthOffset
                t = ocl.Triangle(
                    ocl.Point(p[0], p[1], p[2] + obj.DepthOffset.Value),
                    ocl.Point(q[0], q[1], q[2] + obj.DepthOffset.Value),
                    ocl.Point(r[0], r[1], r[2] + obj.DepthOffset.Value))
                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)