Exemplo n.º 1
0
    def findHoles(self, obj, shape):
        import DraftGeomUtils as dgu
        PathLog.track('obj: {} shape: {}'.format(obj, shape))
        holelist = []
        tooldiameter = obj.ToolController.Proxy.getTool(obj.ToolController).Diameter
        PathLog.debug('search for holes larger than tooldiameter: {}: '.format(tooldiameter))
        if dgu.isPlanar(shape):
            PathLog.debug("shape is planar")
            for i in range(len(shape.Edges)):
                candidateEdgeName = "Edge" + str(i + 1)
                e = shape.getElement(candidateEdgeName)
                if PathUtils.isDrillable(shape, e, tooldiameter):
                    PathLog.debug('edge candidate: {} (hash {})is drillable '.format(e, e.hashCode()))
                    x = e.Curve.Center.x
                    y = e.Curve.Center.y
                    diameter = e.BoundBox.XLength
                    holelist.append({'featureName': candidateEdgeName, 'feature': e, 'x': x, 'y': y, 'd': diameter, 'enabled': True})
        else:
            PathLog.debug("shape is not planar")
            for i in range(len(shape.Faces)):
                candidateFaceName = "Face" + str(i + 1)
                f = shape.getElement(candidateFaceName)
                if PathUtils.isDrillable(shape, f, tooldiameter):
                    PathLog.debug('face candidate: {} is drillable '.format(f))
                    x = f.Surface.Center.x
                    y = f.Surface.Center.y
                    diameter = f.BoundBox.XLength
                    holelist.append({'featureName': candidateFaceName, 'feature': f, 'x': x, 'y': y, 'd': diameter, 'enabled': True})

        PathLog.debug("holes found: {}".format(holelist))
        return holelist
Exemplo n.º 2
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        if obj.UseComp:
            self.commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")"))
        else:
            self.commandlist.append(Path.Command("(Uncompensated Tool Path)"))

        shapes = []

        if obj.Base:  # The user has selected subobjects from the base.  Process each.
            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:
                        FreeCAD.Console.PrintWarning("found a base object which is not a face.  Can't continue.")
                        return

            for wire in holes:
                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                drillable = PathUtils.isDrillable(self.baseobject.Shape, wire)
                if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                    env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=f, depthparams=self.depthparams)
                    shapes.append((env, True))

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

            if obj.processPerimeter:
                env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=profileshape, depthparams=self.depthparams)
                shapes.append((env, False))

        else:  # Try to build targets from the job base
            if hasattr(self.baseobject, "Proxy"):
                if isinstance(self.baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                    if obj.processCircles or obj.processHoles:
                        for shape in self.baseobject.Proxy.getHoles(self.baseobject, transform=True):
                            for wire in shape.Wires:
                                drillable = PathUtils.isDrillable(self.baseobject.Proxy, wire)
                                if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                                    env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=f, depthparams=self.depthparams)
                                    shapes.append((env, True))

                    if obj.processPerimeter:
                        for shape in self.baseobject.Proxy.getOutlines(self.baseobject, transform=True):
                            for wire in shape.Wires:
                                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                                env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=f, depthparams=self.depthparams)
                                shapes.append((env, False))

        PathLog.debug("%d shapes" % len(shapes))
        return shapes
Exemplo n.º 3
0
    def findHoles(self, obj, baseobject):
        '''findHoles(obj, baseobject) ... inspect baseobject and identify all features that resemble a straight cricular hole.'''
        shape = baseobject.Shape
        PathLog.track('obj: {} shape: {}'.format(obj, shape))
        holelist = []
        features = []
        # tooldiameter = obj.ToolController.Proxy.getTool(obj.ToolController).Diameter
        tooldiameter = None
        PathLog.debug('search for holes larger than tooldiameter: {}: '.format(
            tooldiameter))
        if DraftGeomUtils.isPlanar(shape):
            PathLog.debug("shape is planar")
            for i in range(len(shape.Edges)):
                candidateEdgeName = "Edge" + str(i + 1)
                e = shape.getElement(candidateEdgeName)
                if PathUtils.isDrillable(shape, e, tooldiameter):
                    PathLog.debug(
                        'edge candidate: {} (hash {})is drillable '.format(
                            e, e.hashCode()))
                    x = e.Curve.Center.x
                    y = e.Curve.Center.y
                    diameter = e.BoundBox.XLength
                    holelist.append({
                        'featureName': candidateEdgeName,
                        'feature': e,
                        'x': x,
                        'y': y,
                        'd': diameter,
                        'enabled': True
                    })
                    features.append((baseobject, candidateEdgeName))
                    PathLog.debug("Found hole feature %s.%s" %
                                  (baseobject.Label, candidateEdgeName))
        else:
            PathLog.debug("shape is not planar")
            for i in range(len(shape.Faces)):
                candidateFaceName = "Face" + str(i + 1)
                f = shape.getElement(candidateFaceName)
                if PathUtils.isDrillable(shape, f, tooldiameter):
                    PathLog.debug('face candidate: {} is drillable '.format(f))
                    x = f.Surface.Center.x
                    y = f.Surface.Center.y
                    diameter = f.BoundBox.XLength
                    holelist.append({
                        'featureName': candidateFaceName,
                        'feature': f,
                        'x': x,
                        'y': y,
                        'd': diameter,
                        'enabled': True
                    })
                    features.append((baseobject, candidateFaceName))
                    PathLog.debug("Found hole feature %s.%s" %
                                  (baseobject.Label, candidateFaceName))

        PathLog.debug("holes found: {}".format(holelist))
        return features
