Пример #1
0
def getEnvelope(partshape, subshape=None, depthparams=None):
    '''
    getEnvelope(partshape, stockheight=None)
    returns a shape corresponding to the partshape silhouette extruded to height.
    if stockheight is given, the returned shape is extruded to that height otherwise the returned shape
    is the height of the original shape boundbox
    partshape = solid object
    stockheight = float - Absolute Z height of the top of material before cutting.
    '''
    PathLog.track(partshape, subshape, depthparams)

    # if partshape.Volume == 0.0:  #Not a 3D object
    #     return None

    zShift = 0
    if subshape is not None:
        if isinstance(subshape, Part.Face):
            PathLog.debug('processing a face')
            sec = Part.makeCompound([subshape])
        else:
            area = Path.Area(Fill=2, Coplanar=0).add(subshape)
            area.setPlane(makeWorkplane(partshape))
            PathLog.debug("About to section with params: {}".format(
                area.getParams()))
            sec = area.makeSections(heights=[0.0], project=True)[0].getShape()

    # zShift = partshape.BoundBox.ZMin - subshape.BoundBox.ZMin
        PathLog.debug('partshapeZmin: {}, subshapeZMin: {}, zShift: {}'.format(
            partshape.BoundBox.ZMin, subshape.BoundBox.ZMin, zShift))

    else:
        area = Path.Area(Fill=2, Coplanar=0).add(partshape)
        area.setPlane(makeWorkplane(partshape))
        sec = area.makeSections(heights=[0.0], project=True)[0].getShape()

    # If depthparams are passed, use it to calculate bottom and height of
    # envelope
    if depthparams is not None:
        #        eLength = float(stockheight)-partshape.BoundBox.ZMin
        eLength = depthparams.safe_height - depthparams.final_depth
        #envelopeshape = sec.extrude(FreeCAD.Vector(0, 0, eLength))
        zShift = depthparams.final_depth - sec.BoundBox.ZMin
        PathLog.debug('boundbox zMIN: {} elength: {} zShift {}'.format(
            partshape.BoundBox.ZMin, eLength, zShift))
    else:
        eLength = partshape.BoundBox.ZLength - sec.BoundBox.ZMin

    # Shift the section based on selection and depthparams.
    newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift),
                                 sec.Placement.Rotation)
    sec.Placement = newPlace

    # Extrude the section to top of Boundbox or desired height
    envelopeshape = sec.extrude(FreeCAD.Vector(0, 0, eLength))
    if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG:
        removalshape = FreeCAD.ActiveDocument.addObject(
            "Part::Feature", "Envelope")
        removalshape.Shape = envelopeshape
    return envelopeshape
Пример #2
0
    def _extractFaceOffset(self, obj, fcShape, isHole):
        '''_extractFaceOffset(obj, fcShape, isHole) ... internal function.
            Original _buildPathArea() version copied from PathAreaOp.py module.  This version is modified.
            Adjustments made based on notes by @sliptonic - https://github.com/sliptonic/FreeCAD/wiki/PathArea-notes.'''
        PathLog.debug('_extractFaceOffset()')

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

        if isHole is False:
            offset = 0 - offset

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

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

        return area.getShape()
Пример #3
0
    def _buildPathArea(self, obj, baseobject, isHole, start, getsim):
        '''_buildPathArea(obj, baseobject, isHole, start, getsim) ... internal function.'''
        # pylint: disable=unused-argument
        PathLog.track()
        area = Path.Area()
        area.setPlane(PathUtils.makeWorkplane(baseobject))
        area.add(baseobject)

        areaParams = self.areaOpAreaParams(obj, isHole) # pylint: disable=assignment-from-no-return
        if hasattr(obj, 'ExpandProfile') and obj.ExpandProfile != 0:
            areaParams = self.areaOpAreaParamsExpandProfile(obj, isHole) # pylint: disable=assignment-from-no-return

        heights = [i for i in self.depthparams]
        PathLog.debug('depths: {}'.format(heights))
        area.setParams(**areaParams)
        obj.AreaParams = str(area.getParams())

        PathLog.debug("Area with params: {}".format(area.getParams()))

        sections = area.makeSections(mode=0, project=self.areaOpUseProjection(obj), heights=heights)
        PathLog.debug("sections = %s" % sections)
        shapelist = [sec.getShape() for sec in sections]
        PathLog.debug("shapelist = %s" % shapelist)

        pathParams = self.areaOpPathParams(obj, isHole) # pylint: disable=assignment-from-no-return
        pathParams['shapes'] = shapelist
        pathParams['feedrate'] = self.horizFeed
        pathParams['feedrate_v'] = self.vertFeed
        pathParams['verbose'] = True
        pathParams['resume_height'] = obj.SafeHeight.Value
        pathParams['retraction'] = obj.ClearanceHeight.Value
        pathParams['return_end'] = True
        # Note that emitting preambles between moves breaks some dressups and prevents path optimization on some controllers
        pathParams['preamble'] = False

        if not self.areaOpRetractTool(obj):
            pathParams['threshold'] = 2.001 * self.radius

        if self.endVector is not None:
            pathParams['start'] = self.endVector
        elif PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint:
            pathParams['start'] = obj.StartPoint

        obj.PathParams = str({key: value for key, value in pathParams.items() if key != 'shapes'})
        PathLog.debug("Path with params: {}".format(obj.PathParams))

        (pp, end_vector) = Path.fromShapes(**pathParams)
        PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
        self.endVector = end_vector # pylint: disable=attribute-defined-outside-init

        simobj = None
        if getsim:
            areaParams['Thicken'] = True
            areaParams['ToolRadius'] = self.radius - self.radius * .005
            area.setParams(**areaParams)
            sec = area.makeSections(mode=0, project=False, heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0, baseobject.BoundBox.ZMax))

        return pp, simobj
