Ejemplo n.º 1
0
def TDPyTest():
    path = os.path.dirname(os.path.abspath(__file__))
    print('TDPy path: ' + path)

    FreeCAD.newDocument("TDPy")
    FreeCAD.setActiveDocument("TDPy")
    FreeCAD.ActiveDocument = FreeCAD.getDocument("TDPy")

    direction = FreeCAD.Vector(0.0, 1.0, 0.0)
    box = FreeCAD.ActiveDocument.addObject("Part::Box", "Box")

    result = TechDraw.project(
        box.Shape, direction)  #visible hard & smooth, hidden hard & smooth
    print("project result: {0}".format(result))
    #    Part.show(result[0])

    result = TechDraw.projectEx(
        box.Shape,
        direction)  #visible & hidden hard, smooth, seam, outline, iso
    print("projectEx result: {0}".format(result))
    #    Part.show(result[0])

    SVGResult = TechDraw.projectToSVG(box.Shape, direction, "ShowHiddenLines",
                                      0.10)  #SVG string
    print("SVG result: {0}".format(SVGResult))

    result = TechDraw.projectToDXF(box.Shape, direction)  #DXF string
    print("DXF result: {0}".format(result))

    result = TechDraw.removeSvgTags(SVGResult)
    print("remove tags result: {0}".format(result))
Ejemplo n.º 2
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    def execute(self, obj):

        import Part
        import TechDraw

        if not obj.Base:
            return
        if not obj.File:
            return
        if not obj.Pattern:
            return
        if not obj.Scale:
            return
        if not obj.Pattern in self.getPatterns(obj.File):
            return
        if not obj.Base.isDerivedFrom("Part::Feature"):
            return
        if not obj.Base.Shape.Faces:
            return

        pla = obj.Placement
        shapes = []
        for face in obj.Base.Shape.Faces:
            face = face.copy()
            if obj.Translate:
                bpoint = face.CenterOfMass
                norm = face.normalAt(0, 0)
                fpla = FreeCAD.Placement(
                    bpoint, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), norm))
                face.Placement = face.Placement.multiply(fpla.inverse())
            if obj.Rotation:
                face.rotate(FreeCAD.Vector(), FreeCAD.Vector(0, 0, 1),
                            obj.Rotation)
            shape = TechDraw.makeGeomHatch(face, obj.Scale, obj.Pattern,
                                           obj.File)
            if obj.Rotation:
                shape.rotate(FreeCAD.Vector(), FreeCAD.Vector(0, 0, 1),
                             -obj.Rotation)
            if obj.Translate:
                shape.Placement = shape.Placement.multiply(fpla)
            shapes.append(shape)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pla
Ejemplo n.º 5
0
    def getProjected(self,obj,shape,direction):

        "returns projected edges from a shape and a direction"
        import Part, TechDraw, DraftGeomUtils
        edges = []
        _groups = TechDraw.projectEx(shape, direction)
        for g in _groups[0:5]:
            if g:
                edges.append(g)
        if hasattr(obj,"HiddenLines"):
            if obj.HiddenLines:
                for g in _groups[5:]:
                    edges.append(g)
        edges = self.cleanExcluded(obj,edges)
        #return Part.makeCompound(edges)
        if hasattr(obj,"Tessellation") and obj.Tessellation:
            return DraftGeomUtils.cleanProjection(Part.makeCompound(edges),
                                                  obj.Tessellation,
                                                  obj.SegmentLength)
        else:
            return Part.makeCompound(edges)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
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
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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
Ejemplo n.º 11
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
Ejemplo n.º 12
0
def silhouette(obj):
    from FreeCAD import Vector
    s = getProjected(obj.Shape, Vector(0, 0, 1))
    print s
    w = TechDraw.findOuterWire(s.Edges)
    return w
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
def silhouette(obj):
    w = TechDraw.findOuterWire(obj.Shape.Edges)
    return w
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    def execute(self, obj):

        import Part
        import TechDraw

        if not obj.Base:
            return
        if not obj.File:
            return
        if not obj.Pattern:
            return
        if not obj.Scale:
            return
        if not obj.Pattern in self.getPatterns(obj.File):
            return
        if not obj.Base.isDerivedFrom("Part::Feature"):
            return
        if not obj.Base.Shape.Faces:
            return

        shapes = []
        for face in obj.Base.Shape.Faces:
            if face.findPlane():  # Only planar faces.
                face = face.copy()
                if obj.Translate:
                    mtx = None
                    w = face.normalAt(0, 0)
                    # Try to base a matrix on the first straight edge with
                    # a reasonable length (> 0.001):
                    for e in face.Edges:
                        if geomType(e) == "Line":
                            sta = e.firstVertex().Point
                            end = e.lastVertex().Point
                            u = end.sub(sta)
                            if u.Length > 0.001:
                                u = u.normalize()
                                v = w.cross(u)
                                mtx = App.Matrix(u.x, v.x, w.x, sta.x, u.y,
                                                 v.y, w.y, sta.y, u.z, v.z,
                                                 w.z, sta.z, 0.0, 0.0, 0.0,
                                                 1.0)
                                break
                    # If no suitable straight edge was found use a default matrix:
                    if not mtx:
                        cen = face.CenterOfMass
                        rot = App.Rotation(App.Vector(0, 0, 1), w)
                        mtx = App.Placement(cen, rot).Matrix
                    face = face.transformGeometry(mtx.inverse()).Faces[0]
                if obj.Rotation.Value:
                    face.rotate(App.Vector(), App.Vector(0, 0, 1),
                                -obj.Rotation)
                shape = TechDraw.makeGeomHatch(face, obj.Scale, obj.Pattern,
                                               obj.File)
                if obj.Rotation.Value:
                    shape.rotate(App.Vector(), App.Vector(0, 0, 1),
                                 obj.Rotation)
                if obj.Translate:
                    shape = shape.transformGeometry(mtx)
                shapes.append(shape)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