Exemplo n.º 4
0
    def addSelected(self):
        for sel in FreeCAD.Gui.Selection.getSelectionEx():

            names = self.obj.Names
            positions = self.obj.Positions
            enabled = self.obj.Enabled
            diameters = self.obj.Diameters

            objectname = sel.ObjectName
            sobj = sel.Object
            for i, sub in enumerate(sel.SubObjects):
                if hasattr(sub, 'ShapeType'):
                    if sub.ShapeType == 'Vertex':
                        PathLog.debug("Selection is a vertex, lets drill that")
                        names.append(objectname + '.' + sel.SubElementNames[i])
                        positions.append(FreeCAD.Vector(sub.X, sub.Y, 0))
                        enabled.append(1)
                        diameters.append(0)

                    elif sub.ShapeType == 'Edge':
                        if PathUtils.isDrillable(sobj, sub):
                            PathLog.debug(
                                "Selection is a drillable edge, lets drill that"
                            )
                            names.append(objectname + '.' +
                                         sel.SubElementNames[i])
                            positions.append(
                                FreeCAD.Vector(sub.Curve.Center.x,
                                               sub.Curve.Center.y, 0))
                            enabled.append(1)
                            diameters.append(sub.BoundBox.XLength)
                    elif sub.ShapeType == 'Face':
                        if PathUtils.isDrillable(sobj.Shape, sub):
                            PathLog.debug(
                                "Selection is a drillable face, lets drill that"
                            )
                            names.append(objectname + '.' +
                                         sel.SubElementNames[i])
                            positions.append(
                                FreeCAD.Vector(sub.Surface.Center.x,
                                               sub.Surface.Center.y, 0))
                            enabled.append(1)
                            diameters.append(sub.BoundBox.XLength)

            self.obj.Names = names
            self.obj.Positions = positions
            self.obj.Enabled = enabled
            self.obj.Diameters = diameters

            self.updateFeatureList()

            FreeCAD.ActiveDocument.recompute()
Exemplo n.º 5
0
    def findHoles(self, obj, shape):
        import DraftGeomUtils as dgu
        PathLog.track('obj: {} shape: {}'.format(obj, shape))
        holelist = []
        # tooldiameter = obj.ToolController.Proxy.getTool(obj.ToolController).Diameter
        tooldiameter = None
        PathLog.debug('search for holes larger than tooldiameter: {}: '.format(
            tooldiameter))
        if dgu.isPlanar(shape):
            PathLog.debug("shape is planar")
            for i in range(len(shape.Edges)):
                candidateEdgeName = "Edge" + str(i + 1)
                e = shape.getElement(candidateEdgeName)
                if PathUtils.isDrillable(shape, e, tooldiameter):
                    PathLog.debug(
                        'edge candidate: {} (hash {})is drillable '.format(
                            e, e.hashCode()))
                    x = e.Curve.Center.x
                    y = e.Curve.Center.y
                    diameter = e.BoundBox.XLength
                    holelist.append({
                        'featureName': candidateEdgeName,
                        'feature': e,
                        'x': x,
                        'y': y,
                        'd': diameter,
                        'enabled': True
                    })
        else:
            PathLog.debug("shape is not planar")
            for i in range(len(shape.Faces)):
                candidateFaceName = "Face" + str(i + 1)
                f = shape.getElement(candidateFaceName)
                if PathUtils.isDrillable(shape, f, tooldiameter):
                    PathLog.debug('face candidate: {} is drillable '.format(f))
                    x = f.Surface.Center.x
                    y = f.Surface.Center.y
                    diameter = f.BoundBox.XLength
                    holelist.append({
                        'featureName': candidateFaceName,
                        'feature': f,
                        'x': x,
                        'y': y,
                        'd': diameter,
                        'enabled': True
                    })

        PathLog.debug("holes found: {}".format(holelist))
        return holelist