Пример #4
0
    def _buildPathArea(self, obj, baseobject, start=None, getsim=False):
        PathLog.track()
        profile = Path.Area()
        profile.setPlane(makeWorkplane(baseobject))
        profile.add(baseobject)

        profileparams = {'Fill': 0, 'Coplanar': 2}

        if obj.UseComp is False:
            profileparams['Offset'] = 0.0
        else:
            profileparams['Offset'] = self.radius + obj.OffsetExtra.Value

        heights = [i for i in self.depthparams]
        PathLog.debug('depths: {}'.format(heights))
        profile.setParams(**profileparams)
        #obj.AreaParams = str(profile.getParams())

        PathLog.debug("Contour with params: {}".format(profile.getParams()))
        sections = profile.makeSections(mode=0, project=True, heights=heights)
        shapelist = [sec.getShape() for sec in sections]

        params = {
            'shapes': shapelist,
            'feedrate': self.horizFeed,
            'feedrate_v': self.vertFeed,
            'verbose': True,
            'resume_height': obj.StepDown.Value,
            'retraction': obj.ClearanceHeight.Value,
            'return_end': True
        }

        if obj.Direction == 'CCW':
            params['orientation'] = 1
        else:
            params['orientation'] = 0

        if self.endVector is not None:
            params['start'] = self.endVector
        elif start is not None:
            params['start'] = start

        (pp, end_vector) = Path.fromShapes(**params)
        PathLog.debug("Generating Path with params: {}".format(params))
        PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
        self.endVector = end_vector

        simobj = None
        if getsim:
            profileparams[
                'Thicken'] = True  #{'Fill':0, 'Coplanar':0, 'Project':True, 'SectionMode':2, 'Thicken':True}
            profileparams['ToolRadius'] = self.radius - self.radius * .005
            profile.setParams(**profileparams)
            sec = profile.makeSections(mode=0, project=False,
                                       heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0,
                                                baseobject.BoundBox.ZMax))

        return pp, simobj
Пример #5
0
    def _buildPathArea(self, obj, baseobject, start=None):
        PathLog.track()
        profile = Path.Area()
        profile.setPlane(makeWorkplane(baseobject))
        profile.add(baseobject)

        profileparams = {'Fill': 0, 'Coplanar': 0}

        if obj.UseComp is False:
            profileparams['Offset'] = 0.0
        else:
            profileparams['Offset'] = self.radius + obj.OffsetExtra.Value

        depthparams = depth_params(clearance_height=obj.ClearanceHeight.Value,
                                   rapid_safety_space=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)

        PathLog.debug('depths: {}'.format(depthparams.get_depths()))
        profile.setParams(**profileparams)
        PathLog.debug("Contour with params: {}".format(profile.getParams()))

        sections = profile.makeSections(mode=0,
                                        project=True,
                                        heights=depthparams.get_depths())
        shapelist = [sec.getShape() for sec in sections]

        params = {
            'shapes': shapelist,
            'feedrate': self.horizFeed,
            'feedrate_v': self.vertFeed,
            'verbose': True,
            'resume_height': obj.StepDown.Value,
            'retraction': obj.ClearanceHeight.Value,
            'return_end': True
        }

        if obj.Direction == 'CCW':
            params['orientation'] = 1
        else:
            params['orientation'] = 0

        if self.endVector is not None:
            params['start'] = self.endVector
        elif start is not None:
            params['start'] = start

        (pp, end_vector) = Path.fromShapes(**params)
        PathLog.debug("Generating Path with params: {}".format(params))
        PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
        self.endVector = end_vector

        return pp
