コード例 #1
0
ファイル: PathContour.py プロジェクト: FreeCAD/FreeCAD
    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
コード例 #2
0
ファイル: PathUtils.py プロジェクト: zhoucantong/FreeCAD
def horizontalFaceLoop(obj, face, faceList=None):
    '''horizontalFaceLoop(obj, face, faceList=None) ... returns a list of face names which form the walls of a vertical hole face is a part of.
    All face names listed in faceList must be part of the hole for the solution to be returned.'''

    wires = [horizontalEdgeLoop(obj, e) for e in face.Edges]
    # Not sure if sorting by Area is a premature optimization - but it seems
    # the loop we're looking for is typically the biggest of the them all.
    wires = sorted([w for w in wires if w], key=lambda w: Part.Face(w).Area)

    for wire in wires:
        hashes = [e.hashCode() for e in wire.Edges]

        # find all faces that share a an edge with the wire and are vertical
        faces = [
            "Face%d" % (i + 1) for i, f in enumerate(obj.Shape.Faces)
            if any(e.hashCode() in hashes
                   for e in f.Edges) and PathGeom.isVertical(f)
        ]

        if faceList and not all(f in faces for f in faceList):
            continue

        # verify they form a valid hole by getting the outline and comparing
        # the resulting XY footprint with that of the faces
        comp = Part.makeCompound([obj.Shape.getElement(f) for f in faces])
        outline = TechDraw.findShapeOutline(comp, 1, FreeCAD.Vector(0, 0, 1))

        # findShapeOutline always returns closed wires, by removing the
        # trace-backs single edge spikes don't contriubte to the bound box
        uniqueEdges = []
        for edge in outline.Edges:
            if any(PathGeom.edgesMatch(edge, e) for e in uniqueEdges):
                continue
            uniqueEdges.append(edge)
        w = Part.Wire(uniqueEdges)

        # if the faces really form the walls of a hole then the resulting
        # wire is still closed and it still has the same footprint
        bb1 = comp.BoundBox
        bb2 = w.BoundBox
        if w.isClosed() and PathGeom.isRoughly(
                bb1.XMin, bb2.XMin) and PathGeom.isRoughly(
                    bb1.XMax, bb2.XMax) and PathGeom.isRoughly(
                        bb1.YMin, bb2.YMin) and PathGeom.isRoughly(
                            bb1.YMax, bb2.YMax):
            return faces
    return None
コード例 #3
0
ファイル: PathUtils.py プロジェクト: zhangli1049/FreeCAD
def horizontalFaceLoop(obj, face, faceList=None):
    '''horizontalFaceLoop(obj, face, faceList=None) ... returns a list of face names which form the walls of a vertical hole face is a part of.
    All face names listed in faceList must be part of the hole for the solution to be returned.'''

    wires = [horizontalEdgeLoop(obj, e) for e in face.Edges]
    # Not sure if sorting by Area is a premature optimization - but it seems
    # the loop we're looking for is typically the biggest of the them all.
    wires = sorted([w for w in wires if w], key=lambda w: Part.Face(w).Area)

    for wire in wires:
        hashes = [e.hashCode() for e in wire.Edges]

        #find all faces that share a an edge with the wire and are vertical
        faces = ["Face%d"%(i+1) for i,f in enumerate(obj.Shape.Faces) if any(e.hashCode() in hashes for e in f.Edges) and PathGeom.isVertical(f)]

        if faceList and not all(f in faces for f in faceList):
            continue

        # verify they form a valid hole by getting the outline and comparing
        # the resulting XY footprint with that of the faces
        comp = Part.makeCompound([obj.Shape.getElement(f) for f in faces])
        outline = TechDraw.findShapeOutline(comp, 1, FreeCAD.Vector(0,0,1))

        # findShapeOutline always returns closed wires, by removing the
        # trace-backs single edge spikes don't contriubte to the bound box
        uniqueEdges = []
        for edge in outline.Edges:
            if any(PathGeom.edgesMatch(edge, e) for e in uniqueEdges):
                continue
            uniqueEdges.append(edge)
        w = Part.Wire(uniqueEdges)

        # if the faces really form the walls of a hole then the resulting
        # wire is still closed and it still has the same footprint
        bb1 = comp.BoundBox
        bb2 = w.BoundBox
        if w.isClosed() and PathGeom.isRoughly(bb1.XMin, bb2.XMin) and PathGeom.isRoughly(bb1.XMax, bb2.XMax) and PathGeom.isRoughly(bb1.YMin, bb2.YMin) and PathGeom.isRoughly(bb1.YMax, bb2.YMax):
            return faces
    return None