Exemplo n.º 6
0
 def findAllHoles(self, obj):
     if not self.getJob(obj):
         return
     features = []
     if self.baseIsArchPanel(obj, self.baseobject):
         holeshapes = self.baseobject.Proxy.getHoles(self.baseobject,
                                                     transform=True)
         tooldiameter = obj.ToolController.Proxy.getTool(
             obj.ToolController).Diameter
         for holeNr, hole in enumerate(holeshapes):
             PathLog.debug('Entering new HoleShape')
             for wireNr, wire in enumerate(hole.Wires):
                 PathLog.debug('Entering new Wire')
                 for edgeNr, edge in enumerate(wire.Edges):
                     if PathUtils.isDrillable(self.baseobject, edge,
                                              tooldiameter):
                         PathLog.debug(
                             'Found drillable hole edges: {}'.format(edge))
                         features.append(
                             (self.baseobject,
                              "%d.%d.%d" % (holeNr, wireNr, edgeNr)))
     else:
         features = self.findHoles(obj, self.baseobject)
     obj.Base = features
     obj.Disabled = []
Exemplo n.º 7
0
 def findAllHoles(self, obj):
     '''findAllHoles(obj) ... find all holes of all base models and assign as features.'''
     PathLog.track()
     if not self.getJob(obj):
         return
     features = []
     if 1 == len(self.model) and self.baseIsArchPanel(obj, self.model[0]):
         panel = self.model[0]
         holeshapes = panel.Proxy.getHoles(panel, transform=True)
         tooldiameter = obj.ToolController.Proxy.getTool(
             obj.ToolController).Diameter
         for holeNr, hole in enumerate(holeshapes):
             PathLog.debug('Entering new HoleShape')
             for wireNr, wire in enumerate(hole.Wires):
                 PathLog.debug('Entering new Wire')
                 for edgeNr, edge in enumerate(wire.Edges):
                     if PathUtils.isDrillable(panel, edge, tooldiameter):
                         PathLog.debug(
                             'Found drillable hole edges: {}'.format(edge))
                         features.append(
                             (panel, "%d.%d.%d" % (holeNr, wireNr, edgeNr)))
     else:
         for base in self.model:
             features.extend(self.findHoles(obj, base))
     obj.Base = features
     obj.Disabled = []
Exemplo n.º 8
0
 def allow(self, doc, obj, sub):
     PathLog.debug('obj: {} sub: {}'.format(obj, sub))
     if hasattr(obj, "Shape") and sub:
         shape = obj.Shape
         subobj = shape.getElement(sub)
         return PathUtils.isDrillable(shape, subobj, includePartials = True)
     else:
         return False
Exemplo n.º 9
0
 def allow(self, doc, obj, sub):  # pylint: disable=unused-argument
     PathLog.debug('obj: {} sub: {}'.format(obj, sub))
     if hasattr(obj, "Shape") and sub:
         shape = obj.Shape
         subobj = shape.getElement(sub)
         return PathUtils.isDrillable(shape, subobj, includePartials=True)
     else:
         return False
Exemplo n.º 10
0
 def allow(self, doc, obj, sub):
     PathLog.debug('obj: {} sub: {}'.format(obj, sub))
     if hasattr(obj, "Shape"):
         obj = obj.Shape
         subobj = obj.getElement(sub)
         return PathUtils.isDrillable(obj, subobj)
     else:
         return False