Пример #6
0
    def _buildPathArea(self, obj, baseobject):
        """build the face path using PathArea"""

        PathLog.track()
        boundary = Path.Area()
        boundary.setPlane(makeWorkplane(baseobject))
        boundary.add(baseobject)

        stepover = (self.radius * 2) * (float(obj.StepOver)/100)

        pocketparams = {'Fill': 0,
                        'Coplanar': 0,
                        'PocketMode': 1,
                        'SectionCount': -1,
                        'Angle': obj.ZigZagAngle,
                        'FromCenter': (obj.StartAt == "Center"),
                        'PocketStepover': stepover,
                        'PocketExtraOffset': 0 - obj.PassExtension.Value}

        Pattern = ['ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid', 'Triangle']
        pocketparams['PocketMode'] = Pattern.index(obj.OffsetPattern) + 1

        offsetval = self.radius
        pocketparams['ToolRadius'] = offsetval

        heights = [i for i in self.depthparams]
        boundary.setParams(**pocketparams)
        obj.AreaParams = str(boundary.getParams())
        sections = boundary.makeSections(mode=0, project=False, heights=heights)

        params = {'feedrate': self.horizFeed,
                  'feedrate_v': self.vertFeed,
                  'verbose': True,
                  'resume_height': obj.StepDown,
                  'retraction': obj.ClearanceHeight.Value}

        pp = []

        if obj.UseStartPoint and obj.StartPoint is not None:
            params['start'] = obj.StartPoint

        # store the params for debugging. Don't need the shape.
        obj.PathParams = str(params)
        PathLog.debug("Generating Path with params: {}".format(params))

        for sec in sections:
            shape = sec.getShape()
            respath = Path.fromShapes(shape, **params)
            # Insert any entry code to the layer

            # append the layer path
            pp.extend(respath.Commands)
            respath.Commands = pp

        return respath
Пример #7
0
    def _buildPathArea(self, obj, baseobject):
        """build the face path using PathArea"""

        PathLog.track()
        boundary = Path.Area()
        boundary.setPlane(makeWorkplane(baseobject))
        boundary.add(baseobject)

        stepover = (self.radius * 2) * (float(obj.StepOver) / 100)

        pocketparams = {
            'Fill': 0,
            'Coplanar': 0,
            'PocketMode': 1,
            'SectionCount': -1,
            'Angle': obj.ZigZagAngle,
            'FromCenter': (obj.StartAt == "Center"),
            'PocketStepover': stepover,
            'PocketExtraOffset': 0 - obj.PassExtension.Value
        }

        Pattern = [
            'ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid',
            'Triangle'
        ]
        pocketparams['PocketMode'] = Pattern.index(obj.OffsetPattern) + 1

        offsetval = self.radius
        pocketparams['ToolRadius'] = offsetval

        heights = [i for i in self.depthparams]
        boundary.setParams(**pocketparams)
        #obj.AreaParams = str(boundary.getParams())
        #PathLog.track('areaparams: {}'.format(obj.AreaParams))
        PathLog.track('height: {}'.format(heights))
        sections = boundary.makeSections(mode=0,
                                         project=False,
                                         heights=heights)
        shapelist = [sec.getShape() for sec in sections]

        params = {
            'shapes': shapelist,
            'feedrate': self.horizFeed,
            'feedrate_v': self.vertFeed,
            'verbose': True,
            'resume_height': obj.StepDown,
            'retraction': obj.ClearanceHeight.Value
        }

        PathLog.debug("Generating Path with params: {}".format(params))
        pp = Path.fromShapes(**params)

        return pp