コード例 #4
0
ファイル: PathPocketShape.py プロジェクト: sujaymc88/FreeCAD
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()

        if obj.Base:
            PathLog.debug("base items exist.  Processing...")
            self.removalshapes = []
            self.horiz = []
            vertical = []
            for o in obj.Base:
                PathLog.debug("Base item: {}".format(o))
                base = o[0]
                for sub in o[1]:
                    if "Face" in sub:
                        face = base.Shape.getElement(sub)
                        if type(face.Surface) == Part.Plane and PathGeom.isVertical(face.Surface.Axis):
                            # it's a flat horizontal face
                            self.horiz.append(face)
                        elif type(face.Surface) == Part.Cylinder and PathGeom.isVertical(face.Surface.Axis):
                            # vertical cylinder wall
                            if any(e.isClosed() for e in face.Edges):
                                # complete cylinder
                                circle = Part.makeCircle(face.Surface.Radius, face.Surface.Center)
                                disk = Part.Face(Part.Wire(circle))
                                self.horiz.append(disk)
                            else:
                                # partial cylinder wall
                                vertical.append(face)
                        elif type(face.Surface) == Part.Plane and PathGeom.isHorizontal(face.Surface.Axis):
                            vertical.append(face)
                        else:
                            PathLog.error(translate('PathPocket', "Pocket does not support shape %s.%s") % (base.Label, sub))

            self.vertical = PathGeom.combineConnectedShapes(vertical)
            self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical]
            for wire in self.vWires:
                w = PathGeom.removeDuplicateEdges(wire)
                face = Part.Face(w)
                face.tessellate(0.1)
                if PathGeom.isRoughly(face.Area, 0):
                    PathLog.error(translate('PathPocket', 'Vertical faces do not form a loop - ignoring'))
                else:
                    self.horiz.append(face)


            # move all horizontal faces to FinalDepth
            for f in self.horiz:
                f.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - f.BoundBox.ZMin))

            # check all faces and see if they are touching/overlapping and combine those into a compound
            self.horizontal = []
            for shape in PathGeom.combineConnectedShapes(self.horiz):
                shape.sewShape()
                shape.tessellate(0.1)
                if obj.UseOutline:
                    wire = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1))
                    wire.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - wire.BoundBox.ZMin))
                    self.horizontal.append(Part.Face(wire))
                else:
                    self.horizontal.append(shape)

            # extrude all faces up to StartDepth and those are the removal shapes
            extent = FreeCAD.Vector(0, 0, obj.StartDepth.Value - obj.FinalDepth.Value)
            self.removalshapes = [(face.extrude(extent), False) for face in self.horizontal]

        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")
            self.outline = Part.Face(TechDraw.findShapeOutline(self.baseobject.Shape, 1, FreeCAD.Vector(0, 0, 1)))
            stockBB = self.stock.Shape.BoundBox

            self.outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
            self.body  = self.outline.extrude(FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
            self.removalshapes = [(self.stock.Shape.cut(self.body), False)]

        for (shape,hole) in self.removalshapes:
            shape.tessellate(0.1)

        if self.removalshapes:
            obj.removalshape = self.removalshapes[0][0]
        return self.removalshapes
コード例 #5
0
ファイル: PathProfile.py プロジェクト: crobarcro/FreeCAD
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        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

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

        if obj.Base:
            holes = []
            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)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print ("found a base object which is not a face.  Can't continue.")
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1, Vector(0, 0, 1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        else:  #Try to build targets frorm the job base
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return

            if hasattr(baseobject, "Proxy"):
                if isinstance(baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                    if obj.processPerimeter:
                        shapes = baseobject.Proxy.getOutlines(baseobject, transform=True)
                        for shape in shapes:
                            for wire in shape.Wires:
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                PathLog.debug("Processing panel perimeter.  edges found: {}".format(len(edgelist)))
                            try:
                                output += self._buildPathLibarea(obj, edgelist, isHole=False)
                            except:
                                FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")

                    shapes = baseobject.Proxy.getHoles(baseobject, transform=True)
                    for shape in shapes:
                        for wire in shape.Wires:
                            drillable = PathUtils.isDrillable(baseobject.Proxy, wire)
                            if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                try:
                                    output += self._buildPathLibarea(obj, edgelist, isHole=True)
                                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
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
コード例 #6
0
    def execute(self, obj):

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

        #Tool may have changed.  Refresh data
        toolLoad = PathUtils.getLastToolLoad(obj)
        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horiRrapid = 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 tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter / 2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        #Build preliminary comments
        output = ""
        output += "(" + obj.Label + ")"

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        #Facing is done either against base objects
        if 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:
                        print('falling out')
                        return
            planeshape = Part.makeCompound(faces)

        #If no base object, do planing of top surface of entire model
        else:
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return
            planeshape = baseobject.Shape

        #if user wants the boundbox, calculate that
        if obj.BoundaryShape == 'Boundbox':
            bb = planeshape.BoundBox
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1,
                                   Vector(bb.XMin, bb.YMin, bb.ZMin),
                                   Vector(0, 0, 1))
            contourwire = TechDraw.findShapeOutline(bbperim, 1,
                                                    Vector(0, 0, 1))
        else:
            contourwire = TechDraw.findShapeOutline(planeshape, 1,
                                                    Vector(0, 0, 1))

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)

        #use libarea to build the pattern
        a = area.Area()
        c = PathScripts.PathKurveUtils.makeAreaCurve(edgelist, 'CW')
        a.append(c)
        a.Reorder()
        output += self.buildpathlibarea(obj, a)

        path = Path.Path(output)
        obj.Path = path
        obj.ViewObject.Visibility = True
コード例 #7
0
ファイル: PathProfile.py プロジェクト: eivindkv/FreeCAD2
    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 tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

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

        if obj.Base:
            holes = []
            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)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print ("found a base object which is not a face.  Can't continue.")
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1, Vector(0,0,1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
コード例 #8
0
ファイル: PathProfile.py プロジェクト: FreeCAD/FreeCAD
    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 tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

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

        if obj.Base:
            holes = []
            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)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print ("found a base object which is not a face.  Can't continue.")
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1, Vector(0,0,1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        if obj.Active:
            path = Path.Path(output)
            obj.Path = path
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
コード例 #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
コード例 #10
0
    def execute(self, obj):
        import Part  # math #DraftGeomUtils
        output = ""

        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

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

        if obj.Base:
            holes = []
            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)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z),
                                         1):  # horizontal face
                            holes += shape.Wires[1:]

                    else:
                        print(
                            "found a base object which is not a face.  Can't continue."
                        )
                        return
            profileshape = Part.makeCompound(faces)
            profilewire = TechDraw.findShapeOutline(profileshape, 1,
                                                    Vector(0, 0, 1))

            if obj.processHoles:
                for wire in holes:
                    edgelist = wire.Edges
                    edgelist = Part.__sortEdges__(edgelist)
                    output += self._buildPathLibarea(obj, edgelist, True)

            if obj.processPerimeter:
                edgelist = profilewire.Edges
                edgelist = Part.__sortEdges__(edgelist)
                output += self._buildPathLibarea(obj, edgelist, False)

        else:  #Try to build targets frorm the job base
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return

            if hasattr(baseobject, "Proxy"):
                if isinstance(baseobject.Proxy,
                              ArchPanel.PanelSheet):  # process the sheet
                    if obj.processPerimeter:
                        shapes = baseobject.Proxy.getOutlines(baseobject,
                                                              transform=True)
                        for shape in shapes:
                            for wire in shape.Wires:
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                PathLog.debug(
                                    "Processing panel perimeter.  edges found: {}"
                                    .format(len(edgelist)))
                            try:
                                output += self._buildPathLibarea(obj,
                                                                 edgelist,
                                                                 isHole=False)
                            except:
                                FreeCAD.Console.PrintError(
                                    "Something unexpected happened. Unable to generate a contour path. Check project and tool config."
                                )

                    shapes = baseobject.Proxy.getHoles(baseobject,
                                                       transform=True)
                    for shape in shapes:
                        for wire in shape.Wires:
                            drillable = PathUtils.isDrillable(
                                baseobject.Proxy, wire)
                            if (drillable and obj.processCircles) or (
                                    not drillable and obj.processHoles):
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                try:
                                    output += self._buildPathLibarea(
                                        obj, edgelist, isHole=True)
                                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
            obj.ViewObject.Visibility = True

        else:
            path = Path.Path("(inactive operation)")
            obj.Path = path
            obj.ViewObject.Visibility = False