Exemplo n.º 11
0
    def opExecute(self, obj):
        '''opExecute(obj) ... processes all Base features and Locations and collects
        them in a list of positions and radii which is then passed to circularHoleExecute(obj, holes).
        If no Base geometries and no Locations are present, the job's Base is inspected and all
        drillable features are added to Base. In this case appropriate values for depths are also
        calculated and assigned.
        Do not overwrite, implement circularHoleExecute(obj, holes) instead.'''
        PathLog.track()

        def haveLocations(self, obj):
            if PathOp.FeatureLocations & self.opFeatures(obj):
                return len(obj.Locations) != 0
            return False

        if len(obj.Base) == 0 and not haveLocations(self, obj):
            features = []
            if self.baseIsArchPanel(obj, self.baseobject):
                holeshapes = self.baseobject.Proxy.getHoles(self.baseobject,
                                                            transform=True)
                tooldiameter = obj.ToolController.Proxy.getTool(
                    obj.ToolController).Diameter
                for holeNr, hole in enumerate(holeshapes):
                    PathLog.debug('Entering new HoleShape')
                    for wireNr, wire in enumerate(hole.Wires):
                        PathLog.debug('Entering new Wire')
                        for edgeNr, edge in enumerate(wire.Edges):
                            if PathUtils.isDrillable(self.baseobject, edge,
                                                     tooldiameter):
                                PathLog.debug(
                                    'Found drillable hole edges: {}'.format(
                                        edge))
                                features.append(
                                    (self.baseobject,
                                     "%d.%d.%d" % (holeNr, wireNr, edgeNr)))
            else:
                features = self.findHoles(obj, self.baseobject)
            obj.Base = features
            obj.Disabled = []

        holes = []

        for base, subs in obj.Base:
            for sub in subs:
                if self.isHoleEnabled(obj, base, sub):
                    pos = self.holePosition(obj, base, sub)
                    if pos:
                        holes.append({
                            'x': pos.x,
                            'y': pos.y,
                            'r': self.holeDiameter(obj, base, sub)
                        })
        if haveLocations(self, obj):
            for location in obj.Locations:
                holes.append({'x': location.x, 'y': location.y, 'r': 0})

        if len(holes) > 0:
            self.circularHoleExecute(obj, holes)
Exemplo n.º 12
0
    def findHoles(self, obj, baseobject):
        '''findHoles(obj, baseobject) ... inspect baseobject and identify all features that resemble a straight cricular hole.'''
        shape = baseobject.Shape
        PathLog.track('obj: {} shape: {}'.format(obj, shape))
        holelist = []
        features = []
        # tooldiameter = obj.ToolController.Proxy.getTool(obj.ToolController).Diameter
        tooldiameter = None
        PathLog.debug('search for holes larger than tooldiameter: {}: '.format(tooldiameter))
        if DraftGeomUtils.isPlanar(shape):
            PathLog.debug("shape is planar")
            for i in range(len(shape.Edges)):
                candidateEdgeName = "Edge" + str(i + 1)
                e = shape.getElement(candidateEdgeName)
                if PathUtils.isDrillable(shape, e, tooldiameter):
                    PathLog.debug('edge candidate: {} (hash {})is drillable '.format(e, e.hashCode()))
                    x = e.Curve.Center.x
                    y = e.Curve.Center.y
                    diameter = e.BoundBox.XLength
                    holelist.append({'featureName': candidateEdgeName, 'feature': e, 'x': x, 'y': y, 'd': diameter, 'enabled': True})
                    features.append((baseobject, candidateEdgeName))
                    PathLog.debug("Found hole feature %s.%s" % (baseobject.Label, candidateEdgeName))
        else:
            PathLog.debug("shape is not planar")
            for i in range(len(shape.Faces)):
                candidateFaceName = "Face" + str(i + 1)
                f = shape.getElement(candidateFaceName)
                if PathUtils.isDrillable(shape, f, tooldiameter):
                    PathLog.debug('face candidate: {} is drillable '.format(f))
                    if hasattr(f.Surface, 'Center'):
                        x = f.Surface.Center.x
                        y = f.Surface.Center.y
                        diameter = f.BoundBox.XLength
                    else:
                        center = f.Edges[0].Curve.Center
                        x = center.x
                        y = center.y
                        diameter = f.Edges[0].Curve.Radius * 2
                    holelist.append({'featureName': candidateFaceName, 'feature': f, 'x': x, 'y': y, 'd': diameter, 'enabled': True})
                    features.append((baseobject, candidateFaceName))
                    PathLog.debug("Found hole feature %s.%s" % (baseobject.Label, candidateFaceName))

        PathLog.debug("holes found: {}".format(holelist))
        return features