Пример #8
0
    def _buildPathArea(self, obj, baseobject, isHole, start, getsim):
        '''_buildPathArea(obj, baseobject, isHole, start, getsim) ... internal function.'''
        PathLog.track()
        area = Path.Area()
        area.setPlane(PathUtils.makeWorkplane(baseobject))
        area.add(baseobject)

        areaParams = self.areaOpAreaParams(obj, isHole)

        heights = [i for i in self.depthparams]
        PathLog.debug('depths: {}'.format(heights))
        area.setParams(**areaParams)
        obj.AreaParams = str(area.getParams())

        PathLog.debug("Area with params: {}".format(area.getParams()))

        sections = area.makeSections(mode=0, project=self.areaOpUseProjection(obj), heights=heights)
        PathLog.debug("sections = %s" % sections)
        shapelist = [sec.getShape() for sec in sections]
        PathLog.debug("shapelist = %s" % shapelist)

        pathParams = self.areaOpPathParams(obj, isHole)
        pathParams['shapes'] = shapelist
        pathParams['feedrate'] = self.horizFeed
        pathParams['feedrate_v'] = self.vertFeed
        pathParams['verbose'] = True
        pathParams['resume_height'] = obj.StepDown.Value
        pathParams['retraction'] = obj.ClearanceHeight.Value
        pathParams['return_end'] = True

        if self.endVector is not None:
            pathParams['start'] = self.endVector
        elif PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint:
            pathParams['start'] = obj.StartPoint

        obj.PathParams = str({key: value for key, value in pathParams.items() if key != 'shapes'})
        PathLog.debug("Path with params: {}".format(obj.PathParams))

        (pp, end_vector) = Path.fromShapes(**pathParams)
        PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
        self.endVector = end_vector

        simobj = None
        if getsim:
            areaParams['Thicken'] = True
            areaParams['ToolRadius'] = self.radius - self.radius * .005
            area.setParams(**areaParams)
            sec = area.makeSections(mode=0, project=False, heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0, baseobject.BoundBox.ZMax))

        return pp, simobj
    def get_part_outline(self):
        '''
        Get Part Outline
        '''
        sections = Path.Area().add(self.model[0].Shape).makeSections(
            mode=0, heights=[0.0], project=True, plane=self.stock_silhoutte)
        part_silhoutte = sections[0].setParams(Offset=0.0).getShape()
        part_bound_face = sections[0].setParams(Offset=0.1).getShape()
        path_area = self.stock_silhoutte.cut(part_silhoutte)

        part_edges = []
        part_segments = []

        for edge in path_area.Edges:
            edge_in = True
            for vertex in edge.Vertexes:
                if not part_bound_face.isInside(vertex.Point, 0.1, True):
                    edge_in = False

            if edge_in:
                # if self.part_edges.__contains__(edge) == False:
                part_edges.append(edge)
                vert = edge.Vertexes
                pt1 = Point(vert[0].X, vert[0].Y, vert[0].Z)
                pt2 = Point(vert[-1].X, vert[-1].Y, vert[-1].Z)
                seg = Segment(pt1, pt2)

                if isinstance(edge.Curve, Part.Circle):
                    # rad = edge.Curve.Radius
                    # angle = 2 * math.asin((seg.get_length()/2) / rad)
                    line1 = Part.makeLine(edge.Curve.Location,
                                          edge.Vertexes[0].Point)
                    line2 = Part.makeLine(edge.Curve.Location,
                                          edge.Vertexes[-1].Point)
                    part_edges.append(line1)
                    part_edges.append(line2)

                    angle = edge.LastParameter - edge.FirstParameter
                    direction = edge.Curve.Axis.y
                    # print('bulge angle', direction, angle * direction)
                    # TODO: set the correct sign for the bulge +-
                    seg.set_bulge(angle * direction)

                part_segments.append(seg)

        # path_profile = Part.makeCompound(part_edges)
        # Part.show(path_profile, 'Final_pass')
        return part_segments
Пример #10
0
def getOffsetArea(
        fcShape,
        offset,
        removeHoles=False,
        # Default: XY plane
        plane=Part.makeCircle(10),
        tolerance=1e-4,
):
    """Make an offset area of a shape, projected onto a plane.
    Positive offsets expand the area, negative offsets shrink it.
    Inspired by _buildPathArea() from PathAreaOp.py module. Adjustments made
    based on notes by @sliptonic at this webpage:
    https://github.com/sliptonic/FreeCAD/wiki/PathArea-notes."""
    PathLog.debug("getOffsetArea()")

    areaParams = {}
    areaParams["Offset"] = offset
    areaParams["Fill"] = 1  # 1
    areaParams["Outline"] = removeHoles
    areaParams["Coplanar"] = 0
    areaParams["SectionCount"] = 1  # -1 = full(all per depthparams??) sections
    areaParams["Reorient"] = True
    areaParams["OpenMode"] = 0
    areaParams["MaxArcPoints"] = 400  # 400
    areaParams["Project"] = True
    areaParams["FitArcs"] = False  # Can be buggy & expensive
    areaParams["Deflection"] = tolerance
    areaParams["Accuracy"] = tolerance
    areaParams["Tolerance"] = 1e-5  # Equal point tolerance
    areaParams["Simplify"] = True
    areaParams["CleanDistance"] = tolerance / 5

    area = Path.Area()  # Create instance of Area() class object
    # Set working plane normal to Z=1
    area.setPlane(makeWorkplane(plane))
    area.add(fcShape)
    area.setParams(**areaParams)  # set parameters

    offsetShape = area.getShape()
    if not offsetShape.Faces:
        return False
    return offsetShape