コード例 #11
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()

        if obj.Base:
            PathLog.debug("base items exist.  Processing...")
            self.removalshapes = []
            self.horiz = []
            vertical = []
            for o in obj.Base:
                PathLog.debug("Base item: {}".format(o))
                base = o[0]
                for sub in o[1]:
                    if "Face" in sub:
                        face = base.Shape.getElement(sub)
                        if type(face.Surface) == Part.Plane and PathGeom.isVertical(face.Surface.Axis):
                            # it's a flat horizontal face
                            self.horiz.append(face)
                        elif type(face.Surface) == Part.Cylinder and PathGeom.isVertical(face.Surface.Axis):
                            # vertical cylinder wall
                            if any(e.isClosed() for e in face.Edges):
                                # complete cylinder
                                circle = Part.makeCircle(face.Surface.Radius, face.Surface.Center)
                                disk = Part.Face(Part.Wire(circle))
                                self.horiz.append(disk)
                            else:
                                # partial cylinder wall
                                vertical.append(face)
                        elif type(face.Surface) == Part.Plane and PathGeom.isHorizontal(face.Surface.Axis):
                            vertical.append(face)
                        else:
                            PathLog.error(translate('PathPocket', "Pocket does not support shape %s.%s") % (base.Label, sub))

            self.vertical = PathGeom.combineConnectedShapes(vertical)
            self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical]
            for wire in self.vWires:
                w = PathGeom.removeDuplicateEdges(wire)
                face = Part.Face(w)
                face.tessellate(0.1)
                if PathGeom.isRoughly(face.Area, 0):
                    PathLog.error(translate('PathPocket', 'Vertical faces do not form a loop - ignoring'))
                else:
                    self.horiz.append(face)


            # move all horizontal faces to FinalDepth
            for f in self.horiz:
                f.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - f.BoundBox.ZMin))

            # check all faces and see if they are touching/overlapping and combine those into a compound
            self.horizontal = []
            for shape in PathGeom.combineConnectedShapes(self.horiz):
                shape.sewShape()
                shape.tessellate(0.1)
                if obj.UseOutline:
                    wire = TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1))
                    wire.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - wire.BoundBox.ZMin))
                    self.horizontal.append(Part.Face(wire))
                else:
                    self.horizontal.append(shape)

            # extrude all faces up to StartDepth and those are the removal shapes
            extent = FreeCAD.Vector(0, 0, obj.StartDepth.Value - obj.FinalDepth.Value)
            self.removalshapes = [(face.extrude(extent), False) for face in self.horizontal]

        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")
            self.outlines = [Part.Face(TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1))) for base in self.model]
            stockBB = self.stock.Shape.BoundBox

            self.removalshapes = []
            self.bodies = []
            for outline in self.outlines:
                outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
                body = outline.extrude(FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
                self.bodies.append(body)
                self.removalshapes.append((self.stock.Shape.cut(body), False))

        for (shape,hole) in self.removalshapes:
            shape.tessellate(0.1)

        if self.removalshapes:
            obj.removalshape = self.removalshapes[0][0]
        return self.removalshapes
コード例 #12
0
ファイル: PathContour.py プロジェクト: mumme74/FreeCAD-path
    def execute(self, obj):
        PathLog.track()
        import Part  # math #DraftGeomUtils
        output = ""

        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) #PathUtils.getTool(obj, toolLoad.ToolNumber)
            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

                #self.radius = 0.25
            else:
                self.radius = tool.Diameter/2

        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

        if hasattr(baseobject, "Proxy"):
            if isinstance(baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                baseobject.Proxy.execute(baseobject)
                for subobj in baseobject.Group:  # process the group of panels
                    if isinstance(subobj.Proxy, ArchPanel.PanelCut):
                        shapes = baseobject.Proxy.getOutlines(baseobject, transform=True)
                        for shape in shapes:
                            for wire in shape.Wires:
                                edgelist = wire.Edges
                                edgelist = Part.__sortEdges__(edgelist)
                                PathLog.debug("Processing panel perimeter.  edges found: {}".format(len(edgelist)))                       # subobj.Proxy.execute(subobj)
                            try:
                                output += self._buildPathLibarea(obj, edgelist)
                            except:
                                FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
        else:
            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
コード例 #13
0
ファイル: PathMillFace.py プロジェクト: mumme74/FreeCAD-path
    def execute(self, obj):
        PathLog.track()
        output = ""

        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 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

        # Build preliminary comments
        output = ""
        output += "(" + obj.Label + ")"

        # 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.info("Working on a collection of faces {}".format(faces))

        # If no base object, do planing of top surface of entire model
        else:
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                PathLog.debug("No base object. No parent job found")
                return
            baseobject = parentJob.Base
            if baseobject is None:
                PathLog.debug("Parent job exists but no Base Object")
                return
            planeshape = baseobject.Shape
            PathLog.info("Working on a shape {}".format(baseobject.Name))

        # if user wants the boundbox, calculate that
        PathLog.info("Boundary Shape: {}".format(obj.BoundaryShape))
        if obj.BoundaryShape == 'Boundbox':
            bb = planeshape.BoundBox
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, Vector(bb.XMin, bb.YMin, bb.ZMin), Vector(0, 0, 1))
            contourwire = TechDraw.findShapeOutline(bbperim, 1, Vector(0, 0, 1))
        else:
            contourwire = TechDraw.findShapeOutline(planeshape, 1, Vector(0, 0, 1))

        # pocket = Path.Area(PocketMode=4,SectionCount=-1,SectionMode=1,Stepdown=0.499)
        # pocket.setParams(PocketExtraOffset = obj.PassExtension.Value, ToolRadius = self.radius)
        # pocket.add(planeshape, op=1)
        # #Part.show(contourwire)
        # path = Path.fromShapes(pocket.getShape())

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)

        # use libarea to build the pattern
        a = area.Area()
        c = PathScripts.PathKurveUtils.makeAreaCurve(edgelist, 'CW')
        PathLog.debug(c.text())
        a.append(c)
        a.Reorder()
        output += self.buildpathlibarea(obj, a)

        path = Path.Path(output)
        if len(path.Commands) == 0:
            FreeCAD.Console.PrintMessage(translate("PathMillFace", "The selected settings did not produce a valid path.\n"))

        obj.Path = path
        obj.ViewObject.Visibility = True
コード例 #14
0
ファイル: PathMillFace.py プロジェクト: sliptonic/FreeCAD
    def execute(self, obj):

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

        #Tool may have changed.  Refresh data
        toolLoad = PathUtils.getLastToolLoad(obj)
        if toolLoad is None or toolLoad.ToolNumber == 0:
            self.vertFeed = 100
            self.horizFeed = 100
            self.vertRapid = 100
            self.horiRrapid = 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 tool.Diameter == 0:
                self.radius = 0.25
            else:
                self.radius = tool.Diameter/2
            obj.ToolNumber = toolLoad.ToolNumber
            obj.ToolDescription = toolLoad.Name

        #Build preliminary comments
        output = ""
        output += "(" + obj.Label + ")"

        if obj.UserLabel == "":
            obj.Label = obj.Name + " :" + obj.ToolDescription
        else:
            obj.Label = obj.UserLabel + " :" + obj.ToolDescription

        #Facing is done either against base objects
        if 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:
                        print ('falling out')
                        return
            planeshape = Part.makeCompound(faces)

        #If no base object, do planing of top surface of entire model
        else:
            parentJob = PathUtils.findParentJob(obj)
            if parentJob is None:
                return
            baseobject = parentJob.Base
            if baseobject is None:
                return
            planeshape = baseobject.Shape

        #if user wants the boundbox, calculate that
        if obj.BoundaryShape == 'Boundbox':
            bb = planeshape.BoundBox
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, Vector(bb.XMin, bb.YMin, bb.ZMin), Vector(0,0,1))
            contourwire = TechDraw.findShapeOutline(bbperim, 1, Vector(0,0,1))
        else:
            contourwire = TechDraw.findShapeOutline(planeshape, 1, Vector(0,0,1))

        edgelist = contourwire.Edges
        edgelist = Part.__sortEdges__(edgelist)

        #use libarea to build the pattern
        a = area.Area()
        c = PathScripts.PathKurveUtils.makeAreaCurve(edgelist, 'CW')
        a.append(c)
        a.Reorder()
        output += self.buildpathlibarea(obj, a)

        path = Path.Path(output)
        obj.Path = path
        obj.ViewObject.Visibility = True