Exemplo n.º 13
0
    def addSelected(self):
        for sel in FreeCAD.Gui.Selection.getSelectionEx():

            names = self.obj.Names
            positions = self.obj.Positions
            enabled = self.obj.Enabled
            diameters = self.obj.Diameters

            objectname = sel.ObjectName
            sobj = sel.Object
            for i, sub in enumerate(sel.SubObjects):
                if hasattr(sub, 'ShapeType'):
                    if sub.ShapeType == 'Vertex':
                        PathLog.debug("Selection is a vertex, lets drill that")
                        names.append(objectname+'.'+sel.SubElementNames[i])
                        positions.append(FreeCAD.Vector(sub.X, sub.Y, 0))
                        enabled.append(1)
                        diameters.append(0)

                    elif sub.ShapeType == 'Edge':
                        if PathUtils.isDrillable(sobj, sub):
                            PathLog.debug("Selection is a drillable edge, lets drill that")
                            names.append(objectname+'.'+sel.SubElementNames[i])
                            positions.append(FreeCAD.Vector(sub.Curve.Center.x, sub.Curve.Center.y, 0))
                            enabled.append(1)
                            diameters.append(sub.BoundBox.XLength)
                    elif sub.ShapeType == 'Face':
                        if PathUtils.isDrillable(sobj.Shape, sub):
                            PathLog.debug("Selection is a drillable face, lets drill that")
                            names.append(objectname+'.'+sel.SubElementNames[i])
                            positions.append(FreeCAD.Vector(sub.Surface.Center.x, sub.Surface.Center.y, 0))
                            enabled.append(1)
                            diameters.append(sub.BoundBox.XLength)

            self.obj.Names = names
            self.obj.Positions = positions
            self.obj.Enabled = enabled
            self.obj.Diameters = diameters

            self.updateFeatureList()

            FreeCAD.ActiveDocument.recompute()
Exemplo n.º 14
0
    def opExecute(self, obj):
        '''opExecute(obj) ... processes all Base features and Locations and collects
        them in a list of positions and radii which is then passed to circularHoleExecute(obj, holes).
        If no Base geometries and no Locations are present, the job's Base is inspected and all
        drillable features are added to Base. In this case appropriate values for depths are also
        calculated and assigned.
        Do not overwrite, implement circularHoleExecute(obj, holes) instead.'''
        PathLog.track()

        def haveLocations(self, obj):
            if PathOp.FeatureLocations & self.opFeatures(obj):
                return len(obj.Locations) != 0
            return False

        if len(obj.Base) == 0 and not haveLocations(self, obj):
            # Arch PanelSheet
            features = []
            if self.baseIsArchPanel(obj, self.baseobject):
                holeshapes = self.baseobject.Proxy.getHoles(self.baseobject, transform=True)
                tooldiameter = obj.ToolController.Proxy.getTool(obj.ToolController).Diameter
                for holeNr, hole in enumerate(holeshapes):
                    PathLog.debug('Entering new HoleShape')
                    for wireNr, wire in enumerate(hole.Wires):
                        PathLog.debug('Entering new Wire')
                        for edgeNr, edge in enumerate(wire.Edges):
                            if PathUtils.isDrillable(self.baseobject, edge, tooldiameter):
                                PathLog.debug('Found drillable hole edges: {}'.format(edge))
                                features.append((self.baseobject, "%d.%d.%d" % (holeNr, wireNr, edgeNr)))

                self.setDepths(obj, None, None, self.baseobject.Shape.BoundBox)
            else:
                features = self.findHoles(obj, self.baseobject)
                self.setupDepthsFrom(obj, features, self.baseobject)
            obj.Base = features
            obj.Disabled = []

        holes = []

        for base, subs in obj.Base:
            for sub in subs:
                if self.isHoleEnabled(obj, base, sub):
                    pos = self.holePosition(obj, base, sub)
                    if pos:
                        holes.append({'x': pos.x, 'y': pos.y, 'r': self.holeDiameter(obj, base, sub)})
        if haveLocations(self, obj):
            for location in obj.Locations:
                holes.append({'x': location.x, 'y': location.y, 'r': 0})

        if len(holes) > 0:
            self.circularHoleExecute(obj, holes)
Exemplo n.º 15
0
 def findAllHoles(self, obj):
     if not self.getJob(obj):
         return
     features = []
     if self.baseIsArchPanel(obj, self.baseobject):
         holeshapes = self.baseobject.Proxy.getHoles(self.baseobject, transform=True)
         tooldiameter = obj.ToolController.Proxy.getTool(obj.ToolController).Diameter
         for holeNr, hole in enumerate(holeshapes):
             PathLog.debug('Entering new HoleShape')
             for wireNr, wire in enumerate(hole.Wires):
                 PathLog.debug('Entering new Wire')
                 for edgeNr, edge in enumerate(wire.Edges):
                     if PathUtils.isDrillable(self.baseobject, edge, tooldiameter):
                         PathLog.debug('Found drillable hole edges: {}'.format(edge))
                         features.append((self.baseobject, "%d.%d.%d" % (holeNr, wireNr, edgeNr)))
     else:
         features = self.findHoles(obj, self.baseobject)
     obj.Base = features
     obj.Disabled = []