Пример #11
0
def getEnvelope(partshape, stockheight=None):
    '''
    getEnvelop(partshape, stockheight=None)
    returns a shape corresponding to the partshape silhouette extruded to height.
    if stockheight is given, the returned shape is extruded to that height otherwise the returned shape
    is the height of the original shape boundbox
    partshape = solid object
    stockheight = float
    '''
    PathLog.track(partshape, stockheight)
    area = Path.Area(Fill=1, Coplanar=0).add(partshape)
    # loc = FreeCAD.Vector(partshape.BoundBox.Center.x,
    #                      partshape.BoundBox.Center.y,
    #                      partshape.BoundBox.ZMin)
    area.setPlane(makeWorkplane(partshape))
    sec = area.makeSections(heights=[1.0], project=True)[0].getShape()
    if stockheight is not None:
        return sec.extrude(FreeCAD.Vector(0, 0, stockheight))
    else:
        return sec.extrude(FreeCAD.Vector(0, 0, partshape.BoundBox.ZLength))
Пример #12
0
    def _buildPathArea(self, obj, envelopeshape, getsim=False):
        PathLog.track()
        pocket = Path.Area()
        pocket.setPlane(Part.makeCircle(10))
        pocket.add(envelopeshape)

        stepover = (self.radius * 2) * (float(obj.StepOver) / 100)

        pocketparams = {
            'Fill': 0,
            'Coplanar': 0,
            'PocketMode': 1,
            'SectionCount': -1,
            'Angle': obj.ZigZagAngle,
            'FromCenter': (obj.StartAt == "Center"),
            'PocketStepover': stepover,
            'PocketExtraOffset': obj.MaterialAllowance.Value
        }

        offsetval = self.radius
        pocketparams['ToolRadius'] = offsetval

        Pattern = [
            'ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid',
            'Triangle'
        ]
        pocketparams['PocketMode'] = Pattern.index(obj.OffsetPattern) + 1

        pocket.setParams(**pocketparams)
        obj.AreaParams = str(pocket.getParams())
        PathLog.debug("Pocketing with params: {}".format(pocket.getParams()))

        heights = [i for i in self.depthparams]
        PathLog.debug('pocket section heights: {}'.format(heights))
        sections = pocket.makeSections(mode=0, project=False, heights=heights)

        shapelist = [sec.getShape() for sec in sections]

        params = {
            'shapes': shapelist,
            'feedrate': self.horizFeed,
            'feedrate_v': self.vertFeed,
            'verbose': True,
            'resume_height': obj.StepDown.Value,
            'retraction': obj.ClearanceHeight.Value
        }

        pp = Path.fromShapes(**params)
        PathLog.debug("Generating Path with params: {}".format(params))
        PathLog.debug(pp)

        simobj = None
        if getsim:
            pocketparams['Thicken'] = True
            pocketparams['ToolRadius'] = self.radius - self.radius * .005
            pocketparams['Stepdown'] = -1
            pocket.setParams(**pocketparams)
            #pocket.makeSections(mode=0, project=False, heights=heights)
            simobj = pocket.getShape().extrude(
                FreeCAD.Vector(0, 0, obj.StepDown.Value))
            #removalshape = FreeCAD.ActiveDocument.addObject("Part::Feature", "simshape")

        return pp, simobj