Ejemplo n.º 17
0
def silhouette(obj):
    from FreeCAD import Vector
    s = getProjected(obj.Shape, Vector(0,0,1))
    print s
    w = TechDraw.findOuterWire(s.Edges)
    return w
Ejemplo n.º 18
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 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
Ejemplo n.º 19
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
Ejemplo n.º 20
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
Ejemplo n.º 21
0
    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
Ejemplo n.º 22
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 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
Ejemplo n.º 23
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.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
Ejemplo n.º 24
0
    def opExecute(self, obj):
        '''opExecute(obj) ... process engraving operation'''
        PathLog.track()

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

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

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

                output += "G0 Z" + PathUtils.fmt(
                    obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(
                        self.vertRapid) + "\n"
                self.commandlist.append(
                    Path.Command('G0', {
                        'Z': obj.ClearanceHeight.Value,
                        'F': self.vertRapid
                    }))

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

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

            if obj.BaseShapes:
                wires = []
                for shape in obj.BaseShapes:
                    shapeWires = adjustWirePlacement(obj, shape,
                                                     shape.Shape.Wires)
                    output += self.buildpathocc(obj, shapeWires, zValues)
                    wires.extend(shapeWires)
                self.wires = wires
            output += "G0 Z" + PathUtils.fmt(
                obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(
                    self.vertRapid) + "\n"
            self.commandlist.append(
                Path.Command('G0', {
                    'Z': obj.ClearanceHeight.Value,
                    'F': self.vertRapid
                }))

        except Exception as e:
            PathLog.error(e)
            traceback.print_exc()
            PathLog.error(
                translate(
                    'PathEngrave',
                    'The Job Base Object has no engraveable element.  Engraving operation will produce no output.'
                ))
Ejemplo n.º 25
0
        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
Ejemplo n.º 26
0
    def computeAreas(self,obj):
        """Compute the area, perimeter length, and volume of the terrain shape.

        Compute the area of the terrain projected onto an XY hyperplane, IE:
        the area of the terrain if viewed from a birds eye view.

        Compute the length of the perimeter of this birds eye view area.

        Compute the volume of the terrain that needs to be subtracted and
        added on account of the Additions and Subtractions to the site.

        Assign these values to their respective site properties.
        """

        if not obj.Shape:
            return
        if obj.Shape.isNull():
            return
        if not obj.Shape.isValid():
            return
        if not obj.Shape.Faces:
            return
        if not hasattr(obj,"Perimeter"): # check we have a latest version site
            return
        if not obj.Terrain:
            return

        # compute area
        fset = []
        for f in obj.Shape.Faces:
            if f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1)) < 1.5707:
                fset.append(f)
        if fset:
            import TechDraw, Part
            pset = []
            for f in fset:
                try:
                    pf = Part.Face(Part.Wire(TechDraw.project(f,FreeCAD.Vector(0,0,1))[0].Edges))
                except Part.OCCError:
                    # error in computing the area. Better set it to zero than show a wrong value
                    if obj.ProjectedArea.Value != 0:
                        print("Error computing areas for ",obj.Label)
                        obj.ProjectedArea = 0
                else:
                    pset.append(pf)
            if pset:
                self.flatarea = pset.pop()
                for f in pset:
                    self.flatarea = self.flatarea.fuse(f)
                self.flatarea = self.flatarea.removeSplitter()
                if obj.ProjectedArea.Value != self.flatarea.Area:
                    obj.ProjectedArea = self.flatarea.Area

        # compute perimeter
        lut = {}
        for e in obj.Shape.Edges:
            lut.setdefault(e.hashCode(),[]).append(e)
        l = 0
        for e in lut.values():
            if len(e) == 1: # keep only border edges
                l += e[0].Length
        if l:
                if obj.Perimeter.Value != l:
                    obj.Perimeter = l

        # compute volumes
        if obj.Terrain.Shape.Solids:
            shapesolid = obj.Terrain.Shape.copy()
        else:
            shapesolid = obj.Terrain.Shape.extrude(obj.ExtrusionVector)
        addvol = 0
        subvol = 0
        for sub in obj.Subtractions:
            subvol += sub.Shape.common(shapesolid).Volume
        for sub in obj.Additions:
            addvol += sub.Shape.cut(shapesolid).Volume
        if obj.SubtractionVolume.Value != subvol:
            obj.SubtractionVolume = subvol
        if obj.AdditionVolume.Value != addvol:
            obj.AdditionVolume = addvol