Exemplo n.º 16
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        PathLog.track()
        PathLog.debug("----- areaOpShapes() in PathProfileFaces.py")

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

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

        baseSubsTuples = []
        subCount = 0
        allTuples = []

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

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

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

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

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

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

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

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

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

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

        return shapes
Exemplo n.º 17
0
    def findHoles(self, obj, baseobject):
        """findHoles(obj, baseobject) ... inspect baseobject and identify all features that resemble a straight cricular hole."""
        shape = baseobject.Shape
        PathLog.track("obj: {} shape: {}".format(obj, shape))
        holelist = []
        features = []
        # tooldiameter = float(obj.ToolController.Proxy.getTool(obj.ToolController).Diameter)
        tooldiameter = None
        PathLog.debug("search for holes larger than tooldiameter: {}: ".format(
            tooldiameter))
        if DraftGeomUtils.isPlanar(shape):
            PathLog.debug("shape is planar")
            for i in range(len(shape.Edges)):
                candidateEdgeName = "Edge" + str(i + 1)
                e = shape.getElement(candidateEdgeName)
                if PathUtils.isDrillable(shape, e, tooldiameter):
                    PathLog.debug(
                        "edge candidate: {} (hash {})is drillable ".format(
                            e, e.hashCode()))
                    x = e.Curve.Center.x
                    y = e.Curve.Center.y
                    diameter = e.BoundBox.XLength
                    holelist.append({
                        "featureName": candidateEdgeName,
                        "feature": e,
                        "x": x,
                        "y": y,
                        "d": diameter,
                        "enabled": True,
                    })
                    features.append((baseobject, candidateEdgeName))
                    PathLog.debug("Found hole feature %s.%s" %
                                  (baseobject.Label, candidateEdgeName))
        else:
            PathLog.debug("shape is not planar")
            for i in range(len(shape.Faces)):
                candidateFaceName = "Face" + str(i + 1)
                f = shape.getElement(candidateFaceName)
                if PathUtils.isDrillable(shape, f, tooldiameter):
                    PathLog.debug("face candidate: {} is drillable ".format(f))
                    if hasattr(f.Surface, "Center"):
                        x = f.Surface.Center.x
                        y = f.Surface.Center.y
                        diameter = f.BoundBox.XLength
                    else:
                        center = f.Edges[0].Curve.Center
                        x = center.x
                        y = center.y
                        diameter = f.Edges[0].Curve.Radius * 2
                    holelist.append({
                        "featureName": candidateFaceName,
                        "feature": f,
                        "x": x,
                        "y": y,
                        "d": diameter,
                        "enabled": True,
                    })
                    features.append((baseobject, candidateFaceName))
                    PathLog.debug("Found hole feature %s.%s" %
                                  (baseobject.Label, candidateFaceName))

        PathLog.debug("holes found: {}".format(holelist))
        return features
Exemplo n.º 18
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        if obj.UseComp:
            self.commandlist.append(
                Path.Command("(Compensated Tool Path. Diameter: " +
                             str(self.radius * 2) + ")"))
        else:
            self.commandlist.append(Path.Command("(Uncompensated Tool Path)"))

        shapes = []
        self.profileshape = []

        if obj.Base:  # The user has selected subobjects from the base.  Process each.
            for base in obj.Base:
                holes = []
                faces = []
                for sub in base[1]:
                    shape = getattr(base[0].Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z),
                                         1):  # horizontal face
                            for wire in shape.Wires[1:]:
                                holes.append((base[0].Shape, wire))
                    else:
                        FreeCAD.Console.PrintWarning(
                            "found a base object which is not a face.  Can't continue."
                        )
                        return

                for shape, wire in holes:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                    drillable = PathUtils.isDrillable(shape, wire)
                    if (drillable
                            and obj.processCircles) or (not drillable
                                                        and obj.processHoles):
                        env = PathUtils.getEnvelope(
                            shape, subshape=f, depthparams=self.depthparams)
                        PathLog.track()
                        shapes.append((env, True))

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

                if obj.processPerimeter:
                    env = PathUtils.getEnvelope(base[0].Shape,
                                                subshape=profileshape,
                                                depthparams=self.depthparams)
                    PathLog.track()
                    shapes.append((env, False))

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

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

        self.removalshapes = shapes
        PathLog.debug("%d shapes" % len(shapes))
        return shapes