Пример #13
0
    def _buildPathArea(self, obj, envelopeshape, getsim=False):
        PathLog.track()
        pocket = Path.Area()
        pocket.setPlane(Part.makeCircle(10))
        pocket.add(envelopeshape)

        stepover = (self.radius * 2) * (float(obj.StepOver)/100)

        pocketparams = {'Fill': 0,
                        'Coplanar': 0,
                        'PocketMode': 1,
                        'SectionCount': -1,
                        'Angle': obj.ZigZagAngle,
                        'FromCenter': (obj.StartAt == "Center"),
                        'PocketStepover': stepover,
                        'PocketExtraOffset': obj.MaterialAllowance.Value}

        offsetval = self.radius
        pocketparams['ToolRadius'] = offsetval

        Pattern = ['ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid', 'Triangle']
        pocketparams['PocketMode'] = Pattern.index(obj.OffsetPattern) + 1

        pocket.setParams(**pocketparams)
        obj.AreaParams = str(pocket.getParams())
        PathLog.debug("Pocketing with params: {}".format(pocket.getParams()))

        heights = [i for i in self.depthparams]
        PathLog.debug('pocket section heights: {}'.format(heights))
        sections = pocket.makeSections(mode=0, project=False, heights=heights)

        shapelist = [sec.getShape() for sec in sections]

        params = {'shapes': shapelist,
                  'feedrate': self.horizFeed,
                  'feedrate_v': self.vertFeed,
                  'verbose': True,
                  'resume_height': obj.StepDown.Value,
                  'retraction': obj.ClearanceHeight.Value}

        if obj.UseStartPoint and obj.StartPoint is not None:
            params['start'] = obj.StartPoint

            # if MinTravel is turned on, set path sorting to 3DSort
            # 3DSort shouldn't be used without a valid start point. Can cause
            # tool crash without it.
            if obj.MinTravel:
                params['sort_mode'] = 2

        obj.PathParams = str({key: value for key, value in params.items() if key != 'shapes'})

        pp = Path.fromShapes(**params)
        PathLog.debug("Generating Path with params: {}".format(params))
        PathLog.debug(pp)

        simobj = None
        if getsim:
            pocketparams['Thicken'] = True
            pocketparams['ToolRadius'] = self.radius - self.radius * .005
            pocketparams['Stepdown'] = -1
            pocket.setParams(**pocketparams)
            simobj = pocket.getShape().extrude(FreeCAD.Vector(0, 0, obj.StepDown.Value))

        return pp, simobj
Пример #14
0
    def get_part_outline(self):
        '''
        Get Part Outline
        '''
        # TODO: Revisit the edge extraction and find a more elegant method
        model = self.model[0].Shape
        # get a section through the part origin on the XZ Plane
        sections = Path.Area().add(model).makeSections(
            mode=0, heights=[0.0], project=True, plane=self.stock_silhoutte)
        part_silhoutte = sections[0].setParams(Offset=0.0).getShape()
        # get an offset section larger than the part section
        part_bound_face = sections[0].setParams(Offset=0.1).getShape()

        # ensure the cutplane is larger than the part or segments will be missed
        modelBB = model.BoundBox
        plane_length = modelBB.ZLength * 1.5
        plane_width = (modelBB.XLength / 2) * 1.5
        z_ref = modelBB.ZMax + (plane_length - modelBB.ZLength) / 2

        # create a plane larger than the part
        cut_plane = Part.makePlane(plane_length, plane_width,
                                   FreeCAD.Vector(-plane_width, 0, z_ref),
                                   FreeCAD.Vector(0, -1, 0))
        # Cut the part section from the cut plane
        path_area = cut_plane.cut(part_silhoutte)

        part_edges = []
        part_segments = []

        # interate through the edges and check if each is inside the bound_face
        for edge in path_area.Edges:
            edge_in = True
            for vertex in edge.Vertexes:
                if not part_bound_face.isInside(vertex.Point, 0.1, True):
                    edge_in = False

            if edge_in:
                part_edges.append(edge)
                vert = edge.Vertexes
                pt1 = Point(vert[0].X, vert[0].Y, vert[0].Z)
                pt2 = Point(vert[-1].X, vert[-1].Y, vert[-1].Z)
                seg = Segment(pt1, pt2)

                if isinstance(edge.Curve, Part.Circle):
                    line1 = Part.makeLine(edge.Curve.Location,
                                          edge.Vertexes[0].Point)
                    line2 = Part.makeLine(edge.Curve.Location,
                                          edge.Vertexes[-1].Point)
                    part_edges.append(line1)
                    part_edges.append(line2)

                    angle = edge.LastParameter - edge.FirstParameter
                    direction = edge.Curve.Axis.y
                    # print('bulge angle', direction, angle * direction)
                    # TODO: set the correct sign for the bulge +-
                    seg.set_bulge(angle * direction)

                part_segments.append(seg)

        # path_profile = Part.makeCompound(part_edges)
        # Part.show(path_profile, 'Final_pass')
        return part_segments