コード例 #15
0
ファイル: PathPocketShape.py プロジェクト: sticwin/FreeCAD
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()
        PathLog.debug("areaOpShapes() in PathPocketShape.py")

        def judgeFinalDepth(obj, fD):
            if obj.FinalDepth.Value >= fD:
                return obj.FinalDepth.Value
            else:
                return fD

        def judgeStartDepth(obj, sD):
            if obj.StartDepth.Value >= sD:
                return obj.StartDepth.Value
            else:
                return sD

        def analyzeVerticalFaces(self, obj, vertTuples):
            hT = []
            # base = FreeCAD.ActiveDocument.getObject(self.modelName)

            # Separate elements, regroup by orientation (axis_angle combination)
            vTags = ['X34.2']
            vGrps = [[(2.3, 3.4, 'X')]]
            for tup in vertTuples:
                (face, sub, angle, axis, tag, strDep, finDep, trans) = tup
                if tag in vTags:
                    # Determine index of found string
                    i = 0
                    for orn in vTags:
                        if orn == tag:
                            break
                        i += 1
                    vGrps[i].append(tup)
                else:
                    vTags.append(tag)  # add orientation entry
                    vGrps.append([tup])  # add orientation entry
            # Remove temp elements
            vTags.pop(0)
            vGrps.pop(0)

            # check all faces in each axis_angle group
            shpList = []
            zmaxH = 0.0
            for o in range(0, len(vTags)):
                shpList = []
                zmaxH = vGrps[o][0].BoundBox.ZMax
                for (face, sub, angle, axis, tag, strDep, finDep,
                     trans) in vGrps[o]:
                    shpList.append(face)
                    # Identify tallest face to use as zMax
                    if face.BoundBox.ZMax > zmaxH:
                        zmaxH = face.BoundBox.ZMax
                # check all faces and see if they are touching/overlapping and combine those into a compound
                # Original Code in For loop
                self.vertical = PathGeom.combineConnectedShapes(shpList)
                self.vWires = [
                    TechDraw.findShapeOutline(shape, 1,
                                              FreeCAD.Vector(0, 0, 1))
                    for shape in self.vertical
                ]
                for wire in self.vWires:
                    w = PathGeom.removeDuplicateEdges(wire)
                    face = Part.Face(w)
                    face.tessellate(0.05)
                    if PathGeom.isRoughly(face.Area, 0):
                        PathLog.error(
                            translate(
                                'PathPocket',
                                'Vertical faces do not form a loop - ignoring')
                        )
                    else:
                        strDep = zmaxH + self.leadIn  # base.Shape.BoundBox.ZMax
                        finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                        tup = face, sub, angle, axis, tag, strDep, finDep, trans
                        hT.append(tup)
            # Eol
            return hT

        if obj.Base:
            PathLog.debug('base items exist.  Processing...')
            self.removalshapes = []
            self.horiz = []
            vertical = []
            horizTuples = []
            vertTuples = []
            axis = 'X'
            angle = 0.0
            reset = False
            resetPlacement = None
            trans = FreeCAD.Vector(0.0, 0.0, 0.0)

            for o in obj.Base:
                PathLog.debug('Base item: {}'.format(o))
                base = o[0]

                # Limit sub faces to children of single Model object.
                if self.modelName is None:
                    self.modelName = base.Name
                else:
                    if base.Name != self.modelName:
                        for sub in o[1]:
                            PathLog.error(sub +
                                          " is not a part of Model object: " +
                                          self.modelName)
                        o[1] = []
                        PathLog.error(
                            "Only processing faces on a single Model object per operation."
                        )
                        PathLog.error(
                            "You will need to separate faces per Model object within the Job."
                        )

                startBase = FreeCAD.Vector(base.Placement.Base.x,
                                           base.Placement.Base.y,
                                           base.Placement.Base.z)
                startAngle = base.Placement.Rotation.Angle
                startAxis = base.Placement.Rotation.Axis
                startRotation = FreeCAD.Rotation(startAxis, startAngle)
                resetPlacement = FreeCAD.Placement(startBase, startRotation)
                for sub in o[1]:
                    if 'Face' in sub:
                        PathLog.debug('sub: {}'.format(sub))
                        # Determine angle of rotation needed to make normal vector = (0,0,1)
                        strDep = obj.StartDepth.Value
                        finDep = obj.FinalDepth.Value
                        trans = FreeCAD.Vector(0.0, 0.0, 0.0)
                        rtn = False

                        if obj.UseRotation != 'Off':
                            (rtn, angle,
                             axis) = self.pocketRotationAnalysis(obj,
                                                                 base,
                                                                 sub,
                                                                 prnt=True)

                        if rtn is True:
                            reset = True
                            PathLog.debug(
                                str(sub) +
                                ": rotating model to make face normal at (0,0,1) ..."
                            )
                            if axis == 'X':
                                bX = 0.0
                                bY = 0.0
                                bZ = math.sin(math.radians(
                                    angle)) * base.Placement.Base.y
                                vect = FreeCAD.Vector(1, 0, 0)
                            elif axis == 'Y':
                                bX = 0.0
                                bY = 0.0
                                bZ = math.sin(math.radians(
                                    angle)) * base.Placement.Base.x
                                if obj.B_AxisErrorOverride is True:
                                    bZ = -1 * bZ
                                vect = FreeCAD.Vector(0, 1, 0)
                            # Rotate base to such that Surface.Axis of pocket bottom is Z=1
                            base.Placement.Rotation = FreeCAD.Rotation(
                                vect, angle)
                            base.recompute()
                            trans = FreeCAD.Vector(bX, bY, bZ)
                        else:
                            axis = 'X'
                            angle = 0.0
                        tag = axis + str(round(angle, 7))
                        face = base.Shape.getElement(sub)

                        if type(face.Surface
                                ) == Part.Plane and PathGeom.isVertical(
                                    face.Surface.Axis):
                            # it's a flat horizontal face
                            PathLog.debug(" == Part.Plane: isVertical")
                            # Adjust start and finish depths for pocket
                            strDep = base.Shape.BoundBox.ZMax + self.leadIn
                            finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                            # Over-write default final depth value, leaves manual override by user
                            obj.StartDepth.Value = trans.z + strDep
                            obj.FinalDepth.Value = trans.z + finDep

                            tup = face, sub, angle, axis, tag, strDep, finDep, trans
                            horizTuples.append(tup)
                        elif type(face.Surface
                                  ) == Part.Cylinder and PathGeom.isVertical(
                                      face.Surface.Axis):
                            PathLog.debug("== Part.Cylinder")
                            # vertical cylinder wall
                            if any(e.isClosed() for e in face.Edges):
                                PathLog.debug("e.isClosed()")
                                # complete cylinder
                                circle = Part.makeCircle(
                                    face.Surface.Radius, face.Surface.Center)
                                disk = Part.Face(Part.Wire(circle))

                                # Adjust start and finish depths for pocket
                                strDep = face.BoundBox.ZMax + self.leadIn  # base.Shape.BoundBox.ZMax + self.leadIn
                                finDep = judgeFinalDepth(
                                    obj, face.BoundBox.ZMin)
                                # Over-write default final depth value, leaves manual override by user
                                obj.StartDepth.Value = trans.z + strDep
                                obj.FinalDepth.Value = trans.z + finDep

                                tup = disk, sub, angle, axis, tag, strDep, finDep, trans
                                horizTuples.append(tup)
                            else:
                                # partial cylinder wall
                                vertical.append(face)

                                # Adjust start and finish depths for pocket
                                strDep = face.BoundBox.ZMax + self.leadIn  # base.Shape.BoundBox.ZMax + self.leadIn
                                finDep = judgeFinalDepth(
                                    obj, face.BoundBox.ZMin)
                                # Over-write default final depth value, leaves manual override by user
                                obj.StartDepth.Value = trans.z + strDep
                                obj.FinalDepth.Value = trans.z + finDep
                                tup = face, sub, angle, axis, tag, strDep, finDep, trans
                                vertTuples.append(tup)

                                PathLog.debug(sub +
                                              "is vertical after rotation.")
                        elif type(face.Surface
                                  ) == Part.Plane and PathGeom.isHorizontal(
                                      face.Surface.Axis):
                            vertical.append(face)

                            # Adjust start and finish depths for pocket
                            strDep = face.BoundBox.ZMax + self.leadIn  # base.Shape.BoundBox.ZMax + self.leadIn
                            finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                            # Over-write default final depth value, leaves manual override by user
                            obj.StartDepth.Value = trans.z + strDep
                            obj.FinalDepth.Value = trans.z + finDep
                            tup = face, sub, angle, axis, tag, strDep, finDep, trans
                            vertTuples.append(tup)
                            PathLog.debug(sub + "is vertical after rotation.")
                        else:
                            PathLog.error(
                                translate(
                                    'PathPocket',
                                    'Pocket does not support shape %s.%s') %
                                (base.Label, sub))

                        if reset is True:
                            base.Placement.Rotation = startRotation
                            base.recompute()
                            reset = False
                    # End IF
                # End FOR
                base.Placement = resetPlacement
                base.recompute()
            # End FOR

            # Analyze vertical faces via PathGeom.combineConnectedShapes()
            # hT = analyzeVerticalFaces(self, obj, vertTuples)
            # horizTuples.extend(hT)

            # This section will be replaced analyzeVerticalFaces(self, obj, vertTuples) above
            self.vertical = PathGeom.combineConnectedShapes(vertical)
            self.vWires = [
                TechDraw.findShapeOutline(shape, 1,
                                          FreeCAD.Vector(0.0, 0.0, 1.0))
                for shape in self.vertical
            ]
            for wire in self.vWires:
                w = PathGeom.removeDuplicateEdges(wire)
                face = Part.Face(w)
                face.tessellate(0.05)
                if PathGeom.isRoughly(face.Area, 0):
                    PathLog.error(
                        translate(
                            'PathPocket',
                            'Vertical faces do not form a loop - ignoring'))
                else:
                    # self.horiz.append(face)
                    strDep = base.Shape.BoundBox.ZMax + self.leadIn
                    finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                    tup = face, 'vertFace', 0.0, 'X', 'X0.0', strDep, finDep, FreeCAD.Vector(
                        0.0, 0.0, 0.0)
                    horizTuples.append(tup)

            # add faces for extensions
            self.exts = []
            for ext in self.getExtensions(obj):
                wire = Part.Face(ext.getWire())
                if wire:
                    face = Part.Face(wire)
                    # self.horiz.append(face)
                    strDep = base.Shape.BoundBox.ZMax + self.leadIn
                    finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                    tup = face, 'vertFace', 0.0, 'X', 'X0.0', strDep, finDep, FreeCAD.Vector(
                        0.0, 0.0, 0.0)
                    horizTuples.append(tup)
                    self.exts.append(face)

            # move all horizontal faces to FinalDepth
            for (face, sub, angle, axis, tag, strDep, finDep,
                 trans) in horizTuples:
                # face.translate(FreeCAD.Vector(0, 0, obj.FinalDepth.Value - face.BoundBox.ZMin))
                if angle <= 0.0:
                    if axis == 'X':
                        face.translate(
                            FreeCAD.Vector(
                                0, trans.z,
                                trans.z + finDep - face.BoundBox.ZMin))
                    elif axis == 'Y':
                        face.translate(
                            FreeCAD.Vector(
                                -1 * trans.z, 0,
                                trans.z + finDep - face.BoundBox.ZMin))
                else:
                    if axis == 'X':
                        face.translate(
                            FreeCAD.Vector(
                                0, -1 * trans.z,
                                trans.z + finDep - face.BoundBox.ZMin))
                    elif axis == 'Y':
                        face.translate(
                            FreeCAD.Vector(
                                trans.z, 0,
                                trans.z + finDep - face.BoundBox.ZMin))

            # Separate elements, regroup by orientation (axis_angle combination)
            hTags = ['X34.2']
            hGrps = [[(2.3, 3.4, 'X')]]
            for tup in horizTuples:
                (face, sub, angle, axis, tag, strDep, finDep, trans) = tup
                if tag in hTags:
                    # Determine index of found string
                    i = 0
                    for orn in hTags:
                        if orn == tag:
                            break
                        i += 1
                    hGrps[i].append(tup)
                else:
                    hTags.append(tag)  # add orientation entry
                    hGrps.append([tup])  # add orientation entry
            # Remove temp elements
            hTags.pop(0)
            hGrps.pop(0)

            # check all faces in each axis_angle group
            self.horizontal = []
            shpList = []
            for o in range(0, len(hTags)):
                PathLog.debug('hTag: {}'.format(hTags[o]))
                shpList = []
                for (face, sub, angle, axis, tag, strDep, finDep,
                     trans) in hGrps[o]:
                    shpList.append(face)
                # check all faces and see if they are touching/overlapping and combine those into a compound
                # Original Code in For loop
                for shape in PathGeom.combineConnectedShapes(shpList):
                    shape.sewShape()
                    # shape.tessellate(0.05) # Russ4262 0.1 original
                    if obj.UseOutline:
                        wire = TechDraw.findShapeOutline(
                            shape, 1, FreeCAD.Vector(0, 0, 1))
                        wire.translate(
                            FreeCAD.Vector(
                                0, 0,
                                obj.FinalDepth.Value - wire.BoundBox.ZMin))
                        PathLog.debug(
                            " -obj.UseOutline: obj.FinalDepth.Value" +
                            str(obj.FinalDepth.Value))
                        PathLog.debug(" -obj.UseOutline: wire.BoundBox.ZMin" +
                                      str(wire.BoundBox.ZMin))
                        # shape.tessellate(0.05) # Russ4262 0.1 original
                        face = Part.Face(wire)
                        tup = face, sub, angle, axis, tag, strDep, finDep, trans
                        self.horizontal.append(tup)
                    else:
                        # Re-pair shape to tuple set
                        for (face, sub, angle, axis, tag, strDep, finDep,
                             trans) in hGrps[o]:
                            if shape is face:
                                tup = face, sub, angle, axis, tag, strDep, finDep, trans
                                self.horizontal.append(tup)
                                break
            # Eol

            # extrude all faces up to StartDepth and those are the removal shapes
            for (face, sub, angle, axis, tag, strDep, finDep,
                 trans) in self.horizontal:
                # extent = FreeCAD.Vector(0, 0, obj.StartDepth.Value - obj.FinalDepth.Value)
                extent = FreeCAD.Vector(0, 0, strDep - finDep)
                shp = face.removeSplitter().extrude(extent)
                # tup = shp, False, sub, angle, axis, tag, strDep, finDep, trans
                tup = shp, False, sub, angle, axis  # shape, isHole, sub, angle, axis
                self.removalshapes.append(tup)

        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")
            self.outlines = [
                Part.Face(
                    TechDraw.findShapeOutline(base.Shape, 1,
                                              FreeCAD.Vector(0, 0, 1)))
                for base in self.model
            ]
            stockBB = self.stock.Shape.BoundBox
            PathLog.debug(" -Using outlines; no obj.Base")

            self.removalshapes = []
            self.bodies = []
            for outline in self.outlines:
                outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
                body = outline.extrude(
                    FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
                self.bodies.append(body)
                self.removalshapes.append(
                    (self.stock.Shape.cut(body), False, 'outline', 0.0, 'X'))

        for (shape, isHole, sub, angle, axis) in self.removalshapes:
            shape.tessellate(0.05)

        if self.removalshapes:
            obj.removalshape = self.removalshapes[0][0]
        return self.removalshapes
コード例 #16
0
ファイル: PathPocketShape.py プロジェクト: sticwin/FreeCAD
        def analyzeVerticalFaces(self, obj, vertTuples):
            hT = []
            # base = FreeCAD.ActiveDocument.getObject(self.modelName)

            # Separate elements, regroup by orientation (axis_angle combination)
            vTags = ['X34.2']
            vGrps = [[(2.3, 3.4, 'X')]]
            for tup in vertTuples:
                (face, sub, angle, axis, tag, strDep, finDep, trans) = tup
                if tag in vTags:
                    # Determine index of found string
                    i = 0
                    for orn in vTags:
                        if orn == tag:
                            break
                        i += 1
                    vGrps[i].append(tup)
                else:
                    vTags.append(tag)  # add orientation entry
                    vGrps.append([tup])  # add orientation entry
            # Remove temp elements
            vTags.pop(0)
            vGrps.pop(0)

            # check all faces in each axis_angle group
            shpList = []
            zmaxH = 0.0
            for o in range(0, len(vTags)):
                shpList = []
                zmaxH = vGrps[o][0].BoundBox.ZMax
                for (face, sub, angle, axis, tag, strDep, finDep,
                     trans) in vGrps[o]:
                    shpList.append(face)
                    # Identify tallest face to use as zMax
                    if face.BoundBox.ZMax > zmaxH:
                        zmaxH = face.BoundBox.ZMax
                # check all faces and see if they are touching/overlapping and combine those into a compound
                # Original Code in For loop
                self.vertical = PathGeom.combineConnectedShapes(shpList)
                self.vWires = [
                    TechDraw.findShapeOutline(shape, 1,
                                              FreeCAD.Vector(0, 0, 1))
                    for shape in self.vertical
                ]
                for wire in self.vWires:
                    w = PathGeom.removeDuplicateEdges(wire)
                    face = Part.Face(w)
                    face.tessellate(0.05)
                    if PathGeom.isRoughly(face.Area, 0):
                        PathLog.error(
                            translate(
                                'PathPocket',
                                'Vertical faces do not form a loop - ignoring')
                        )
                    else:
                        strDep = zmaxH + self.leadIn  # base.Shape.BoundBox.ZMax
                        finDep = judgeFinalDepth(obj, face.BoundBox.ZMin)
                        tup = face, sub, angle, axis, tag, strDep, finDep, trans
                        hT.append(tup)
            # Eol
            return hT
コード例 #17
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()
        PathLog.debug("----- areaOpShapes() in PathPocketShape.py")

        baseSubsTuples = []
        subCount = 0
        allTuples = []
        finalDepths = []

        def planarFaceFromExtrusionEdges(face, trans):
            useFace = 'useFaceName'
            minArea = 0.0
            fCnt = 0
            clsd = []
            planar = False
            # Identify closed edges
            for edg in face.Edges:
                if edg.isClosed():
                    PathLog.debug('  -e.isClosed()')
                    clsd.append(edg)
                    planar = True
            # Attempt to create planar faces and select that with smallest area for use as pocket base
            if planar is True:
                planar = False
                for edg in clsd:
                    fCnt += 1
                    fName = sub + '_face_' + str(fCnt)
                    # Create planar face from edge
                    mFF = Part.Face(Part.Wire(Part.__sortEdges__([edg])))
                    if mFF.isNull():
                        PathLog.debug('Face(Part.Wire()) failed')
                    else:
                        if trans is True:
                            mFF.translate(
                                FreeCAD.Vector(
                                    0, 0,
                                    face.BoundBox.ZMin - mFF.BoundBox.ZMin))
                        if FreeCAD.ActiveDocument.getObject(fName):
                            FreeCAD.ActiveDocument.removeObject(fName)
                        tmpFace = FreeCAD.ActiveDocument.addObject(
                            'Part::Feature', fName).Shape = mFF
                        tmpFace = FreeCAD.ActiveDocument.getObject(fName)
                        tmpFace.purgeTouched()
                        if minArea == 0.0:
                            minArea = tmpFace.Shape.Face1.Area
                            useFace = fName
                            planar = True
                        elif tmpFace.Shape.Face1.Area < minArea:
                            minArea = tmpFace.Shape.Face1.Area
                            FreeCAD.ActiveDocument.removeObject(useFace)
                            useFace = fName
                        else:
                            FreeCAD.ActiveDocument.removeObject(fName)
            if useFace != 'useFaceName':
                self.useTempJobClones(useFace)
            return (planar, useFace)

        def clasifySub(self, bs, sub):
            face = bs.Shape.getElement(sub)

            if type(face.Surface) == Part.Plane:
                PathLog.debug('type() == Part.Plane')
                if PathGeom.isVertical(face.Surface.Axis):
                    PathLog.debug('  -isVertical()')
                    # it's a flat horizontal face
                    self.horiz.append(face)
                    return True
                elif PathGeom.isHorizontal(face.Surface.Axis):
                    PathLog.debug('  -isHorizontal()')
                    self.vert.append(face)
                    return True
                else:
                    return False
            elif type(face.Surface) == Part.Cylinder and PathGeom.isVertical(
                    face.Surface.Axis):
                PathLog.debug('type() == Part.Cylinder')
                # vertical cylinder wall
                if any(e.isClosed() for e in face.Edges):
                    PathLog.debug('  -e.isClosed()')
                    # complete cylinder
                    circle = Part.makeCircle(face.Surface.Radius,
                                             face.Surface.Center)
                    disk = Part.Face(Part.Wire(circle))
                    disk.translate(
                        FreeCAD.Vector(0, 0, face.BoundBox.ZMin -
                                       disk.BoundBox.ZMin))
                    self.horiz.append(disk)
                    return True
                else:
                    PathLog.debug('  -none isClosed()')
                    # partial cylinder wall
                    self.vert.append(face)
                    return True
            elif type(face.Surface) == Part.SurfaceOfExtrusion:
                # extrusion wall
                PathLog.debug('type() == Part.SurfaceOfExtrusion')
                # Attempt to extract planar face from surface of extrusion
                (planar, useFace) = planarFaceFromExtrusionEdges(face,
                                                                 trans=True)
                # Save face object to self.horiz for processing or display error
                if planar is True:
                    uFace = FreeCAD.ActiveDocument.getObject(useFace)
                    self.horiz.append(uFace.Shape.Faces[0])
                    msg = translate(
                        'Path',
                        "<b>Verify depth of pocket for '{}'.</b>".format(sub))
                    msg += translate(
                        'Path', "\n<br>Pocket is based on extruded surface.")
                    msg += translate(
                        'Path',
                        "\n<br>Bottom of pocket might be non-planar and/or not normal to spindle axis."
                    )
                    msg += translate(
                        'Path',
                        "\n<br>\n<br><i>3D pocket bottom is NOT available in this operation</i>."
                    )
                    PathLog.info(msg)
                    title = translate('Path', 'Depth Warning')
                    self.guiMessage(title, msg, False)
                else:
                    PathLog.error(
                        translate(
                            "Path",
                            "Failed to create a planar face from edges in {}.".
                            format(sub)))
            else:
                PathLog.debug('  -type(face.Surface): {}'.format(
                    type(face.Surface)))
                return False

        if obj.Base:
            PathLog.debug('Processing... obj.Base')
            self.removalshapes = []  # pylint: disable=attribute-defined-outside-init
            # ----------------------------------------------------------------------
            if obj.EnableRotation == 'Off':
                stock = PathUtils.findParentJob(obj).Stock
                for (base, subList) in obj.Base:
                    baseSubsTuples.append((base, subList, 0.0, 'X', stock))
            else:
                for p in range(0, len(obj.Base)):
                    (base, subsList) = obj.Base[p]
                    isLoop = False

                    # First, check all subs collectively for loop of faces
                    if len(subsList) > 2:
                        (isLoop, norm,
                         surf) = self.checkForFacesLoop(base, subsList)
                    if isLoop is True:
                        PathLog.info(
                            "Common Surface.Axis or normalAt() value found for loop faces."
                        )
                        rtn = False
                        subCount += 1
                        (rtn, angle, axis,
                         praInfo) = self.faceRotationAnalysis(obj, norm, surf)  # pylint: disable=unused-variable
                        PathLog.info("angle: {};  axis: {}".format(
                            angle, axis))

                        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
                                        break
                            if rtn is False:
                                if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
                                    (clnBase, clnStock,
                                     angle) = self.applyInverseAngle(
                                         obj, clnBase, clnStock, axis, angle)
                                else:
                                    PathLog.info(
                                        translate(
                                            "Path",
                                            "Consider toggling the InverseAngle property and recomputing the operation."
                                        ))

                            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
                        allTuples.append(tup)
                        baseSubsTuples.append(tup)
                    # Eif

                    if isLoop is False:
                        PathLog.debug(
                            translate('Path',
                                      "Processing subs individually ..."))
                        for sub in subsList:
                            subCount += 1
                            if 'Face' in sub:
                                rtn = False
                                face = base.Shape.getElement(sub)
                                if type(face.Surface
                                        ) == Part.SurfaceOfExtrusion:
                                    # extrusion wall
                                    PathLog.debug(
                                        'analyzing type() == Part.SurfaceOfExtrusion'
                                    )
                                    # Attempt to extract planar face from surface of extrusion
                                    (planar,
                                     useFace) = planarFaceFromExtrusionEdges(
                                         face, trans=False)
                                    # Save face object to self.horiz for processing or display error
                                    if planar is True:
                                        base = FreeCAD.ActiveDocument.getObject(
                                            useFace)
                                        sub = 'Face1'
                                        PathLog.debug(
                                            '  -successful face created: {}'.
                                            format(useFace))
                                    else:
                                        PathLog.error(
                                            translate(
                                                "Path",
                                                "Failed to create a planar face from edges in {}."
                                                .format(sub)))

                                (norm, surf) = self.getFaceNormAndSurf(face)
                                (rtn, angle, axis,
                                 praInfo) = self.faceRotationAnalysis(
                                     obj, norm, surf)  # pylint: disable=unused-variable

                                if rtn is True:
                                    faceNum = sub.replace('Face', '')
                                    (clnBase, angle, clnStock,
                                     tag) = self.applyRotationalAnalysis(
                                         obj, base, angle, axis, faceNum)
                                    # Verify faces are correctly oriented - InverseAngle might be necessary
                                    faceIA = clnBase.Shape.getElement(sub)
                                    (norm,
                                     surf) = self.getFaceNormAndSurf(faceIA)
                                    (rtn, praAngle, praAxis,
                                     praInfo) = self.faceRotationAnalysis(
                                         obj, norm, surf)  # pylint: disable=unused-variable
                                    if rtn is True:
                                        PathLog.debug(
                                            "Face not aligned after initial rotation."
                                        )
                                        if obj.AttemptInverseAngle is True and obj.InverseAngle is False:
                                            (clnBase, clnStock,
                                             angle) = self.applyInverseAngle(
                                                 obj, clnBase, clnStock, axis,
                                                 angle)
                                        else:
                                            PathLog.info(
                                                translate(
                                                    "Path",
                                                    "Consider toggling the InverseAngle property and recomputing the operation."
                                                ))
                                    else:
                                        PathLog.debug(
                                            "Face appears to be oriented correctly."
                                        )

                                    tup = clnBase, [sub], angle, axis, clnStock
                                else:
                                    if self.warnDisabledAxis(obj,
                                                             axis) is False:
                                        PathLog.debug(
                                            str(sub) + ": No rotation used")
                                    axis = 'X'
                                    angle = 0.0
                                    stock = PathUtils.findParentJob(obj).Stock
                                    tup = base, [sub], angle, axis, stock
                                # Eif
                                allTuples.append(tup)
                                baseSubsTuples.append(tup)
                            else:
                                ignoreSub = base.Name + '.' + sub
                                PathLog.error(
                                    translate(
                                        'Path',
                                        "Selected feature is not a Face. Ignoring: {}"
                                        .format(ignoreSub)))

            for o in baseSubsTuples:
                self.horiz = []  # pylint: disable=attribute-defined-outside-init
                self.vert = []  # pylint: disable=attribute-defined-outside-init
                subBase = o[0]
                subsList = o[1]
                angle = o[2]
                axis = o[3]
                stock = o[4]

                for sub in subsList:
                    if 'Face' in sub:
                        if clasifySub(self, subBase, sub) is False:
                            PathLog.error(
                                translate(
                                    'PathPocket',
                                    'Pocket does not support shape %s.%s') %
                                (subBase.Label, sub))
                            if obj.EnableRotation != 'Off':
                                PathLog.info(
                                    translate(
                                        'PathPocket',
                                        'Face might not be within rotation accessibility limits.'
                                    ))

                # Determine final depth as highest value of bottom boundbox of vertical face,
                #   in case of uneven faces on bottom
                if len(self.vert) > 0:
                    vFinDep = self.vert[0].BoundBox.ZMin
                    for vFace in self.vert:
                        if vFace.BoundBox.ZMin > vFinDep:
                            vFinDep = vFace.BoundBox.ZMin
                    # Determine if vertical faces for a loop: Extract planar loop wire as new horizontal face.
                    self.vertical = PathGeom.combineConnectedShapes(self.vert)  # pylint: disable=attribute-defined-outside-init
                    self.vWires = [
                        TechDraw.findShapeOutline(shape, 1,
                                                  FreeCAD.Vector(0, 0, 1))
                        for shape in self.vertical
                    ]  # pylint: disable=attribute-defined-outside-init
                    for wire in self.vWires:
                        w = PathGeom.removeDuplicateEdges(wire)
                        face = Part.Face(w)
                        # face.tessellate(0.1)
                        if PathGeom.isRoughly(face.Area, 0):
                            msg = translate(
                                'PathPocket',
                                'Vertical faces do not form a loop - ignoring')
                            PathLog.error(msg)
                            # title = translate("Path", "Face Selection Warning")
                            # self.guiMessage(title, msg, True)
                        else:
                            face.translate(
                                FreeCAD.Vector(0, 0,
                                               vFinDep - face.BoundBox.ZMin))
                            self.horiz.append(face)
                            msg = translate(
                                'Path',
                                'Verify final depth of pocket shaped by vertical faces.'
                            )
                            PathLog.error(msg)
                            title = translate('Path', 'Depth Warning')
                            self.guiMessage(title, msg, False)

                # add faces for extensions
                self.exts = []  # pylint: disable=attribute-defined-outside-init
                for ext in self.getExtensions(obj):
                    wire = ext.getWire()
                    if wire:
                        face = Part.Face(wire)
                        self.horiz.append(face)
                        self.exts.append(face)

                # move all horizontal faces to FinalDepth
                for f in self.horiz:
                    finDep = max(obj.FinalDepth.Value, f.BoundBox.ZMin)
                    f.translate(FreeCAD.Vector(0, 0, finDep - f.BoundBox.ZMin))

                # check all faces and see if they are touching/overlapping and combine those into a compound
                self.horizontal = []  # pylint: disable=attribute-defined-outside-init
                for shape in PathGeom.combineConnectedShapes(self.horiz):
                    shape.sewShape()
                    # shape.tessellate(0.1)
                    if obj.UseOutline:
                        wire = TechDraw.findShapeOutline(
                            shape, 1, FreeCAD.Vector(0, 0, 1))
                        wire.translate(
                            FreeCAD.Vector(
                                0, 0,
                                obj.FinalDepth.Value - wire.BoundBox.ZMin))
                        self.horizontal.append(Part.Face(wire))
                    else:
                        self.horizontal.append(shape)

                for face in self.horizontal:
                    # extrude all faces up to StartDepth and those are the removal shapes
                    (strDep, finDep) = self.calculateStartFinalDepths(
                        obj, face, stock)
                    finalDepths.append(finDep)
                    extent = FreeCAD.Vector(0, 0, strDep - finDep)
                    self.removalshapes.append(
                        (face.removeSplitter().extrude(extent), False,
                         'pathPocketShape', angle, axis, strDep, finDep))
                    PathLog.debug(
                        "Extent depths are str: {}, and fin: {}".format(
                            strDep, finDep))
                # Efor face

            # Adjust obj.FinalDepth.Value as needed.
            if len(finalDepths) > 0:
                finalDep = min(finalDepths)
                if subCount == 1:
                    obj.FinalDepth.Value = finalDep
        else:
            # process the job base object as a whole
            PathLog.debug(translate("Path", 'Processing model as a whole ...'))
            finDep = obj.FinalDepth.Value
            strDep = obj.StartDepth.Value
            self.outlines = [
                Part.Face(
                    TechDraw.findShapeOutline(base.Shape, 1,
                                              FreeCAD.Vector(0, 0, 1)))
                for base in self.model
            ]  # pylint: disable=attribute-defined-outside-init
            stockBB = self.stock.Shape.BoundBox

            self.removalshapes = []  # pylint: disable=attribute-defined-outside-init
            self.bodies = []  # pylint: disable=attribute-defined-outside-init
            for outline in self.outlines:
                outline.translate(FreeCAD.Vector(0, 0, stockBB.ZMin - 1))
                body = outline.extrude(
                    FreeCAD.Vector(0, 0, stockBB.ZLength + 2))
                self.bodies.append(body)
                self.removalshapes.append(
                    (self.stock.Shape.cut(body), False, 'pathPocketShape', 0.0,
                     'X', strDep, finDep))

        for (shape, hole, sub, angle, axis, strDep,
             finDep) in self.removalshapes:  # pylint: disable=unused-variable
            shape.tessellate(0.05)  # originally 0.1

        if self.removalshapes:
            obj.removalshape = self.removalshapes[0][0]

        return self.removalshapes