Exemplo n.º 19
0
    def execute(self, obj):
        PathLog.track()

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

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

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

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

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

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

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

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

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

            output += "G80\n"

        path = Path.Path(output)
        obj.Path = path
Exemplo n.º 20
0
    def execute(self, obj):
        PathLog.track()
        output = ""
        if obj.Comment != "":
            output += '(' + str(obj.Comment)+')\n'

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

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

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

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

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

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

            output += "G80\n"

        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
Exemplo n.º 21
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
Exemplo n.º 22
0
    def execute(self, obj, getsim=False):
        import Part

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

        self.depthparams = depth_params(
                clearance_height=obj.ClearanceHeight.Value,
                safe_height=obj.SafeHeight.Value,
                start_depth=obj.StartDepth.Value,
                step_down=obj.StepDown.Value,
                z_finish_step=0.0,
                final_depth=obj.FinalDepth.Value,
                user_depths=None)

        commandlist = []
        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

        commandlist.append(Path.Command("(" + obj.Label + ")"))

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

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

        if obj.Base:  # The user has selected subobjects from the base.  Process each.
            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:
                        FreeCAD.Console.PrintWarning("found a base object which is not a face.  Can't continue.")
                        return

            for wire in holes:
                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                drillable = PathUtils.isDrillable(baseobject.Shape, wire)
                if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
                    env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, depthparams=self.depthparams)
                    try:
                        (pp, sim) = self._buildPathArea(obj, baseobject=env, isHole=True, start=None, getsim=getsim)
                        commandlist.extend(pp.Commands)
                    except Exception as e:
                        FreeCAD.Console.PrintError(e)
                        FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")

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

            if obj.processPerimeter:
                env = PathUtils.getEnvelope(baseobject.Shape, subshape=profileshape, depthparams=self.depthparams)
                try:
                    (pp, sim) = self._buildPathArea(obj, baseobject=env, start=None, getsim=getsim)
                    commandlist.extend(pp.Commands)
                except Exception as e:
                    FreeCAD.Console.PrintError(e)
                    FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")

        else:  # Try to build targets from the job base
            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:
                                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                                env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, depthparams=self.depthparams)
                                try:
                                    (pp, sim) = self._buildPathArea(obj, baseobject=env, isHole=False, start=None, getsim=getsim)
                                    commandlist.extend(pp.Commands)
                                except Exception as e:
                                    FreeCAD.Console.PrintError(e)
                                    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):
                                f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                                env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, depthparams=self.depthparams)
                                try:
                                    (pp, sim) = self._buildPathArea(obj, baseobject=env, isHole=True, start=None, getsim=getsim)
                                    commandlist.extend(pp.Commands)
                                except Exception as e:
                                    FreeCAD.Console.PrintError(e)
                                    FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")

        # Let's finish by rapid to clearance...just for safety
        commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))

        path = Path.Path(commandlist)
        obj.Path = path