Пример #15
0
    def _buildPathArea(self, obj, baseobject, isHole, start, getsim):
        """_buildPathArea(obj, baseobject, isHole, start, getsim) ... internal function."""
        PathLog.track()
        area = Path.Area()
        area.setPlane(PathUtils.makeWorkplane(baseobject))
        area.add(baseobject)

        areaParams = self.areaOpAreaParams(obj, isHole)

        heights = [i for i in self.depthparams]
        PathLog.debug("depths: {}".format(heights))
        area.setParams(**areaParams)
        obj.AreaParams = str(area.getParams())

        PathLog.debug("Area with params: {}".format(area.getParams()))

        sections = area.makeSections(mode=0,
                                     project=self.areaOpUseProjection(obj),
                                     heights=heights)
        PathLog.debug("sections = %s" % sections)
        shapelist = [sec.getShape() for sec in sections]
        PathLog.debug("shapelist = %s" % shapelist)

        pathParams = self.areaOpPathParams(obj, isHole)
        pathParams["shapes"] = shapelist
        pathParams["feedrate"] = self.horizFeed
        pathParams["feedrate_v"] = self.vertFeed
        pathParams["verbose"] = True
        pathParams["resume_height"] = obj.SafeHeight.Value
        pathParams["retraction"] = obj.ClearanceHeight.Value
        pathParams["return_end"] = True
        # Note that emitting preambles between moves breaks some dressups and prevents path optimization on some controllers
        pathParams["preamble"] = False

        if not self.areaOpRetractTool(obj):
            pathParams["threshold"] = 2.001 * self.radius

        if self.endVector is not None:
            pathParams["start"] = self.endVector
        elif PathOp.FeatureStartPoint & self.opFeatures(
                obj) and obj.UseStartPoint:
            pathParams["start"] = obj.StartPoint

        obj.PathParams = str({
            key: value
            for key, value in pathParams.items() if key != "shapes"
        })
        PathLog.debug("Path with params: {}".format(obj.PathParams))

        (pp, end_vector) = Path.fromShapes(**pathParams)
        PathLog.debug("pp: {}, end vector: {}".format(pp, end_vector))
        self.endVector = end_vector

        simobj = None
        if getsim:
            areaParams["Thicken"] = True
            areaParams["ToolRadius"] = self.radius - self.radius * 0.005
            area.setParams(**areaParams)
            sec = area.makeSections(mode=0, project=False,
                                    heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0,
                                                baseobject.BoundBox.ZMax))

        return pp, simobj
Пример #16
0
    def _buildPathArea(self, obj, baseobject, start=None, getsim=False):
        PathLog.track()
        profile = Path.Area()
        profile.setPlane(Part.makeCircle(10))
        profile.add(baseobject)

        profileparams = {
            'Fill': 0,
            'Coplanar': 0,
            'Offset': 0.0,
            'SectionCount': -1
        }

        if obj.UseComp:
            if obj.Side == 'Right':
                profileparams[
                    'Offset'] = 0 - self.radius + obj.OffsetExtra.Value
            else:
                profileparams['Offset'] = self.radius + obj.OffsetExtra.Value

        profile.setParams(**profileparams)
        obj.AreaParams = str(profile.getParams())

        PathLog.debug("About to profile with params: {}".format(
            profile.getParams()))

        heights = [i for i in self.depthparams]
        sections = profile.makeSections(mode=0, project=True, heights=heights)
        shapelist = [sec.getShape() for sec in sections]

        params = {
            'shapes': shapelist,
            'feedrate': self.horizFeed,
            'feedrate_v': self.vertFeed,
            'verbose': False,
            'resume_height': obj.StepDown.Value,
            'retraction': obj.ClearanceHeight.Value
        }

        if obj.Direction == 'CCW':
            params['orientation'] = 0
        else:
            params['orientation'] = 1

        if obj.UseStartPoint is True and obj.StartPoint is not None:
            params['start'] = obj.StartPoint

        pp = Path.fromShapes(**params)
        PathLog.debug("Generating Path with params: {}".format(params))

        # store the params for debugging. Don't need the shape.
        obj.PathParams = str(
            {key: value
             for key, value in params.items() if key != 'shapes'})

        simobj = None
        if getsim:
            profileparams['Thicken'] = True
            profileparams['ToolRadius'] = self.radius - self.radius * .005
            profile.setParams(**profileparams)
            sec = profile.makeSections(mode=0, project=False,
                                       heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0,
                                                baseobject.BoundBox.ZMax))

        return pp, simobj