Exemplo n.º 23
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all base shapes or wires for Arch.Panels.'''
        PathLog.track()

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

        shapes = []
        self.profileshape = []  # pylint: disable=attribute-defined-outside-init

        baseSubsTuples = []
        subCount = 0
        allTuples = []

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

                                tup = clnBase, sub, tag, angle, axis, clnStock
                            else:
                                if self.warnDisabledAxis(obj, axis) is False:
                                    PathLog.debug(
                                        str(sub) + ": No rotation used")
                                axis = 'X'
                                angle = 0.0
                                tag = base.Name + '_' + axis + str(
                                    angle).replace('.', '_')
                                stock = PathUtils.findParentJob(obj).Stock
                                tup = base, sub, tag, angle, axis, stock

                            allTuples.append(tup)

                if subCount > 1:
                    msg = translate('Path',
                                    "Multiple faces in Base Geometry.") + "  "
                    msg += translate(
                        'Path', "Depth settings will be applied to all faces.")
                    PathLog.warning(msg)

                (Tags, Grps) = self.sortTuplesByIndex(
                    allTuples, 2)  # return (TagList, GroupList)
                subList = []
                for o in range(0, len(Tags)):
                    subList = []
                    for (base, sub, tag, angle, axis, stock) in Grps[o]:
                        subList.append(sub)

                    pair = base, subList, angle, axis, stock
                    baseSubsTuples.append(pair)
                # Efor
            else:
                PathLog.debug(
                    translate("Path", "EnableRotation property is 'Off'."))
                stock = PathUtils.findParentJob(obj).Stock
                for (base, subList) in obj.Base:
                    baseSubsTuples.append((base, subList, 0.0, 'X', stock))

            # for base in obj.Base:
            finish_step = obj.FinishDepth.Value if hasattr(
                obj, "FinishDepth") else 0.0
            for (base, subsList, angle, axis, stock) in baseSubsTuples:
                holes = []
                faces = []
                faceDepths = []
                startDepths = []

                for sub in subsList:
                    shape = getattr(base.Shape, sub)
                    if isinstance(shape, Part.Face):
                        faces.append(shape)
                        if numpy.isclose(abs(shape.normalAt(0, 0).z),
                                         1):  # horizontal face
                            for wire in shape.Wires[1:]:
                                holes.append((base.Shape, wire))

                        # Add face depth to list
                        faceDepths.append(shape.BoundBox.ZMin)
                    else:
                        ignoreSub = base.Name + '.' + sub
                        msg = translate(
                            'Path',
                            "Found a selected object which is not a face. Ignoring: {}"
                            .format(ignoreSub))
                        PathLog.error(msg)
                        FreeCAD.Console.PrintWarning(msg)

                # Set initial Start and Final Depths and recalculate depthparams
                finDep = obj.FinalDepth.Value
                strDep = obj.StartDepth.Value
                if strDep > stock.Shape.BoundBox.ZMax:
                    strDep = stock.Shape.BoundBox.ZMax

                startDepths.append(strDep)
                self.depthparams = self._customDepthParams(obj, strDep, finDep)

                for shape, wire in holes:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                    drillable = PathUtils.isDrillable(shape, wire)
                    if (drillable
                            and obj.processCircles) or (not drillable
                                                        and obj.processHoles):
                        env = PathUtils.getEnvelope(
                            shape, subshape=f, depthparams=self.depthparams)
                        tup = env, True, 'pathProfileFaces', angle, axis, strDep, finDep
                        shapes.append(tup)

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

                if obj.processPerimeter:
                    if obj.HandleMultipleFeatures == 'Collectively':
                        custDepthparams = self.depthparams
                        if obj.LimitDepthToFace is True and obj.EnableRotation != 'Off':
                            if profileshape.BoundBox.ZMin > obj.FinalDepth.Value:
                                finDep = profileshape.BoundBox.ZMin
                                custDepthparams = self._customDepthParams(
                                    obj, strDep,
                                    finDep - 0.5)  # only an envelope
                        try:
                            env = PathUtils.getEnvelope(
                                base.Shape,
                                subshape=profileshape,
                                depthparams=custDepthparams)
                        except Exception:  # pylint: disable=broad-except
                            # PathUtils.getEnvelope() failed to return an object.
                            PathLog.error(
                                translate(
                                    'Path',
                                    'Unable to create path for face(s).'))
                        else:
                            tup = env, False, 'pathProfileFaces', angle, axis, strDep, finDep
                            shapes.append(tup)

                    elif obj.HandleMultipleFeatures == 'Individually':
                        for shape in faces:
                            profShape = Part.makeCompound([shape])
                            finalDep = obj.FinalDepth.Value
                            custDepthparams = self.depthparams
                            if obj.Side == 'Inside':
                                if finalDep < shape.BoundBox.ZMin:
                                    # Recalculate depthparams
                                    finalDep = shape.BoundBox.ZMin
                                    custDepthparams = self._customDepthParams(
                                        obj, strDep, finalDep - 0.5)

                            env = PathUtils.getEnvelope(
                                base.Shape,
                                subshape=profShape,
                                depthparams=custDepthparams)
                            tup = env, False, 'pathProfileFaces', angle, axis, strDep, finalDep
                            shapes.append(tup)

            # Lower high Start Depth to top of Stock
            startDepth = max(startDepths)
            if obj.StartDepth.Value > startDepth:
                obj.StartDepth.Value = startDepth

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

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

        self.removalshapes = shapes  # pylint: disable=attribute-defined-outside-init
        PathLog.debug("%d shapes" % len(shapes))

        return shapes
Exemplo n.º 24
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