Пример #17
0
    def _buildPathArea(self, obj, baseobject, start=None, getsim=False):
        PathLog.track()
        profile = Path.Area()
        profile.setPlane(makeWorkplane(baseobject))
        profile.add(baseobject)

        profileparams = {'Fill': 0, 'Coplanar': 2}

        if obj.UseComp is False:
            profileparams['Offset'] = 0.0
        else:
            profileparams['Offset'] = self.radius + obj.OffsetExtra.Value

        jointype = ['Round', 'Square', 'Miter']
        profileparams['JoinType'] = jointype.index(obj.JoinType)

        if obj.JoinType == 'Miter':
            profileparams['MiterLimit'] = obj.MiterLimit

        heights = [i for i in self.depthparams]
        PathLog.debug('depths: {}'.format(heights))
        profile.setParams(**profileparams)
        obj.AreaParams = str(profile.getParams())

        PathLog.debug("Contour with params: {}".format(profile.getParams()))
        sections = profile.makeSections(mode=0, project=True, heights=heights)
        shapelist = [sec.getShape() for sec in sections]

        params = {
            'shapes': shapelist,
            'feedrate': self.horizFeed,
            'feedrate_v': self.vertFeed,
            'verbose': True,
            'resume_height': obj.StepDown.Value,
            'retraction': obj.ClearanceHeight.Value,
            'return_end': True
        }

        if obj.Direction == 'CCW':
            params['orientation'] = 0
        else:
            params['orientation'] = 1

        if self.endVector is not None:
            params['start'] = self.endVector
        elif obj.UseStartPoint:
            params['start'] = obj.StartPoint

        obj.PathParams = str(
            {key: value
             for key, value in params.items() if key != 'shapes'})

        (pp, end_vector) = Path.fromShapes(**params)
        PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
        self.endVector = end_vector

        simobj = None
        if getsim:
            profileparams['Thicken'] = True
            profileparams['ToolRadius'] = self.radius - self.radius * .005
            profile.setParams(**profileparams)
            sec = profile.makeSections(mode=0, project=False,
                                       heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0,
                                                baseobject.BoundBox.ZMax))

        return pp, simobj
Пример #18
0
    def _buildPathArea(self, obj, baseobject, isHole=False, start=None, getsim=False):
        PathLog.track()
        profile = Path.Area()
        profile.setPlane(Part.makeCircle(10))
        profile.add(baseobject)

        profileparams = {'Fill': 0,
                         'Coplanar': 2,
                         'Offset': 0.0,
                         'SectionCount': -1}

        offsetval = 0

        if obj.UseComp:
            offsetval = self.radius+obj.OffsetExtra.Value

        if obj.Side == 'Inside':
            offsetval = 0 - offsetval

        if isHole:
            offsetval = 0 - offsetval

        profileparams['Offset'] = offsetval

        jointype = ['Round', 'Square', 'Miter']
        profileparams['JoinType'] = jointype.index(obj.JoinType)

        if obj.JoinType == 'Miter':
            profileparams['MiterLimit'] = obj.MiterLimit

        profile.setParams(**profileparams)
        obj.AreaParams = str(profile.getParams())

        # PathLog.debug("About to profile with params: {}".format(profileparams))
        PathLog.debug("About to profile with params: {}".format(profile.getParams()))

        heights = [i for i in self.depthparams]

        sections = profile.makeSections(mode=0, project=True, heights=heights)
        shapelist = [sec.getShape() for sec in sections]

        params = {'shapes': shapelist,
                  'feedrate': self.horizFeed,
                  'feedrate_v': self.vertFeed,
                  'verbose': True,
                  'resume_height': obj.StepDown.Value,
                  'retraction': obj.ClearanceHeight.Value}

        # Reverse the direction for holes
        if isHole:
            direction = "CW" if obj.Direction == "CCW" else "CCW"
        else:
            direction = obj.Direction

        if direction == 'CCW':
            params['orientation'] = 0
        else:
            params['orientation'] = 1

        if obj.UseStartPoint is True and obj.StartPoint is not None:
            params['start'] = obj.StartPoint

        pp = Path.fromShapes(**params)

        obj.PathParams = str({key: value for key, value in params.items() if key != 'shapes'})

        PathLog.debug("Generating Path with params: {}".format(params))
        PathLog.debug(pp)

        simobj = None
        if getsim:
            profileparams['Thicken'] = True
            profileparams['ToolRadius'] = self.radius - self.radius * .005
            profile.setParams(**profileparams)
            sec = profile.makeSections(mode=0, project=False, heights=heights)[-1].getShape()
            simobj = sec.extrude(FreeCAD.Vector(0, 0, baseobject.BoundBox.ZMax))

        return pp, simobj