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
Example #2
0
def circle_hollow(params,document):
        od = params['D']
        t = params['t']
        l = params['l']
        name = params['name']

        id = od - t

        outer = Part.Wire(Part.makeCircle(0.5*od))
        inner = Part.Wire(Part.makeCircle(0.5*id))
        face = Part.makeFace([outer, inner], "Part::FaceMakerBullseye")

        if params['arch']:
                part = Arch.makeStructure(name=name)

                prof = document.addObject("Part::Feature","Profile")
                prof.Shape = face
                part.Base = prof

                part.Height = l
        else:
                part = document.addObject("Part::Feature","BOLTS_part")
                part.Label = name

                beam = face.extrude(Vector(0,0,l))
                part.Shape = beam
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all wires formed by the base edges.'''
        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 = []
        if obj.Base:
            basewires = []

            for b in obj.Base:
                edgelist = []
                for sub in b[1]:
                    edgelist.append(getattr(b[0].Shape, sub))
                basewires.append((b[0], findWires(edgelist)))

            for base,wires in basewires:
                for wire in wires:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')

                    # shift the compound to the bottom of the base object for
                    # proper sectioning
                    zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin
                    newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation)
                    f.Placement = newPlace
                    env = PathUtils.getEnvelope(base.Shape, subshape=f, depthparams=self.depthparams)
                    shapes.append((env, False))
        return shapes
Example #4
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()

        if obj.Base:
            PathLog.debug("base items exist.  Processing...")
            removalshapes = []
            for b in obj.Base:
                PathLog.debug("Base item: {}".format(b))
                for sub in b[1]:
                    if "Face" in sub:
                        shape = Part.makeCompound([getattr(b[0].Shape, sub)])
                    else:
                        edges = [getattr(b[0].Shape, sub) for sub in b[1]]
                        shape = Part.makeFace(edges, 'Part::FaceMakerSimple')

                    env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=shape, depthparams=self.depthparams)
                    obj.removalshape = env.cut(self.baseobject.Shape)
                    removalshapes.append((obj.removalshape, False))
        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")

            env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=None, depthparams=self.depthparams)
            obj.removalshape = env.cut(self.baseobject.Shape)
            removalshapes = [(obj.removalshape, False)]
        return removalshapes
Example #5
0
def smBase(thk=2.0,
           length=10.0,
           radius=1.0,
           Side="Inside",
           midplane=False,
           reverse=False,
           MainObject=None):
    WireList = MainObject.Shape.Wires[0]
    mat = MainObject.getGlobalPlacement()
    normal = mat.multVec(FreeCAD.Vector(0, 0, 1))
    #print(sketch_normal)
    if WireList.isClosed():
        sketch_face = Part.makeFace(MainObject.Shape.Wires,
                                    "Part::FaceMakerBullseye")
        wallSolid = sketch_face.extrude(sketch_face.normalAt(0, 0) * thk)
    else:
        if len(WireList.Edges) > 1:
            if midplane:
                WireList.translate(normal * length / 2.0)
                wire_extr = WireList.extrude(normal * -length)
            elif reverse:
                wire_extr = WireList.extrude(normal * length)
            else:
                wire_extr = WireList.extrude(normal * -length)
            #Part.show(wire_extr,"wire_extr")
            if Side == "Middle":
                wire_extr = wire_extr.makeOffsetShape(-thk / 2.0,
                                                      0.0,
                                                      fill=False,
                                                      join=2)
            elif Side == "Outside":
                wire_extr = wire_extr.makeOffsetShape(-thk,
                                                      0.0,
                                                      fill=False,
                                                      join=2)
            #Part.show(wire_extr,"wire_extr")
            filleted_extr = wire_extr.makeFillet((radius + thk / 2.0),
                                                 wire_extr.Edges)
            #Part.show(filleted_extr,"filleted_extr")
            offset_extr = filleted_extr.makeOffsetShape(-thk / 2.0,
                                                        0.0,
                                                        fill=False)
            #Part.show(offset_extr,"offset_extr")
            wallSolid = filleted_extr.makeOffsetShape(thk, 0.0, fill=True)
            #Part.show(wallSolid,"wallSolid")
        else:
            if MainObject.TypeId == 'Sketcher::SketchObject':
                sketch_face = MainObject.Shape.Wires[0].extrude(normal *
                                                                -length)
                #Part.show(sketch_face)
                wallSolid = sketch_face.extrude(
                    sketch_face.Faces[0].normalAt(0, 0) * -thk)

    Gui.ActiveDocument.getObject(MainObject.Name).Visibility = False
    return wallSolid
    def execute(self, slopedPlanes):
        '''execute(self, slopedPlanes)
        Builds the shape of the slopedPlanes object.'''

        # print('execute')

        sketch = slopedPlanes.Base
        shape = sketch.Shape.copy()
        shape.Placement = P()

        self.declareSlopedPlanes(slopedPlanes)

        # print(self.OnChanged, self.slopeList)

        if self.OnChanged and self.slopeList:
            # print('A ', self.OnChanged)

            faceList = self.reProcessFaces(slopedPlanes)
            pyFaceListNew = self.Pyth

        else:
            # print('B ', self.OnChanged)

            face = Part.makeFace(shape.Wires, slopedPlanes.FaceMaker)
            fList = face.Faces
            faceList, pyFaceListNew = self.processFaces(slopedPlanes, fList)
            self.Pyth = pyFaceListNew

        # print('pyFaceListNew ', pyFaceListNew)

        self.OnChanged = False

        endShape =\
            self.makeShells(slopedPlanes, pyFaceListNew)

        if slopedPlanes.Group:
            # print('Group')
            endShape = self.groupping(slopedPlanes, endShape)

        if slopedPlanes.Thickness:
            # print('Thickness')
            endShape = self.fattening(slopedPlanes, faceList, endShape)

        if not slopedPlanes.Complement:
            endShape.complement()

        endShape.removeInternalWires(True)

        if slopedPlanes.Solid:
            endShape = Part.makeSolid(endShape)

        # print(endShape.Placement)

        slopedPlanes.Shape = endShape
Example #7
0
 def sweep_wire(self, w, solid=False):
     faces = []
     for e in w.Edges:
         faces.append(self.sweep_edge(e, solid))
     shell = Part.Shell(faces)
     shell.sewShape()
     if solid:
         cyl = Part.makeCylinder(self.max_radius * 2,
                                 self.nb_of_turns * self.lead)
         cyl.Placement = self._placement.multiply(
             FreeCAD.Placement(FreeCAD.Vector(), FreeCAD.Vector(1, 0, 0),
                               -90))
         common = cyl.common(shell)
         cut_faces = common.Faces
         new_edges = []
         for e1 in common.Edges:
             found = False
             for e2 in shell.Edges:
                 if nurbs_tools.is_same(e1.Curve,
                                        e2.Curve,
                                        tol=1e-7,
                                        full=False):
                     found = True
                     #print("found similar edges")
                     continue
             if not found:
                 new_edges.append(e1)
         #print(len(Part.sortEdges(new_edges)))
         el1, el2 = Part.sortEdges(new_edges)[0:2]
         f1 = Part.makeFace(Part.Wire(el1), 'Part::FaceMakerSimple')
         f2 = Part.makeFace(Part.Wire(el2), 'Part::FaceMakerSimple')
         cut_faces.extend([f1, f2])
         try:
             shell = Part.Shell(cut_faces)
             shell.sewShape()
             return Part.Solid(shell)
         except Part.OCCError:
             print("Failed to create solid")
             return Part.Compound(cut_faces)
     return shell
def smBase(thk=2.0, length=10.0, radius=1.0, Side="Inside", MainObject=None):
    WireList = MainObject.Shape.Wires[0]
    #print(sketch_normal)
    if WireList.isClosed():
        sketch_face = Part.makeFace(MainObject.Shape.Wires,
                                    "Part::FaceMakerBullseye")
        wallSolid = sketch_face.extrude(sketch_face.normalAt(0, 0) * thk)
    else:
        if len(WireList.Edges) > 1:
            if Side == "Inside":
                wire = WireList.makeOffset2D(thk / 2.0,
                                             openResult=True,
                                             join=2)
            elif Side == "Outside":
                wire = WireList.makeOffset2D(-thk / 2.0,
                                             openResult=True,
                                             join=2)
            else:
                wire = WireList
            #Part.show(wire)
            filletedWire = DraftGeomUtils.filletWire(wire, (radius + thk / 2))
            #Part.show(filletedWire)
            offsetwire = filletedWire.makeOffset2D(thk / 2.0, openResult=True)
            #Part.show(offsetwire)
            sketch_face = offsetwire.makeOffset2D(thk,
                                                  openResult=True,
                                                  fill=True)
            #Part.show(sketch_face)
            Edge_Dir = sketch_face.normalAt(0, 0)
            offsetSolid = offsetwire.extrude(Edge_Dir * length)
            CutList = []
            for x in offsetSolid.Faces:
                if issubclass(type(x.Surface), Part.Plane):
                    offsetSolid = x.extrude(x.normalAt(0, 0) * -thk)
                    CutList.append(offsetSolid)
                    #Part.show(offsetSolid)
            wallSolid = sketch_face.extrude(Edge_Dir * length)
            offsetSolids = CutList[0].multiFuse(CutList[1:])
            wallSolid = wallSolid.fuse(offsetSolids)
        else:
            if MainObject.TypeId == 'Sketcher::SketchObject':
                mat = MainObject.getGlobalPlacement()
                normal = mat.multVec(FreeCAD.Vector(0, 0, 1))
                sketch_face = MainObject.Shape.Wires[0].extrude(normal *
                                                                -length)
                #Part.show(sketch_face)
                wallSolid = sketch_face.extrude(
                    sketch_face.Faces[0].normalAt(0, 0) * -thk)

    Gui.ActiveDocument.getObject(MainObject.Name).Visibility = False
    return wallSolid
def smBase(thk=2.0,
           length=10.0,
           radius=1.0,
           Side="Inside",
           midplane=False,
           reverse=False,
           MainObject=None):
    # To Get sketch normal
    WireList = MainObject.Shape.Wires[0]
    mat = MainObject.getGlobalPlacement().Rotation
    normal = (mat.multVec(FreeCAD.Vector(0, 0, 1))).normalize()
    #print([mat, normal])
    if WireList.isClosed():
        # If Cosed sketch is there, make a face & extrude it
        sketch_face = Part.makeFace(MainObject.Shape.Wires,
                                    "Part::FaceMakerBullseye")
        wallSolid = sketch_face.extrude(sketch_face.normalAt(0, 0) * thk)
    else:
        filleted_extr = modifiedWire(WireList, radius, thk, length, normal,
                                     Side, 1.0)
        #Part.show(filleted_extr,"filleted_extr")
        dist = WireList.Vertexes[0].Point.distanceToPlane(
            FreeCAD.Vector(0, 0, 0), normal)
        #print(dist)
        slice_wire = filleted_extr.slice(normal, dist)
        #print(slice_wire)
        #Part.show(slice_wire[0],"slice_wire")
        traj = slice_wire[0]
        #Part.show(traj,"traj")
        if midplane:
            traj.translate(normal * -length / 2.0)
        elif reverse:
            traj.translate(normal * -length)

        traj_extr = traj.extrude(normal * length)
        #Part.show(traj_extr,"traj_extr")
        solidlist = []
        for face in traj_extr.Faces:
            solid = face.makeOffsetShape(thk, 0.0, fill=True)
            solidlist.append(solid)
        if len(solidlist) > 1:
            wallSolid = solidlist[0].multiFuse(solidlist[1:])
        else:
            wallSolid = solidlist[0]
        #Part.show(wallSolid,"wallSolid")

    #Part.show(wallSolid,"wallSolid")
    return wallSolid
Example #10
0
def makeFace(rib):
    if len(rib.Wires) == 1:
        wire = rib.Wires[0]
    else:
        wire = Part.Wire(rib.Edges)

    if wire.isClosed():
        try:
            return Part.makeFace(wire, "Part::FaceMakerSimple")
        except:
            FreeCAD.Console.PrintError(
                "Cannot make face from Base shape. Cannot draw solid\n")
    else:
        FreeCAD.Console.PrintError(
            "Base shape is not closed. Cannot draw solid\n")

    return None
Example #11
0
 def execute(self, obj):
     debug("\n* paramVector : execute *\n")
     if not hasattr(obj,"Origin"):
         v0 = FreeCAD.Vector(0,0,0)
     else:
         v0 = obj.Origin
     if not hasattr(obj,"Direction"):
         v1 = FreeCAD.Vector(0,0,-10)
     else:
         v1 = obj.Direction.normalize().multiply(10)
     v2 = v0.add(v1)
     line = Part.Edge(Part.LineSegment(v0,v2))
     cone = Part.makeCone(1,0,3,v2,v1,360)
     circle = Part.makeCircle(10,v0,v1.negative())
     face = Part.makeFace(circle,"Part::FaceMakerSimple")
     comp = Part.Compound([line,cone,face])
     obj.Shape = comp
     obj.ViewObject.Transparency = 50
Example #12
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return envelope over the job's Base.Shape or all Arch.Panel shapes.'''
        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)"))

        isPanel = False
        if hasattr(self.baseobject, "Proxy"):
            if isinstance(self.baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                isPanel = True
                self.baseobject.Proxy.execute(self.baseobject)
                shapes = self.baseobject.Proxy.getOutlines(self.baseobject, transform=True)
                for shape in shapes:
                    f = Part.makeFace([shape], 'Part::FaceMakerSimple')
                    thickness = self.baseobject.Group[0].Source.Thickness
                    return [(f.extrude(FreeCAD.Vector(0, 0, thickness)), False)]

        if hasattr(self.baseobject, "Shape") and not isPanel:
            return [(PathUtils.getEnvelope(partshape=self.baseobject.Shape, subshape=None, depthparams=self.depthparams), False)]
Example #13
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return envelope over the job's Base.Shape or all Arch.Panel shapes.'''
        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)"))

        isPanel = False
        if hasattr(self.baseobject, "Proxy"):
            if isinstance(self.baseobject.Proxy, ArchPanel.PanelSheet):  # process the sheet
                isPanel = True
                self.baseobject.Proxy.execute(self.baseobject)
                shapes = self.baseobject.Proxy.getOutlines(self.baseobject, transform=True)
                for shape in shapes:
                    f = Part.makeFace([shape], 'Part::FaceMakerSimple')
                    thickness = self.baseobject.Group[0].Source.Thickness
                    return [(f.extrude(FreeCAD.Vector(0, 0, thickness)), False)]

        if hasattr(self.baseobject, "Shape") and not isPanel:
            return [(PathUtils.getEnvelope(partshape=self.baseobject.Shape, subshape=None, depthparams=self.depthparams), False)]
Example #14
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... returns envelope for all wires formed by the base edges.'''
        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 = []
        if obj.Base:
            basewires = []

            zMin = None
            for b in obj.Base:
                edgelist = []
                for sub in b[1]:
                    edgelist.append(getattr(b[0].Shape, sub))
                basewires.append((b[0], findWires(edgelist)))
                if zMin is None or b[0].Shape.BoundBox.ZMin < zMin:
                    zMin = b[0].Shape.BoundBox.ZMin

            for base, wires in basewires:
                for wire in wires:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')

                    # shift the compound to the bottom of the base object for
                    # proper sectioning
                    zShift = zMin - f.BoundBox.ZMin
                    newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift),
                                                 f.Placement.Rotation)
                    f.Placement = newPlace
                    env = PathUtils.getEnvelope(base.Shape,
                                                subshape=f,
                                                depthparams=self.depthparams)
                    shapes.append((env, False))
        return shapes
Example #15
0
def smBase(thk = 2.0, length = 10.0, radius = 1.0, Side = "Inside", midplane = False, reverse = False, MainObject = None):
  # To Get sketch normal
  WireList = MainObject.Shape.Wires[0]
  mat = MainObject.getGlobalPlacement().Rotation
  normal = (mat.multVec(FreeCAD.Vector(0,0,1))).normalize()
  #print([mat, normal])
  if WireList.isClosed() :
    # If Cosed sketch is there, make a face & extrude it 
    sketch_face = Part.makeFace(MainObject.Shape.Wires,"Part::FaceMakerBullseye")
    wallSolid = sketch_face.extrude(sketch_face.normalAt(0,0) * thk)
  else :
    # If sketch is one type, make a face by extruding & offset it to correct position
    if midplane :
      WireList.translate(normal * length/2.0)
      wire_extr = WireList.extrude(normal * -length)
    elif reverse:
      wire_extr = WireList.extrude(normal * length)
    else :
      wire_extr = WireList.extrude(normal * -length)
    #Part.show(wire_extr,"wire_extr")
    if Side == "Inside" :
      wire_extr = wire_extr.makeOffsetShape(-thk/2.0, 0.0, fill = False, join = 2)
    elif Side == "Outside" :
      wire_extr = wire_extr.makeOffsetShape(thk/2.0, 0.0, fill = False, join = 2)
    #Part.show(wire_extr,"wire_extr")
    if len(WireList.Edges) > 1 :
      filleted_extr = wire_extr.makeFillet((radius + thk / 2.0), wire_extr.Edges)
      #Part.show(filleted_extr,"filleted_extr")
    else :
      filleted_extr = wire_extr
      #Part.show(filleted_extr,"filleted_extr")
    offset_extr = filleted_extr.makeOffsetShape(-thk/2.0, 0.0, fill = False)
    #Part.show(offset_extr,"offset_extr")
    wallSolid = offset_extr.makeOffsetShape(thk, 0.0, fill = True)
    #Part.show(wallSolid,"wallSolid")

  #Part.show(wallSolid,"wallSolid")
  return wallSolid
def setup(doc=None, solvertype="ccxtools"):

    # init FreeCAD document
    if doc is None:
        doc = init_doc()

    # explanation object
    # just keep the following line and change text string in get_explanation method
    manager.add_explanation_obj(
        doc, get_explanation(manager.get_header(get_information())))

    # geometric object
    v1 = vec(-200, -100, 0)
    v2 = vec(200, -100, 0)
    v3 = vec(200, 100, 0)
    v4 = vec(-200, 100, 0)
    l1 = ln(v1, v2)
    l2 = ln(v2, v3)
    l3 = ln(v3, v4)
    l4 = ln(v4, v1)
    v5 = vec(0, 0, 0)
    c1 = ci(50, v5)
    face = Part.makeFace([Part.Wire([l1, l2, l3, l4]), c1],
                         "Part::FaceMakerBullseye")
    geom_obj = doc.addObject("Part::Feature", "Hole_Plate")
    geom_obj.Shape = face.extrude(vec(0, 0, 10))
    doc.recompute()

    if FreeCAD.GuiUp:
        geom_obj.ViewObject.Document.activeView().viewAxonometric()
        geom_obj.ViewObject.Document.activeView().fitAll()

    # analysis
    analysis = ObjectsFem.makeAnalysis(doc, "Analysis")

    # solver
    if solvertype == "calculix":
        solver_obj = ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX")
    elif solvertype == "ccxtools":
        solver_obj = ObjectsFem.makeSolverCalculixCcxTools(
            doc, "CalculiXccxTools")
        solver_obj.WorkingDir = u""
    else:
        FreeCAD.Console.PrintWarning(
            "Not known or not supported solver type: {}. "
            "No solver object was created.\n".format(solvertype))
    if solvertype == "calculix" or solvertype == "ccxtools":
        solver_obj.SplitInputWriter = False
        solver_obj.AnalysisType = "static"
        solver_obj.GeometricalNonlinearity = "linear"
        solver_obj.ThermoMechSteadyState = False
        solver_obj.MatrixSolverType = "default"
        solver_obj.IterationsControlParameterTimeUse = False
        solver_obj.GeometricalNonlinearity = 'nonlinear'
        solver_obj.MaterialNonlinearity = 'nonlinear'
    analysis.addObject(solver_obj)

    # linear material
    material_obj = ObjectsFem.makeMaterialSolid(doc, "Material_lin")
    matprop = material_obj.Material
    matprop["Name"] = "CalculiX-Steel"
    matprop["YoungsModulus"] = "210000 MPa"
    matprop["PoissonRatio"] = "0.30"
    material_obj.Material = matprop
    analysis.addObject(material_obj)

    # nonlinear material
    name_nlm = "Material_nonlin"
    nonlinear_mat = ObjectsFem.makeMaterialMechanicalNonlinear(
        doc, material_obj, name_nlm)
    nonlinear_mat.YieldPoint1 = '240.0, 0.0'
    nonlinear_mat.YieldPoint2 = '270.0, 0.025'
    analysis.addObject(nonlinear_mat)
    # check solver attributes, Nonlinearity needs to be set to nonlinear

    # constraint fixed
    con_fixed = ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed")
    con_fixed.References = [(geom_obj, "Face4")]
    analysis.addObject(con_fixed)

    # pressure constraint
    con_pressure = ObjectsFem.makeConstraintPressure(doc, "ConstraintPressure")
    con_pressure.References = [(geom_obj, "Face2")]
    con_pressure.Pressure = 130.0
    con_pressure.Reversed = True
    analysis.addObject(con_pressure)

    # mesh
    from .meshes.mesh_platewithhole_tetra10 import create_nodes, create_elements
    fem_mesh = Fem.FemMesh()
    control = create_nodes(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating nodes.\n")
    control = create_elements(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating elements.\n")
    femmesh_obj = analysis.addObject(
        ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
    femmesh_obj.FemMesh = fem_mesh
    femmesh_obj.Part = geom_obj
    femmesh_obj.SecondOrderLinear = False

    doc.recompute()
    return doc
    def getExtrusionData(self,obj):

        """returns (shape,extrusion vector,placement) or None"""

        if hasattr(obj,"IfcRole"):
            role = obj.IfcRole
        else:
            role = obj.Role
        import Part,DraftGeomUtils
        data = ArchComponent.Component.getExtrusionData(self,obj)
        if data:
            if not isinstance(data[0],list):
                # multifuses not considered here
                return data
        length  = obj.Length.Value
        width = obj.Width.Value
        height = obj.Height.Value
        normal = None
        if not height:
            for p in obj.InList:
                if Draft.getType(p) in ["Floor","BuildingPart"]:
                    if p.Height.Value:
                        height = p.Height.Value
        base = None
        placement = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        return None
                    elif obj.Base.Shape.Faces:
                        if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                            return None
                        else:
                            base,placement = self.rebase(obj.Base.Shape)
                            normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                            normal = placement.inverse().Rotation.multVec(normal)
                    elif obj.Base.Shape.Wires:
                        baseface = None
                        if hasattr(obj,"FaceMaker"):
                            if obj.FaceMaker != "None":
                                try:
                                    baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                                except:
                                    FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                    return None
                                if len(baseface.Faces) > 1:
                                    baseface = baseface.Faces[0]
                                normal = baseface.normalAt(0,0)
                        if not baseface:
                            for w in obj.Base.Shape.Wires:
                                if not w.isClosed():
                                    p0 = w.OrderedVertexes[0].Point
                                    p1 = w.OrderedVertexes[-1].Point
                                    if p0 != p1:
                                        e = Part.Line(p0,p1).toShape()
                                        w.add(e)
                                w.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(w)
                                if baseface:
                                    baseface = baseface.fuse(f)
                                else:
                                    baseface = f
                                    normal = f.normalAt(0,0)
                        base,placement = self.rebase(baseface)
                        normal = placement.inverse().Rotation.multVec(normal)
                    elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                        # closed edge
                        w = Part.Wire(obj.Base.Shape.Edges[0])
                        baseface = Part.Face(w)
                        base,placement = self.rebase(baseface)
        elif length and width and height:
            if (length > height) and (role != "Slab"):
                h2 = height/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(0,-w2,-h2)
                v4 = Vector(0,-w2,h2)
                v3 = Vector(0,w2,h2)
                v2 = Vector(0,w2,-h2)
            else:
                l2 = length/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
            import Part
            baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            base,placement = self.rebase(baseface)
        if base and placement:
            if obj.Normal.Length:
                normal = Vector(obj.Normal)
                normal = placement.inverse().Rotation.multVec(normal)
            if not normal:
                normal = Vector(0,0,1)
            if not normal.Length:
                normal = Vector(0,0,1)
            extrusion = normal
            if (length > height) and (role != "Slab"):
                if length:
                    extrusion = normal.multiply(length)
            else:
                if height:
                    extrusion = normal.multiply(height)
            return (base,extrusion,placement)
        return None
Example #18
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         if not isinstance(data[0],list):
             # multifuses not considered here
             return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     normal = None
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     base = None
     placement = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                         normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                 elif obj.Base.Shape.Wires:
                     baseface = None
                     if hasattr(obj,"FaceMaker"):
                         if obj.FaceMaker != "None":
                             try:
                                 baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                             except:
                                 FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                 return None
                             if len(baseface.Faces) > 1:
                                 baseface = baseface.Faces[0]
                             normal = baseface.normalAt(0,0)
                     if not baseface:
                         for w in obj.Base.Shape.Wires:
                             w.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(w)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                                 normal = f.normalAt(0,0)
                     base,placement = self.rebase(baseface)
                 elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                     # closed edge
                     w = Part.Wire(obj.Base.Shape.Edges[0])
                     baseface = Part.Face(w)
                     base,placement = self.rebase(baseface)
     elif length and width and height:
         if (length > height) and (obj.Role != "Slab"):
             h2 = height/2 or 0.5
             w2 = width/2 or 0.5
             v1 = Vector(0,-w2,-h2)
             v2 = Vector(0,-w2,h2)
             v3 = Vector(0,w2,h2)
             v4 = Vector(0,w2,-h2)
         else:
             l2 = length/2 or 0.5
             w2 = width/2 or 0.5
             v1 = Vector(-l2,-w2,0)
             v2 = Vector(l2,-w2,0)
             v3 = Vector(l2,w2,0)
             v4 = Vector(-l2,w2,0)
         import Part
         baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         base,placement = self.rebase(baseface)
     if base and placement:
         if obj.Normal == Vector(0,0,0):
             if not normal:
                 normal = Vector(0,0,1)
         else:
             normal = Vector(obj.Normal)
         if (length > height) and (obj.Role != "Slab"):
             extrusion = normal.multiply(length)
         else:
             extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
Example #19
0
    def execute(self, obj, getsim=False):
        commandlist = []
        sim = None

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

        parentJob = PathUtils.findParentJob(obj)
        if parentJob is None:
            return
        baseobject = parentJob.Base
        if baseobject is None:
            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)

        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."
            )
        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)"))

        if obj.Base:
            wires = []

            for b in obj.Base:
                edgelist = []
                for sub in b[1]:
                    edgelist.append(getattr(b[0].Shape, sub))
                wires.extend(findWires(edgelist))

            for wire in wires:
                f = Part.makeFace(wire, 'Part::FaceMakerSimple')

                # shift the compound to the bottom of the base object for
                # proper sectioning
                zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin
                newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift),
                                             f.Placement.Rotation)
                f.Placement = newPlace
                env = PathUtils.getEnvelope(baseobject.Shape,
                                            subshape=f,
                                            depthparams=self.depthparams)

                try:
                    (pp, sim) = self._buildPathArea(obj,
                                                    baseobject=env,
                                                    start=obj.StartPoint,
                                                    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
        obj.ViewObject.Visibility = True
        return sim
Example #20
0
def rectangle_hollow(params,document):
        h = params['h']
        b = params['b']
        t = params['t']
        l = params['l']
        name = params['name']

        ## Definition in EN standard
        ri=1.0*t
        ro=1.5*t

        # outer rectangle, going clockwise
        Vor1 = Vector((b/2),(h/2-ro),0)
        Vor2 = Vector((b/2),(-h/2+ro),0)
        Vor3 = Vector((b/2-ro),(-h/2),0)
        Vor4 = Vector((-b/2+ro),-h/2,0)
        Vor5 = Vector(-b/2,(-h/2+ro),0)
        Vor6 = Vector(-b/2,(h/2-ro),0)
        Vor7 = Vector((-b/2+ro),(h/2),0)
        Vor8 = Vector((b/2-ro),(h/2),0)
        Lor1 = makeLine(Vor1,Vor2)
        Lor2 = makeLine(Vor3,Vor4)
        Lor3 = makeLine(Vor5,Vor6)
        Lor4 = makeLine(Vor7,Vor8)

        # outer radius, going clockwise
        Voc1 = Vector((b/2-ro),(-h/2+ro),0)
        Voc2 = Vector((-b/2+ro),(-h/2+ro),0)
        Voc3 = Vector((-b/2+ro),(h/2-ro),0)
        Voc4= Vector((b/2-ro),(h/2-ro),0)
        normal = Vector(0,0,1)
        Coc1 = makeCircle(ro,Voc1,normal,270,  0)
        Coc2 = makeCircle(ro,Voc2,normal,180,270)
        Coc3 = makeCircle(ro,Voc3,normal, 90,180)
        Coc4 = makeCircle(ro,Voc4,normal,  0, 90)

        # inner rectangle, going clockwise
        Vir1 = Vector((b/2-t),(h/2-t-ri),0)
        Vir2 = Vector((b/2-t),(-h/2+t+ri),0)
        Vir3 = Vector((b/2-t-ri),(-h/2+t),0)
        Vir4 = Vector((-b/2+t+ri),(-h/2+t),0)
        Vir5 = Vector((-b/2+t),(-h/2+t+ri),0)
        Vir6 = Vector((-b/2+t),(h/2-t-ri),0)
        Vir7 = Vector((-b/2+t+ri),(h/2-t),0)
        Vir8 = Vector((b/2-t-ri),(h/2-t),0)
        Lir1 = makeLine(Vir1,Vir2)
        Lir2 = makeLine(Vir3,Vir4)
        Lir3 = makeLine(Vir5,Vir6)
        Lir4 = makeLine(Vir7,Vir8)

        # inner radius, going clockwise
        Vic1 = Vector((b/2-t-ri),(-h/2+t+ri),0)
        Vic2 = Vector((-b/2+t+ri),(-h/2+t+ri),0)
        Vic3 = Vector((-b/2+t+ri),(h/2-t-ri),0)
        Vic4= Vector((b/2-t-ri),(h/2-t-ri),0)
        normal = Vector(0,0,1)
        Cic1 = makeCircle(ri,Vic1,normal,270,  0)
        Cic2 = makeCircle(ri,Vic2,normal,180,270)
        Cic3 = makeCircle(ri,Vic3,normal, 90,180)
        Cic4 = makeCircle(ri,Vic4,normal,  0, 90)

        # putting the segments together, make wires, make faces, extrude them and cut them
        Wo = Part.Wire([Lor1,Coc1,Lor2,Coc2,Lor3,Coc3,Lor4,Coc4,])
        Wi = Part.Wire([Lir1,Cic1,Lir2,Cic2,Lir3,Cic3,Lir4,Cic4,])
        face = Part.makeFace([Wo, Wi], "Part::FaceMakerBullseye")

        if params['arch']:
                part = Arch.makeStructure(name=name)

                prof = document.addObject("Part::Feature","Profile")
                prof.Shape = face
                part.Base = prof

                part.Height = l
        else:
                part = document.addObject("Part::Feature","BOLTS_part")
                part.Label = name

                beam = face.extrude(Vector(0,0,l))
                part.Shape = beam
Example #21
0
def rectangle_hollow(params, document):
    h = params["h"]
    b = params["b"]
    t = params["t"]
    le = params["l"]
    name = params["name"]

    # Definition in EN standard
    ri = 1.0 * t
    ro = 1.5 * t

    # outer rectangle, going clockwise
    Vor1 = Vector((b / 2), (h / 2 - ro), 0)
    Vor2 = Vector((b / 2), (-h / 2 + ro), 0)
    Vor3 = Vector((b / 2 - ro), (-h / 2), 0)
    Vor4 = Vector((-b / 2 + ro), -h / 2, 0)
    Vor5 = Vector(-b / 2, (-h / 2 + ro), 0)
    Vor6 = Vector(-b / 2, (h / 2 - ro), 0)
    Vor7 = Vector((-b / 2 + ro), (h / 2), 0)
    Vor8 = Vector((b / 2 - ro), (h / 2), 0)
    Lor1 = makeLine(Vor1, Vor2)
    Lor2 = makeLine(Vor3, Vor4)
    Lor3 = makeLine(Vor5, Vor6)
    Lor4 = makeLine(Vor7, Vor8)

    # outer radius, going clockwise
    Voc1 = Vector((b / 2 - ro), (-h / 2 + ro), 0)
    Voc2 = Vector((-b / 2 + ro), (-h / 2 + ro), 0)
    Voc3 = Vector((-b / 2 + ro), (h / 2 - ro), 0)
    Voc4 = Vector((b / 2 - ro), (h / 2 - ro), 0)
    normal = Vector(0, 0, 1)
    Coc1 = makeCircle(ro, Voc1, normal, 270, 0)
    Coc2 = makeCircle(ro, Voc2, normal, 180, 270)
    Coc3 = makeCircle(ro, Voc3, normal, 90, 180)
    Coc4 = makeCircle(ro, Voc4, normal, 0, 90)

    # inner rectangle, going clockwise
    Vir1 = Vector((b / 2 - t), (h / 2 - t - ri), 0)
    Vir2 = Vector((b / 2 - t), (-h / 2 + t + ri), 0)
    Vir3 = Vector((b / 2 - t - ri), (-h / 2 + t), 0)
    Vir4 = Vector((-b / 2 + t + ri), (-h / 2 + t), 0)
    Vir5 = Vector((-b / 2 + t), (-h / 2 + t + ri), 0)
    Vir6 = Vector((-b / 2 + t), (h / 2 - t - ri), 0)
    Vir7 = Vector((-b / 2 + t + ri), (h / 2 - t), 0)
    Vir8 = Vector((b / 2 - t - ri), (h / 2 - t), 0)
    Lir1 = makeLine(Vir1, Vir2)
    Lir2 = makeLine(Vir3, Vir4)
    Lir3 = makeLine(Vir5, Vir6)
    Lir4 = makeLine(Vir7, Vir8)

    # inner radius, going clockwise
    Vic1 = Vector((b / 2 - t - ri), (-h / 2 + t + ri), 0)
    Vic2 = Vector((-b / 2 + t + ri), (-h / 2 + t + ri), 0)
    Vic3 = Vector((-b / 2 + t + ri), (h / 2 - t - ri), 0)
    Vic4 = Vector((b / 2 - t - ri), (h / 2 - t - ri), 0)
    normal = Vector(0, 0, 1)
    Cic1 = makeCircle(ri, Vic1, normal, 270, 0)
    Cic2 = makeCircle(ri, Vic2, normal, 180, 270)
    Cic3 = makeCircle(ri, Vic3, normal, 90, 180)
    Cic4 = makeCircle(ri, Vic4, normal, 0, 90)

    # putting the segments together, make wires, make faces, extrude them and cut them
    Wo = Part.Wire([
        Lor1,
        Coc1,
        Lor2,
        Coc2,
        Lor3,
        Coc3,
        Lor4,
        Coc4,
    ])
    Wi = Part.Wire([
        Lir1,
        Cic1,
        Lir2,
        Cic2,
        Lir3,
        Cic3,
        Lir4,
        Cic4,
    ])
    face = Part.makeFace([Wo, Wi], "Part::FaceMakerBullseye")

    if params["arch"]:
        from ArchStructure import makeStructure

        part = makeStructure(name=name)

        prof = document.addObject("Part::Feature", "Profile")
        prof.Shape = face
        part.Base = prof

        part.Height = le
    else:
        part = document.addObject("Part::Feature", "BOLTS_part")
        part.Label = name

        beam = face.extrude(Vector(0, 0, le))
        part.Shape = beam
Example #22
0
def get_elebase_sh(corner_min, size, baseheight, tm):

    from FreeCAD import Vector as vec
    from MeshPart import meshFromShape
    from Part import makeLine

    # scaled place on origin
    place_for_mesh = FreeCAD.Vector(
        -corner_min.x - size[0],
        -corner_min.y - size[1],
        0.00)

    # SRTM data resolution is 30 m = 30'000 mm in the usa
    # rest of the world is 90 m = 90'000 mm
    # it makes no sense to use values smaller than 90'000 mm
    pt_distance = 100000

    say(corner_min)
    # y is huge!, but this is ok!
    say(size)

    # base area surface mesh with heights
    # Version new
    pn1 = vec(
        0,
        0,
        0
    )
    pn2 = vec(
        pn1.x + size[0] * 2,
        pn1.y,
        0
    )
    pn3 = vec(
        pn1.x + size[0] * 2,
        pn1.y + size[1] * 2,
        0
    )
    pn4 = vec(
        pn1.x,
        pn1.y + size[1] * 2,
        0
    )
    ln1 = makeLine(pn1, pn2)
    ln2 = makeLine(pn2, pn3)
    ln3 = makeLine(pn3, pn4)
    ln4 = makeLine(pn4, pn1)
    wi = Part.Wire([ln1, ln2, ln3, ln4])
    fa = Part.makeFace([wi], "Part::FaceMakerSimple")
    msh = meshFromShape(fa, LocalLength=pt_distance)
    # move to corner_min to retrieve the heights
    msh.translate(
        corner_min.x,
        corner_min.y,
        0,
    )
    # move mesh points z-koord
    for pt_msh in msh.Points:
        # say(pt_msh.Index)
        # say(pt_msh.Vector)
        pt_tm = tm.toGeographic(pt_msh.Vector.x, pt_msh.Vector.y)
        height = get_height_single(pt_tm[0], pt_tm[1])  # mm
        # say(height)
        pt_msh.move(FreeCAD.Vector(0, 0, height))
    # move mesh back centered on origin
    msh.translate(
        -corner_min.x - size[0],
        -corner_min.y - size[1],
        -baseheight,
    )

    # create Shape from Mesh
    sh = Part.Shape()
    sh.makeShapeFromMesh(msh.Topology, 0.1)

    return sh
Example #23
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return top face'''
        # Facing is done either against base objects
        holeShape = None

        if obj.Base:
            PathLog.debug("obj.Base: {}".format(obj.Base))
            faces = []
            holes = []
            holeEnvs = []
            oneBase = [obj.Base[0][0], True]
            sub0 = getattr(obj.Base[0][0].Shape, obj.Base[0][1][0])
            minHeight = sub0.BoundBox.ZMax

            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 shape.BoundBox.ZMin < minHeight:
                            minHeight = shape.BoundBox.ZMin
                        if oneBase[0] is not b[0]:
                            oneBase[1] = False
                        if numpy.isclose(abs(shape.normalAt(0, 0).z), 1):  # horizontal face
                            for wire in shape.Wires[1:]:
                                if obj.ExcludeRaisedAreas is True:
                                    ip = self.isPocket(b[0], shape, wire)
                                    if ip is False:
                                        holes.append((b[0].Shape, wire))
                                else:
                                    holes.append((b[0].Shape, wire))
                    else:
                        PathLog.error('The base subobject, "{}," is not a face. Ignoring "{}."'.format(sub, sub))

            if obj.ExcludeRaisedAreas is True and len(holes) > 0:
                for shape, wire in holes:
                    f = Part.makeFace(wire, 'Part::FaceMakerSimple')
                    env = PathUtils.getEnvelope(shape, subshape=f, depthparams=self.depthparams)
                    holeEnvs.append(env)
                    holeShape = Part.makeCompound(holeEnvs)

            PathLog.debug("Working on a collection of faces {}".format(faces))
            planeshape = Part.makeCompound(faces)

        # If no base object, do planing of top surface of entire model
        else:
            planeshape = Part.makeCompound([base.Shape for base in self.model])
            PathLog.debug("Working on a shape {}".format(obj.Label))

        # Find the correct shape depending on Boundary shape.
        PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape))
        bb = planeshape.BoundBox
        if obj.BoundaryShape == 'Boundbox':
            bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Vector(0, 0, 1))
            env = PathUtils.getEnvelope(partshape=bbperim, depthparams=self.depthparams)
            if obj.ExcludeRaisedAreas is True and oneBase[1] is True:
                includedFaces = self.getAllIncludedFaces(oneBase[0], env, faceZ=minHeight)
                if len(includedFaces) > 0:
                    includedShape = Part.makeCompound(includedFaces)
                    includedEnv = PathUtils.getEnvelope(oneBase[0].Shape, subshape=includedShape, depthparams=self.depthparams)
                    env = env.cut(includedEnv)
        elif obj.BoundaryShape == 'Stock':
            stock = PathUtils.findParentJob(obj).Stock.Shape
            env = stock
            if obj.ExcludeRaisedAreas is True and oneBase[1] is True:
                includedFaces = self.getAllIncludedFaces(oneBase[0], stock, faceZ=minHeight)
                if len(includedFaces) > 0:
                    stockEnv = PathUtils.getEnvelope(partshape=stock, depthparams=self.depthparams)
                    includedShape = Part.makeCompound(includedFaces)
                    includedEnv = PathUtils.getEnvelope(oneBase[0].Shape, subshape=includedShape, depthparams=self.depthparams)
                    env = stockEnv.cut(includedEnv)
        else:
            env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams)

        if holeShape is not None:
            PathLog.info("Processing holes...")
            holeEnv = PathUtils.getEnvelope(partshape=holeShape, depthparams=self.depthparams)
            newEnv = env.cut(holeEnv)
            return [(newEnv, False)]
        else:
            return [(env, False)]
Example #24
0
def smBend(bendR = 1.0, bendA = 90.0, miterA1 = 0.0,miterA2 = 0.0, BendType = "Material Outside", flipped = False, unfold = False, 
            offset = 0.0, extLen = 10.0, gap1 = 0.0, gap2 = 0.0,  reliefType = "Rectangle", reliefW = 0.8, reliefD = 1.0, extend1 = 0.0, 
            extend2 = 0.0, kfactor = 0.45, ReliefFactor = 0.7, UseReliefFactor = False, selFaceNames = '', MainObject = None, 
            automiter = True, sketch = None ):

  # if sketch is as wall 
  sketches = False
  if sketch :
    if sketch.Shape.Wires[0].isClosed() :
      sketches = True
    else :
      pass

  if not(sketches) :
    miterA1List1, miterA2List1, gap1List1, gap2List1, reliefDList1, wallsolid_common_list1 = smMiter(bendR = bendR, bendA = bendA, miterA1 = miterA1, miterA2 = miterA2, flipped = flipped, extLen = extLen, gap1 = gap1, 
                                      sign = 1.0, offset = offset, gap2 = gap2, reliefD = reliefD, selFaceNames = selFaceNames, automiter = automiter, MainObject = MainObject)
    bendAflip = (bendA - 180)
    miterA1List2, miterA2List2, gap1List2, gap2List2, reliefDList2, wallsolid_common_list2 = smMiter(bendR = bendR, bendA = bendAflip, miterA1 = miterA1, miterA2 = miterA2, flipped = flipped, extLen = extLen, gap1 = gap1, 
                                      sign = -1.0, offset = offset, gap2 = gap2, reliefD = reliefD, selFaceNames = selFaceNames, automiter = automiter, MainObject = MainObject)

    miterA1List = [x if a > b else y for x, y, a, b in zip(miterA1List1, miterA1List2, wallsolid_common_list1, wallsolid_common_list2)]
    miterA2List = [x if a > b else y for x, y, a, b in zip(miterA2List1, miterA2List2, wallsolid_common_list1, wallsolid_common_list2)]
    gap1List = [max(x,y) for x, y in zip(gap1List1, gap1List2)]
    gap2List = [max(x,y) for x, y in zip(gap2List1, gap2List2)]
    reliefDList = [min(x , y) for x, y in zip(reliefDList1, reliefDList2)]

  else :
    miterA1List, miterA2List, gap1List, gap2List, reliefDList = ( [0.0],[0.0],[gap1],[gap2],[reliefD])

  thk_faceList = []
  resultSolid = MainObject
  for i, selFaceName in enumerate(selFaceNames):
    selItem = MainObject.getElement(selFaceName)
    selFace = smFace(selItem, MainObject)
    selFace = smModifiedFace(selFace, resultSolid)
    gap1, gap2 = (gap1List[i], gap2List[i])
    reliefD = reliefDList[i]

    # find the narrow edge
    thk = 999999.0
    for edge in selFace.Edges:
      if abs( edge.Length ) < thk:
        thk = abs( edge.Length )
        thkEdge = edge

    # Add as offset to  set any distance
    if UseReliefFactor :
      reliefW = thk * ReliefFactor
      reliefD = thk * ReliefFactor

    # Add Relief factor
    if BendType == "Material Outside" :
      offset = 0.0
      inside = False
    elif BendType == "Material Inside" :
      offset = -(thk + bendR)
      inside = True
    elif BendType == "Thickness Outside" :
      offset = -bendR
      inside = True
    elif BendType == "Offset" :
      if offset < 0.0 :
        inside = True
      else :
        inside = False

    # find a length edge  =  revolve axis direction
    p0 = thkEdge.valueAt(thkEdge.FirstParameter)
    for lenEdge in selFace.Edges:
      p1 = lenEdge.valueAt(lenEdge.FirstParameter)
      p2 = lenEdge.valueAt(lenEdge.LastParameter)
      if lenEdge.isSame(thkEdge):
        continue
      if (p1 - p0).Length < smEpsilon:
        revAxisV = p2 - p1
        break
      if (p2 - p0).Length < smEpsilon:
        revAxisV = p1 - p2
        break

    # find the large face connected with selected face
    list2 = resultSolid.ancestorsOfType(lenEdge, Part.Face)
    for Cface in list2 :
      if not(Cface.isSame(selFace)) :
        break

    # Produce Offset Edge
    if offset > 0.0 :
      lenEdge.translate(selFace.normalAt(0,0) * offset)

    # main Length Edge
    MlenEdge = lenEdge
    leng = MlenEdge.Length
    revAxisV.normalize()
    thkDir = Cface.normalAt(0,0) * -1
    FaceDir = selFace.normalAt(0,0)

    # Get correct size inside face
    if inside :
      e1 = MlenEdge.copy()
      e1.translate(FaceDir * offset)
      EdgeShape = e1.common(Cface)
      lenEdge = EdgeShape.Edges[0]
      Noffset1 = abs((MlenEdge.valueAt(MlenEdge.FirstParameter)-lenEdge.valueAt(lenEdge.FirstParameter)).Length)
      Noffset2 = abs((MlenEdge.valueAt(MlenEdge.LastParameter)-lenEdge.valueAt(lenEdge.LastParameter)).Length)

    # if sketch is as wall 
    sketches = False
    if sketch :
      if sketch.Shape.Wires[0].isClosed() :
        sketches = True
      else :
        pass

    if sketches :
      sketch_face = Part.makeFace(sketch.Shape.Wires, "Part::FaceMakerBullseye")
      sketch_face.translate(thkDir * -thk )
      if inside :
        sketch_face.translate(FaceDir * offset )
      sketch_Shape = lenEdge.common(sketch_face)
      sketch_Edge = sketch_Shape.Edges[0]
      gap1 = (lenEdge.valueAt(lenEdge.FirstParameter) - sketch_Edge.valueAt(sketch_Edge.FirstParameter)).Length
      gap2 = (lenEdge.valueAt(lenEdge.LastParameter) - sketch_Edge.valueAt(sketch_Edge.LastParameter)).Length

    # Get angles of adjacent face
    Agap1 = 0.0
    Agap2 = 0.0
    if inside :
      AngleList =[]
      if MlenEdge.Vertexes[0].Orientation == "Reversed" :
        vertex1 = MlenEdge.Vertexes[0]
        vertex0 = MlenEdge.Vertexes[1]
      else : 
        vertex0 = MlenEdge.Vertexes[0]
        vertex1 = MlenEdge.Vertexes[1]
      Edgelist = Cface.ancestorsOfType(vertex0, Part.Edge)
      for ed in Edgelist :
        if not(MlenEdge.isSame(ed)):
          #Part.show(ed)
          if abs((MlenEdge.valueAt(MlenEdge.FirstParameter)- ed.valueAt(ed.LastParameter)).Length)  < smEpsilon:
            lineDir = ed.valueAt(ed.LastParameter)- ed.valueAt(ed.FirstParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.FirstParameter) - MlenEdge.valueAt(MlenEdge.LastParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("1",angle)
            AngleList.append(angle)
          elif abs((MlenEdge.valueAt(MlenEdge.FirstParameter) - ed.valueAt(ed.FirstParameter)).Length) < smEpsilon:
            lineDir = ed.valueAt(ed.FirstParameter)- ed.valueAt(ed.LastParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.FirstParameter) - MlenEdge.valueAt(MlenEdge.LastParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("2",angle)
            AngleList.append(angle)

      Edgelist = Cface.ancestorsOfType(vertex1, Part.Edge)
      for ed in Edgelist :
        if not(MlenEdge.isSame(ed)):
          if abs((MlenEdge.valueAt(MlenEdge.LastParameter)- ed.valueAt(ed.FirstParameter)).Length)  < smEpsilon:
            lineDir = ed.valueAt(ed.FirstParameter)- ed.valueAt(ed.LastParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.LastParameter) - MlenEdge.valueAt(MlenEdge.FirstParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("1",angle)
            AngleList.append(angle)
          elif abs((MlenEdge.valueAt(MlenEdge.LastParameter) - ed.valueAt(ed.LastParameter)).Length) < smEpsilon:
            lineDir = ed.valueAt(ed.LastParameter)- ed.valueAt(ed.FirstParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.LastParameter) - MlenEdge.valueAt(MlenEdge.FirstParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("2",angle)
            AngleList.append(angle)
      if AngleList : 
        if AngleList[0] > 90.01 and gap1 == 0.0 :
          Agap1 = reliefW
        if AngleList[1] > 90.01 and gap2 == 0.0 :
          Agap2 = reliefW
    
    #make sure the direction verctor is correct in respect to the normal
    if (thkDir.cross(revAxisV).normalize() - FaceDir).Length < smEpsilon:
     revAxisV = revAxisV * -1

    reliefDn = reliefD
    if inside :
      reliefDn = reliefD + abs(offset)

    # CutSolids list for collecting Solids
    CutSolids = []

    # remove relief if needed
    if reliefD > 0.0 :
      if reliefW > 0.0 and ( gap1 > 0.0 or Agap1 > 0.0 ):
        reliefFace1 = smMakeReliefFace(MlenEdge, FaceDir* -1, gap1-reliefW, reliefW, reliefDn, reliefType)
        reliefSolid1 = reliefFace1.extrude(thkDir * thk)
        #Part.show(reliefSolid1)
        CutSolids.append(reliefSolid1)
      if reliefW > 0.0 and ( gap2 > 0.0 or Agap2 > 0.0 ):
        reliefFace2 = smMakeReliefFace(MlenEdge, FaceDir* -1, leng-gap2, reliefW, reliefDn, reliefType)
        reliefSolid2 = reliefFace2.extrude(thkDir * thk)
        #Part.show(reliefSolid2)
        CutSolids.append(reliefSolid2)

    # restrict angle
    if (bendA < 0):
        bendA = -bendA
        flipped = not flipped

    if not(flipped):
      revAxisP = lenEdge.valueAt(lenEdge.FirstParameter) + thkDir * (bendR + thk)
      revAxisV = revAxisV * -1
    else:
      revAxisP = lenEdge.valueAt(lenEdge.FirstParameter) + thkDir * -bendR

    # remove bend face if present
    if inside :
      if gap1 == 0.0 or (reliefD == 0.0 and  gap1 == 0.1) :
        Edgelist = selFace.ancestorsOfType(vertex0, Part.Edge)
        for ed in Edgelist :
          if not(MlenEdge.isSame(ed)):
            list1 = resultSolid.ancestorsOfType(ed, Part.Face)
            for Rface in list1 :
              if Rface.Area != selFace.Area and issubclass(type(Rface.Surface),Part.Plane) :
                for edge in Rface.Edges:
                  if issubclass(type(edge.Curve),Part.Circle):
                    RfaceE = Rface.extrude(Rface.normalAt(0,0) * -Noffset1 )
                    CutSolids.append(RfaceE)
                    break

      if gap2 == 0.0 or (reliefD == 0.0 and  gap2 == 0.1) :
        Edgelist = selFace.ancestorsOfType(vertex1, Part.Edge)
        for ed in Edgelist :
          if not(MlenEdge.isSame(ed)):
            list1 = resultSolid.ancestorsOfType(ed, Part.Face)
            for Rface in list1 :
              if Rface.Area != selFace.Area and issubclass(type(Rface.Surface),Part.Plane) :
                for edge in Rface.Edges:
                  if issubclass(type(edge.Curve),Part.Circle):
                    RfaceE = Rface.extrude(Rface.normalAt(0,0) * -Noffset2 )
                    CutSolids.append(RfaceE)
                    break

      if reliefD == 0.0 and ( gap1 == 0.1 or gap2 == 0.1 ) :
        CutFace = smMakeFace(MlenEdge, thkDir, thk, 0, 0)
      else :
        CutFace = smMakeFace(MlenEdge, thkDir, thk, gap1, gap2)
      CutSolid = CutFace.extrude(FaceDir * offset )
      CfaceSolid = Cface.extrude(thkDir * thk)
      CutSolid = CutSolid.common(CfaceSolid)
      CutSolids.append(CutSolid)

    # Produce Main Solid for Inside Bends
    if CutSolids :
      if len(CutSolids) == 1 :
        resultSolid = resultSolid.cut(CutSolids[0])
      else :
        Solid = CutSolids[0].multiFuse(CutSolids[1:])
        Solid.removeSplitter()
        #Part.show(Solid)
        resultSolid = resultSolid.cut(Solid)

    # Produce Offset Solid
    if offset > 0.0 :
      # create wall
      offset_face = smMakeFace(lenEdge, FaceDir, -offset)
      OffsetSolid = offset_face.extrude(thkDir * thk)
      resultSolid = resultSolid.fuse(OffsetSolid)

    #wallSolid = None
    if sketches :
      Wall_face = Part.makeFace(sketch.Shape.Wires, "Part::FaceMakerBullseye")
      if inside :
        Wall_face.translate(FaceDir * offset )
      FaceAxisP = sketch_Edge.valueAt(sketch_Edge.FirstParameter) + thkDir * thk
      FaceAxisV = sketch_Edge.valueAt(sketch_Edge.FirstParameter) - sketch_Edge.valueAt(sketch_Edge.LastParameter)
      Wall_face.rotate(FaceAxisP, FaceAxisV, -90.0)
      wallSolid = Wall_face.extrude(thkDir * -thk)
      #Part.show(wallSolid)
      wallSolid.rotate(revAxisP, revAxisV, bendA)

    elif extLen > 0.0 :
      # create wall
      Wall_face = smMakeFace(lenEdge, FaceDir, extLen, gap1-extend1, gap2-extend2, miterA1List[i], miterA2List[i])
      wallSolid = Wall_face.extrude(thkDir * thk)
      #Part.show(wallSolid)
      wallSolid.rotate(revAxisP, revAxisV, bendA)
      #Part.show(wallSolid.Faces[2])
      thk_faceList.append(wallSolid.Faces[2])

    # Produce bend Solid
    if not(unfold) :
      if bendA > 0.0 :
        # create bend
        # narrow the wall if we have gaps
        revFace = smMakeFace(lenEdge, thkDir, thk, gap1, gap2)
        if revFace.normalAt(0,0) != FaceDir :
          revFace.reverse()
        bendSolid = revFace.revolve(revAxisP, revAxisV, bendA)
        #Part.show(bendSolid)
        resultSolid = resultSolid.fuse(bendSolid)
      if wallSolid :
        resultSolid = resultSolid.fuse(wallSolid)

    # Produce unfold Solid
    else :
      if bendA > 0.0 :
        # create bend
        unfoldLength = ( bendR + kfactor * thk ) * bendA * math.pi / 180.0
        # narrow the wall if we have gaps
        unfoldFace = smMakeFace(lenEdge, thkDir, thk, gap1, gap2)
        if unfoldFace.normalAt(0,0) != FaceDir :
          unfoldFace.reverse()
        unfoldSolid = unfoldFace.extrude(FaceDir * unfoldLength)
        #Part.show(unfoldSolid)
        resultSolid = resultSolid.fuse(unfoldSolid)

      if extLen > 0.0 :
        wallSolid.rotate(revAxisP, revAxisV, -bendA)
        #Part.show(wallSolid)
        wallSolid.translate(FaceDir * unfoldLength)
        resultSolid = resultSolid.fuse(wallSolid)

  #Gui.ActiveDocument.getObject(MainObject.Name).Visibility = False
  #if sketch :
    #Gui.ActiveDocument.getObject(sketch.Name).Visibility = False
  return resultSolid, thk_faceList
    def doPlane(self, direction, pyWire, geom, firstParam, lastParam,
                scale, closed):

        '''doPlane(self, direction, pyWire, geom, firstParam, lastParam,
                   scale, closed)'''

        # print '# doPlane'

        # print 'scale ', scale

        size = _Py.size
        width = size
        length = 2 * size

        # print 'size ', size
        # print 'width ', width
        # print 'length ', length

        leftScale = self.leftWidth * scale
        rightScale = self.rightWidth * scale
        upScale = self.length * scale

        # print 'leftScale ', leftScale
        # print 'rightScale ', rightScale
        # print 'upScale ', upScale

        if not upScale:
            # print 'up'
            upScale = 2 * size * scale

        if scale > 1:

            if self.leftWidth < width:
                # print 'left'
                leftScale = width * scale

            if self.rightWidth < width:
                # print 'right'
                rightScale = width * scale

            if self.length < length:
                # print 'length'
                upScale = length * scale

        # print 'leftScale ', leftScale
        # print 'rightScale ', rightScale
        # print 'upScale ', upScale

        # print 'firstParam ', firstParam
        # print 'lastParam ', lastParam

        if isinstance(geom, (Part.LineSegment,
                             Part.ArcOfParabola)):
            # print 'a'

            startParam = firstParam - leftScale
            endParam = lastParam + rightScale

        elif isinstance(geom, (Part.ArcOfHyperbola)):
            # print 'b'

            startParam = firstParam
            endParam = lastParam

        elif isinstance(geom, (Part.ArcOfCircle,
                               Part.ArcOfEllipse)):
            # print 'c'

            rear = self.rear

            if rear:
                # print 'reflex'

                if len(rear) == 1:
                    # print 'c1'

                    pyReflex = self.reflexedList[0]

                    if rear[0] == pyReflex.rear[0]:
                        # print 'c11'

                        startParam = firstParam
                        endParam = startParam + 2 * pi

                    else:
                        # print 'c12'

                        startParam = lastParam
                        endParam = startParam - 2 * pi

                else:
                    # print 'c2'

                    startParam = (2 * pi - (lastParam - firstParam)) / 2 + lastParam
                    endParam = startParam + 2 * pi

            else:
                # print 'no reflex'

                dist = abs(lastParam - firstParam)
                # print 'dist ', dist

                if dist >= pi:
                    # print '2pi o more'

                    startParam = firstParam
                    endParam = lastParam

                else:
                    # print 'less 2pi'

                    center = (lastParam - firstParam) / 2 + firstParam
                    # print 'center ', center
                    startParam = center - pi / 2
                    endParam = center + pi / 2

        elif isinstance(geom, Part.BSplineCurve):
            # print 'd'

            pass

        # print 'startParam ', startParam
        # print 'endParam ', endParam

        extendGeom = self.makeGeom(geom, startParam, endParam)
        # print 'extendGeom ', extendGeom
        extendShape = extendGeom.toShape()

        if self.sweepCurve and not\
           FreeCAD.ActiveDocument.getObject(self.sweepCurve).Shape.isNull():
            # print 'A'

            angle = self.angle

            sweepSketch = FreeCAD.ActiveDocument.getObject(self.sweepCurve)
            wire = sweepSketch.Shape.copy()

            wire.Placement = FreeCAD.Placement()

            try:
                constraint = degrees(sweepSketch.Constraints[3].Value)
            except IndexError:
                constraint = 45

            angleConstraint = constraint
            ang = angle - angleConstraint
            wire.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), ang)

            geomShape = self.geomShape
            ffPoint = geomShape.firstVertex(True).Point
            llPoint = geomShape.lastVertex(True).Point

            if ffPoint == llPoint:
                # print 'a'
                edge = _Py.slopedPlanes.Shape.Edges[1]
                aa = ffPoint
                bb = edge.firstVertex(True).Point
                direction = bb.sub(aa)
            else:
                # print 'b'
                direction = llPoint.sub(ffPoint)

            aa = direction.getAngle(FreeCAD.Vector(1, 0, 0)) + pi / 2
            if ffPoint.y > llPoint.y:
                aa = aa + pi

            rotation = FreeCAD.Rotation()
            rotation.Axis = FreeCAD.Vector(1, 0, 0)
            rotation.Angle = pi / 2
            wire.Placement.Rotation =\
                rotation.multiply(wire.Placement.Rotation)

            if ffPoint == llPoint:
                # print 'aa'
                point = geom.Location
                numWire = self.numWire
                angleXU = geom.AngleXU
                # print 'angleXU ', angleXU
                rotation = FreeCAD.Rotation()
                rotation.Axis = FreeCAD.Vector(0, 0, 1)
                if numWire == 0:
                    rotation.Angle = pi + angleXU
                else:
                    rotation.Angle = angleXU
                wire.Placement.Rotation =\
                    rotation.multiply(wire.Placement.Rotation)

                wire.Placement.Base = ffPoint
                edge = wire.Edges[0]
                # print 'edge ', edge.Curve
                # print edge.firstVertex(True).Point
                # print edge.lastVertex(True).Point

                plane = edge.revolve(point, FreeCAD.Vector(0, 0, 1))

                # print plane
                # print plane.Area

                if _Py.reverse:
                    # print 'negative'
                    plane = plane.mirror(FreeCAD.Vector(0, 0, 0),
                                         FreeCAD.Vector(0, 0, -1))

                if isinstance(geom, Part.ArcOfEllipse):
                    # print 'ellipse'

                    major = geom.MajorRadius
                    minor = geom.MinorRadius

                    matrix = FreeCAD.Matrix()
                    coef = minor / major
                    matrix.scale(FreeCAD.Vector(1, coef, 1))
                    plane.translate(-1 * point)
                    plane.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), -1 * degrees(angleXU))
                    plane = plane.transformGeometry(matrix)
                    plane.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), degrees(angleXU))
                    plane.translate(point)

                plane = plane.Faces[0]

            else:
                # print 'bb'
                rotation = FreeCAD.Rotation()
                rotation.Axis = _Py.normal
                rotation.Angle = aa
                wire.Placement.Rotation =\
                    rotation.multiply(wire.Placement.Rotation)

                wire.Placement.Base = ffPoint

                extendShape = Part.Wire(extendShape)
                plane = wire.makePipeShell([extendShape])

        else:
            # print 'B'

            if closed:
                # print 'B1'

                angle = self.angle
                # print 'angle ', angle
                point = geom.Location
                # print 'point ', point
                length = self.length
                # print 'length ', length

                # print 'geom'

                if isinstance(geom, Part.ArcOfEllipse):
                    # print 'ellipse'
                    major = geom.MajorRadius
                    minor = geom.MinorRadius
                    radius = major

                else:
                    # print 'circle'
                    radius = geom.Radius

                # print 'radius ', radius

                angle = abs(angle) % 360
                # print 'angle ', angle

                if angle == 0:
                    # print 'B11'

                    slopedPlanes = _Py.slopedPlanes
                    faceMaker = slopedPlanes.FaceMaker

                    if pyWire.numWire == 0:
                        plane = Part.makeFace(geom.toShape(),
                                              faceMaker)
                    else:
                        rr = radius + length
                        circle = Part.makeCircle(rr)
                        circle.translate(point)
                        plane = Part.makeFace([extendShape,
                                               circle],
                                              faceMaker)

                elif angle == 90:
                    # print 'B12'

                    plane = Part.makeCylinder(radius, length, point)

                elif angle == 180:
                    # print 'B13'

                    slopedPlanes = _Py.slopedPlanes
                    faceMaker = slopedPlanes.FaceMaker

                    if pyWire.numWire > 0:
                        # print 'B131'

                        plane = Part.makeFace(extendShape,
                                              faceMaker)
                        plane.translate(point)

                    else:
                        # print 'B132'

                        rr = radius + length
                        circle = Part.makeCircle(rr)
                        circle.translate(point)
                        plane = Part.makeFace([extendShape,
                                               circle],
                                              faceMaker)

                elif angle > 90:
                    # print 'B14'

                    radiusBottom = radius
                    ang = angle - 90
                    # print 'ang ', ang

                    if pyWire.numWire == 0:
                        # print 'B141'
                        radiusTop = radiusBottom + length * sin(radians(ang))

                    else:
                        # print 'B142'
                        ll = radius / cos(radians(ang))
                        # print 'll ', ll
                        if ll <= length:
                            radiusTop = 0
                        else:
                            radiusTop = radiusBottom - length * sin(radians(ang))

                    height = length * cos(radians(ang))

                    # print 'radiusBottom ', radiusBottom
                    # print 'radiusTop ', radiusTop
                    # print 'height ', height

                    plane = Part.makeCone(radiusBottom, radiusTop, height,
                                          point)
                    # print plane.Placement

                else:
                    # print 'B15'

                    radiusBottom = radius
                    ll = radius / cos(radians(angle))
                    # print 'll ', ll

                    if ll <= length:
                        # print 'B151'
                        if pyWire.numWire == 0:
                            # print 'B1511'
                            height = radius * tan(radians(angle))
                            radiusTop = 0
                        else:
                            # print 'B1512'
                            height = length * sin(radians(angle))
                            radiusTop = radiusBottom + length * cos(radians(angle))

                    else:
                        # print 'B152'
                        if pyWire.numWire == 0:
                            # print 'B1521'
                            height = length * sin(radians(angle))
                            radiusTop = radiusBottom - length * cos(radians(angle))
                        else:
                            # print 'B1522'
                            height = radius * tan(radians(angle))
                            radiusTop = radiusBottom + length * cos(radians(angle))

                    # print 'radiusBottom ', radiusBottom
                    # print 'radiusTop ', radiusTop
                    # print 'height ', height

                    plane = Part.makeCone(radiusBottom, radiusTop, height,
                                          point)
                    # print plane.Placement

                if isinstance(geom, Part.ArcOfEllipse):
                    # print 'ellipse'

                    matrix = FreeCAD.Matrix()
                    coef = minor / major
                    matrix.scale(FreeCAD.Vector(1, coef, 1))
                    plane.translate(-1 * point)
                    plane = plane.transformGeometry(matrix)
                    plane.translate(point)

                if self.angle < 0 and _Py.reverse:
                    pass

                elif self.angle < 0 or _Py.reverse:
                    # print 'negative'
                    plane = plane.mirror(FreeCAD.Vector(0, 0, 0),
                                         FreeCAD.Vector(0, 0, -1))

                plane = plane.Faces[0]
                # print plane.Placement
                angleXU = geom.AngleXU
                # print 'angleXU ', angleXU
                plane.rotate(point, FreeCAD.Vector(0, 0, 1), degrees(angleXU))
                # print plane.Placement

            else:
                # print 'B2'

                plane = extendShape.extrude(direction * upScale)

        return plane
Example #26
0
def setup(doc=None, solvertype="ccxtools"):
    """ Nonlinear material example, plate with hole.

    https://forum.freecadweb.org/viewtopic.php?f=24&t=31997&start=30
    https://forum.freecadweb.org/viewtopic.php?t=33974&start=90
    https://forum.freecadweb.org/viewtopic.php?t=35893

    plate: 400x200x10 mm
    hole: diameter 100 mm (half cross section)
    load: 130 MPa tension
    linear material: Steel, E = 210000 MPa, my = 0.3
    nonlinear material: '240.0, 0.0' to '270.0, 0.025'
    TODO nonlinear material: give more information, use values from harry
    TODO compare results with example from HarryvL

    """

    if doc is None:
        doc = init_doc()

    # part
    import Part
    from FreeCAD import Vector as vec
    from Part import makeLine as ln
    from Part import makeCircle as ci

    v1 = vec(-200, -100, 0)
    v2 = vec(200, -100, 0)
    v3 = vec(200, 100, 0)
    v4 = vec(-200, 100, 0)
    l1 = ln(v1, v2)
    l2 = ln(v2, v3)
    l3 = ln(v3, v4)
    l4 = ln(v4, v1)
    v5 = vec(0, 0, 0)
    c1 = ci(50, v5)
    face = Part.makeFace([Part.Wire([l1, l2, l3, l4]), c1],
                         "Part::FaceMakerBullseye")
    partfem = doc.addObject("Part::Feature", "Hole_Plate")
    partfem.Shape = face.extrude(vec(0, 0, 10))
    doc.recompute()

    if FreeCAD.GuiUp:
        import FreeCADGui
        FreeCADGui.ActiveDocument.activeView().viewAxonometric()
        FreeCADGui.SendMsgToActiveView("ViewFit")

    # analysis
    analysis = ObjectsFem.makeAnalysis(doc, "Analysis")

    # solver
    if solvertype == "calculix":
        solver = analysis.addObject(
            ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0]
    elif solvertype == "ccxtools":
        solver = analysis.addObject(
            ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0]
        solver.WorkingDir = u""
    if solvertype == "calculix" or solvertype == "ccxtools":
        solver.SplitInputWriter = False
        solver.AnalysisType = "static"
        solver.GeometricalNonlinearity = "linear"
        solver.ThermoMechSteadyState = False
        solver.MatrixSolverType = "default"
        solver.IterationsControlParameterTimeUse = False
        solver.GeometricalNonlinearity = 'nonlinear'
        solver.MaterialNonlinearity = 'nonlinear'

    # linear material
    matprop = {}
    matprop["Name"] = "CalculiX-Steel"
    matprop["YoungsModulus"] = "210000 MPa"
    matprop["PoissonRatio"] = "0.30"
    matprop["Density"] = "7900 kg/m^3"
    material = analysis.addObject(
        ObjectsFem.makeMaterialSolid(doc, "Material_lin"))[0]
    material.Material = matprop

    # nonlinear material
    nonlinear_material = analysis.addObject(
        ObjectsFem.makeMaterialMechanicalNonlinear(doc, material,
                                                   "Material_nonlin"))[0]
    nonlinear_material.YieldPoint1 = '240.0, 0.0'
    nonlinear_material.YieldPoint2 = '270.0, 0.025'
    # check solver attributes, Nonlinearity needs to be set to nonlinear

    # fixed_constraint
    fixed_constraint = analysis.addObject(
        ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed"))[0]
    fixed_constraint.References = [(partfem, "Face4")]

    # force constraint
    pressure_constraint = doc.Analysis.addObject(
        ObjectsFem.makeConstraintPressure(doc, "ConstraintPressure"))[0]
    pressure_constraint.References = [(partfem, "Face2")]
    pressure_constraint.Pressure = 130.0
    pressure_constraint.Reversed = True

    # mesh
    from .meshes.mesh_platewithhole_tetra10 import create_nodes, create_elements
    fem_mesh = Fem.FemMesh()
    control = create_nodes(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating nodes.\n")
    control = create_elements(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating elements.\n")
    femmesh_obj = analysis.addObject(
        doc.addObject("Fem::FemMeshObject", mesh_name))[0]
    femmesh_obj.FemMesh = fem_mesh

    doc.recompute()
    return doc
Example #27
0
    def execute(self, obj):
        "creates the panel shape"

        if self.clone(obj):
            return

        import Part, DraftGeomUtils

        # base tests
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if not obj.Base.Mesh.isSolid():
                    return
        else:
            if obj.Length.Value:
                length = obj.Length.Value
            else:
                return
            if obj.Width.Value:
                width = obj.Width.Value
            else:
                return
        if obj.Thickness.Value:
            thickness = obj.Thickness.Value
        else:
            if not obj.Base:
                return
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if not obj.Base.Shape.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if hasattr(obj, "Normal"):
            if obj.Normal.Length > 0:
                normal = Vector(obj.Normal)
                normal.normalize()
                normal.multiply(thickness)
        baseprofile = None
        if obj.Base:
            base = obj.Base.Shape.copy()
            if not base.Solids:
                p = FreeCAD.Placement(obj.Base.Placement)
                if base.Faces:
                    baseprofile = base
                    if not normal:
                        normal = baseprofile.Faces[0].normalAt(
                            0, 0).multiply(thickness)
                    base = base.extrude(normal)
                elif base.Wires:
                    fm = False
                    if hasattr(obj, "FaceMaker"):
                        if obj.FaceMaker != "None":
                            try:
                                base = Part.makeFace(
                                    base.Wires,
                                    "Part::FaceMaker" + str(obj.FaceMaker))
                                fm = True
                            except:
                                FreeCAD.Console.PrintError(
                                    translate("Arch",
                                              "Facemaker returned an error") +
                                    "\n")
                                return
                    if not fm:
                        closed = True
                        for w in base.Wires:
                            if not w.isClosed():
                                closed = False
                        if closed:
                            baseprofile = ArchCommands.makeFace(base.Wires)
                            if not normal:
                                normal = baseprofile.normalAt(
                                    0, 0).multiply(thickness)
                            base = baseprofile.extrude(normal)
                elif obj.Base.isDerivedFrom("Mesh::Feature"):
                    if obj.Base.Mesh.isSolid():
                        if obj.Base.Mesh.countComponents() == 1:
                            sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                            if sh.isClosed() and sh.isValid() and sh.Solids:
                                base = sh
        else:
            if not normal:
                normal = Vector(0, 0, 1).multiply(thickness)
            l2 = length / 2 or 0.5
            w2 = width / 2 or 0.5
            v1 = Vector(-l2, -w2, 0)
            v2 = Vector(l2, -w2, 0)
            v3 = Vector(l2, w2, 0)
            v4 = Vector(-l2, w2, 0)
            base = Part.makePolygon([v1, v2, v3, v4, v1])
            baseprofile = Part.Face(base)
            base = baseprofile.extrude(normal)

        if hasattr(obj, "Area"):
            if baseprofile:
                obj.Area = baseprofile.Area

        if hasattr(obj, "WaveLength"):
            if baseprofile and obj.WaveLength.Value and obj.WaveHeight.Value:
                # corrugated element
                bb = baseprofile.BoundBox
                bb.enlarge(bb.DiagonalLength)
                p1 = Vector(bb.getPoint(0).x, bb.getPoint(0).y, bb.Center.z)
                if obj.WaveType == "Curved":
                    p2 = p1.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               obj.WaveHeight.Value))
                    p3 = p2.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               -obj.WaveHeight.Value))
                    e1 = Part.Arc(p1, p2, p3).toShape()
                    p4 = p3.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               -obj.WaveHeight.Value))
                    p5 = p4.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               obj.WaveHeight.Value))
                    e2 = Part.Arc(p3, p4, p5).toShape()
                else:
                    if obj.WaveHeight.Value < obj.WaveLength.Value:
                        p2 = p1.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   obj.WaveHeight.Value))
                        p3 = p2.add(
                            Vector(
                                obj.WaveLength.Value -
                                2 * obj.WaveHeight.Value, 0, 0))
                        p4 = p3.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   -obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1, p2, p3, p4])
                        p5 = p4.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   -obj.WaveHeight.Value))
                        p6 = p5.add(
                            Vector(
                                obj.WaveLength.Value -
                                2 * obj.WaveHeight.Value, 0, 0))
                        p7 = p6.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p4, p5, p6, p7])
                    else:
                        p2 = p1.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   obj.WaveHeight.Value))
                        p3 = p2.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   -obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1, p2, p3])
                        p4 = p3.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   -obj.WaveHeight.Value))
                        p5 = p4.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p3, p4, p5])
                edges = [e1, e2]
                for i in range(int(bb.XLength / (obj.WaveLength.Value * 2))):
                    e1 = e1.copy()
                    e1.translate(Vector(obj.WaveLength.Value * 2, 0, 0))
                    e2 = e2.copy()
                    e2.translate(Vector(obj.WaveLength.Value * 2, 0, 0))
                    edges.extend([e1, e2])
                basewire = Part.Wire(edges)
                baseface = basewire.extrude(Vector(0, bb.YLength, 0))
                base = baseface.extrude(Vector(0, 0, thickness))
                rot = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), normal)
                base.rotate(bb.Center, rot.Axis, math.degrees(rot.Angle))
                if obj.WaveDirection.Value:
                    base.rotate(bb.Center, normal, obj.WaveDirection.Value)
                n1 = normal.negative().normalize().multiply(
                    obj.WaveHeight.Value * 2)
                self.vol = baseprofile.copy()
                self.vol.translate(n1)
                self.vol = self.vol.extrude(n1.negative().multiply(2))
                base = self.vol.common(base)
                base = base.removeSplitter()
                if not base:
                    FreeCAD.Console.PrintError(
                        transpate("Arch", "Error computing shape of ") +
                        obj.Label + "\n")
                    return False

        if base and (obj.Sheets > 1) and normal and thickness:
            bases = [base]
            for i in range(1, obj.Sheets):
                n = FreeCAD.Vector(normal).normalize().multiply(i * thickness)
                b = base.copy()
                b.translate(n)
                bases.append(b)
            base = Part.makeCompound(bases)

        if base and normal and hasattr(obj, "Offset"):
            if obj.Offset.Value:
                v = DraftVecUtils.scaleTo(normal, obj.Offset.Value)
                base.translate(v)

        # process subshapes
        base = self.processSubShapes(obj, base, pl)

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(
                            translate("Arch", "Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Example #28
0
    def areaOpShapes(self, obj):
        '''areaOpShapes(obj) ... return shapes representing the solids to be removed.'''
        PathLog.track()

        subObjTups = []
        removalshapes = []

        if obj.Base:
            PathLog.debug("base items exist.  Processing... ")
            for base in obj.Base:
                PathLog.debug("obj.Base item: {}".format(base))

                # Check if all subs are faces
                allSubsFaceType = True
                Faces = []
                for sub in base[1]:
                    if "Face" in sub:
                        face = getattr(base[0].Shape, sub)
                        Faces.append(face)
                        subObjTups.append((sub, face))
                    else:
                        allSubsFaceType = False
                        break

                if len(Faces) == 0:
                    allSubsFaceType = False

                if allSubsFaceType is True and obj.HandleMultipleFeatures == 'Collectively':
                    if obj.OpFinalDepth == obj.FinalDepth:
                        (fzmin, fzmax) = self.getMinMaxOfFaces(Faces)
                        obj.FinalDepth.Value = fzmin
                        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=obj.StartDepth.Value,
                            step_down=obj.StepDown.Value,
                            z_finish_step=finish_step,
                            final_depth=fzmin,
                            user_depths=None)
                        PathLog.info(
                            "Updated obj.FinalDepth.Value and self.depthparams to zmin: {}"
                            .format(fzmin))

                    if obj.AdaptivePocketStart is True or obj.AdaptivePocketFinish is True:
                        pocketTup = self.calculateAdaptivePocket(
                            obj, base, subObjTups)
                        if pocketTup is not False:
                            removalshapes.append(
                                pocketTup
                            )  # (shape, isHole, sub, angle, axis, strDep, finDep)
                    else:
                        strDep = obj.StartDepth.Value
                        finDep = obj.FinalDepth.Value

                        shape = Part.makeCompound(Faces)
                        env = PathUtils.getEnvelope(
                            base[0].Shape,
                            subshape=shape,
                            depthparams=self.depthparams)
                        obj.removalshape = env.cut(base[0].Shape)
                        obj.removalshape.tessellate(0.1)
                        # (shape, isHole, sub, angle, axis, strDep, finDep)
                        removalshapes.append(
                            (obj.removalshape, False, '3DPocket', 0.0, 'X',
                             strDep, finDep))
                else:
                    for sub in base[1]:
                        if "Face" in sub:
                            shape = Part.makeCompound(
                                [getattr(base[0].Shape, sub)])
                        else:
                            edges = [
                                getattr(base[0].Shape, sub) for sub in base[1]
                            ]
                            shape = Part.makeFace(edges,
                                                  'Part::FaceMakerSimple')

                        env = PathUtils.getEnvelope(
                            base[0].Shape,
                            subshape=shape,
                            depthparams=self.depthparams)
                        obj.removalshape = env.cut(base[0].Shape)
                        obj.removalshape.tessellate(0.1)

                        removalshapes.append((obj.removalshape, False))

        else:  # process the job base object as a whole
            PathLog.debug("processing the whole job base object")
            strDep = obj.StartDepth.Value
            finDep = obj.FinalDepth.Value
            recomputeDepthparams = False
            for base in self.model:
                if obj.OpFinalDepth == obj.FinalDepth:
                    if base.Shape.BoundBox.ZMin < obj.FinalDepth.Value:
                        obj.FinalDepth.Value = base.Shape.BoundBox.ZMin
                        finDep = base.Shape.BoundBox.ZMin
                        recomputeDepthparams = True
                        PathLog.info(
                            "Updated obj.FinalDepth.Value to {}".format(
                                finDep))
                if obj.OpStartDepth == obj.StartDepth:
                    if base.Shape.BoundBox.ZMax > obj.StartDepth.Value:
                        obj.StartDepth.Value = base.Shape.BoundBox.ZMax
                        finDep = base.Shape.BoundBox.ZMax
                        recomputeDepthparams = True
                        PathLog.info(
                            "Updated obj.StartDepth.Value to {}".format(
                                strDep))
                if recomputeDepthparams is True:
                    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=obj.StartDepth.Value,
                        step_down=obj.StepDown.Value,
                        z_finish_step=finish_step,
                        final_depth=obj.FinalDepth.Value,
                        user_depths=None)
                    recomputeDepthparams = False

                if obj.ProcessStockArea is True:
                    job = PathUtils.findParentJob(obj)
                    finish_step = obj.FinishDepth.Value if hasattr(
                        obj, "FinishDepth") else 0.0

                    depthparams = PathUtils.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=finish_step,
                        final_depth=base.Shape.BoundBox.ZMin,
                        user_depths=None)
                    stockEnvShape = PathUtils.getEnvelope(
                        job.Stock.Shape,
                        subshape=None,
                        depthparams=depthparams)

                    obj.removalshape = stockEnvShape.cut(base.Shape)
                    obj.removalshape.tessellate(0.1)
                else:
                    env = PathUtils.getEnvelope(base.Shape,
                                                subshape=None,
                                                depthparams=self.depthparams)
                    obj.removalshape = env.cut(base.Shape)
                    obj.removalshape.tessellate(0.1)

                removalshapes.append((obj.removalshape, False, '3DPocket', 0.0,
                                      'X', strDep, finDep))

        return removalshapes
Example #29
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
def smSketchOnSheetMetal(kfactor = 0.5, sketch = '', flipped = False, selFaceNames = '', MainObject = None):
  resultSolid = MainObject.Shape.copy()
  selElement = resultSolid.getElement(selFaceNames[0])
  LargeFace = smFace(selElement, resultSolid)
  sketch_face = Part.makeFace(sketch.Shape.Wires,"Part::FaceMakerBullseye")

  #To get thk of sheet, top face normal
  thk = smthk(resultSolid, LargeFace)
  #print(thk)

  #To get top face normal, flatsolid
  solidlist = []
  normal = LargeFace.normalAt(0,0)
  #To check face direction
  coeff = normal.dot(sketch_face.Faces[0].normalAt(0,0))
  if coeff < 0 :
    sketch_face.reverse()
  Flatface = sketch_face.common(LargeFace)
  BalanceFaces = sketch_face.cut(Flatface)
  #Part.show(BalanceFace,"BalanceFace")
  Flatsolid = Flatface.extrude(normal * -thk)
  #Part.show(Flatsolid,"Flatsolid")
  solidlist.append(Flatsolid)

  if BalanceFaces.Faces :
    for BalanceFace in BalanceFaces.Faces :
      #Part.show(BalanceFace,"BalanceFace")
      TopFace = LargeFace
      #Part.show(TopFace,"TopFace")
      #flipped = False
      while BalanceFace.Faces :
        BendEdge = smGetEdge(BalanceFace, TopFace)
        #Part.show(BendEdge,"BendEdge")
        facelist = resultSolid.ancestorsOfType(BendEdge, Part.Face)

        #To get bend radius, bend angle
        for cylface in facelist :
          if issubclass(type(cylface.Surface),Part.Cylinder) :
            break
        if not(issubclass(type(cylface.Surface),Part.Cylinder)) :
          break
        #Part.show(cylface,"cylface")
        for planeface in facelist :
          if issubclass(type(planeface.Surface),Part.Plane) :
            break
        #Part.show(planeface,"planeface")
        normal = planeface.normalAt(0,0)
        revAxisV = cylface.Surface.Axis
        revAxisP = cylface.Surface.Center
        bendA = bendAngle(cylface, revAxisP)
        #print([bendA, revAxisV, revAxisP, cylface.Orientation])

        #To check bend direction
        offsetface = cylface.makeOffsetShape(-thk, 0.0, fill = False)
        #Part.show(offsetface,"offsetface")
        if offsetface.Area < cylface.Area :
          bendR = cylface.Surface.Radius - thk
          flipped = True
        else :
          bendR = cylface.Surface.Radius
          flipped = False

        #To arrive unfold Length, neturalRadius
        unfoldLength = ( bendR + kfactor * thk ) * abs(bendA) * math.pi / 180.0
        neturalRadius =  ( bendR + kfactor * thk )
        #print([unfoldLength,neturalRadius])

        #To get faceNormal, bend face
        faceNormal = normal.cross(revAxisV).normalize()
        #print(faceNormal)
        if bendR < cylface.Surface.Radius :
          offsetSolid = cylface.makeOffsetShape(bendR/2.0, 0.0, fill = True)
        else:
          offsetSolid = cylface.makeOffsetShape(-bendR/2.0, 0.0, fill = True)
        #Part.show(offsetSolid,"offsetSolid")
        tool = BendEdge.copy()
        FaceArea = tool.extrude(faceNormal * -unfoldLength )
        #Part.show(FaceArea,"FaceArea")
        #Part.show(BalanceFace,"BalanceFace")
        SolidFace = offsetSolid.common(FaceArea)
        #Part.show(BendSolidFace,"BendSolidFace")
        if not(SolidFace.Faces):
          faceNormal = faceNormal * -1
          FaceArea = tool.extrude(faceNormal * -unfoldLength )
        BendSolidFace = BalanceFace.common(FaceArea)
        #Part.show(FaceArea,"FaceArea")
        #Part.show(BendSolidFace,"BendSolidFace")
        #print([bendR, bendA, revAxisV, revAxisP, normal, flipped, BendSolidFace.Faces[0].normalAt(0,0)])
    
        bendsolid = SheetMetalBendSolid.BendSolid(BendSolidFace.Faces[0], BendEdge, bendR, thk, neturalRadius, revAxisV, flipped)
        #Part.show(bendsolid,"bendsolid")
        solidlist.append(bendsolid)

        if flipped == True:
          bendA = -bendA
        if not(SolidFace.Faces):
          revAxisV = revAxisV * -1
        sketch_face = BalanceFace.cut(BendSolidFace)
        sketch_face.translate(faceNormal * unfoldLength)
        #Part.show(sketch_face,"sketch_face")
        sketch_face.rotate(revAxisP, -revAxisV, bendA)
        #Part.show(sketch_face,"Rsketch_face")
        TopFace = smCutFace(sketch_face, resultSolid)
        #Part.show(TopFace,"TopFace") 

        #To get top face normal, flatsolid
        normal = TopFace.normalAt(0,0)
        Flatface = sketch_face.common(TopFace)
        BalanceFace = sketch_face.cut(Flatface)
        #Part.show(BalanceFace,"BalanceFace")
        Flatsolid = Flatface.extrude(normal * -thk)
        #Part.show(Flatsolid,"Flatsolid")
        solidlist.append(Flatsolid)

  #To get relief Solid fused
  if len(solidlist) > 1 :
    SMSolid = solidlist[0].multiFuse(solidlist[1:])
    #Part.show(SMSolid,"SMSolid") 
    SMSolid = SMSolid.removeSplitter()
  else :
   SMSolid = solidlist[0]
  #Part.show(SMSolid,"SMSolid")
  resultSolid = resultSolid.cut(SMSolid)

  Gui.ActiveDocument.getObject(MainObject.Name).Visibility = False
  Gui.ActiveDocument.getObject(sketch.Name).Visibility = False
  return resultSolid
Example #31
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     normal = None
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     base = None
     placement = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                         normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                 elif obj.Base.Shape.Wires:
                     baseface = None
                     if hasattr(obj,"FaceMaker"):
                         if obj.FaceMaker != "None":
                             try:
                                 baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                             except:
                                 FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                 return None
                             if len(baseface.Faces) > 1:
                                 baseface = baseface.Faces[0]
                             normal = baseface.normalAt(0,0)
                     if not baseface:
                         for w in obj.Base.Shape.Wires:
                             w.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(w)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                                 normal = f.normalAt(0,0)
                     base,placement = self.rebase(baseface)
                 elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                     # closed edge
                     w = Part.Wire(obj.Base.Shape.Edges[0])
                     baseface = Part.Face(w)
                     base,placement = self.rebase(baseface)
     elif length and width and height:
         if (length > height) and (obj.Role != "Slab"):
             h2 = height/2 or 0.5
             w2 = width/2 or 0.5
             v1 = Vector(0,-w2,-h2)
             v2 = Vector(0,-w2,h2)
             v3 = Vector(0,w2,h2)
             v4 = Vector(0,w2,-h2)
         else:
             l2 = length/2 or 0.5
             w2 = width/2 or 0.5
             v1 = Vector(-l2,-w2,0)
             v2 = Vector(l2,-w2,0)
             v3 = Vector(l2,w2,0)
             v4 = Vector(-l2,w2,0)
         import Part
         baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         base,placement = self.rebase(baseface)
     if base and placement:
         if obj.Normal == Vector(0,0,0):
             if not normal:
                 normal = Vector(0,0,1)
         else:
             normal = Vector(obj.Normal)
         if (length > height) and (obj.Role != "Slab"):
             extrusion = normal.multiply(length)
         else:
             extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
Example #32
0
def setup(doc=None, solvertype="ccxtools"):
    # setup model

    if doc is None:
        doc = init_doc()

    # geometry objects
    v1 = vec(-200, -100, 0)
    v2 = vec(200, -100, 0)
    v3 = vec(200, 100, 0)
    v4 = vec(-200, 100, 0)
    l1 = ln(v1, v2)
    l2 = ln(v2, v3)
    l3 = ln(v3, v4)
    l4 = ln(v4, v1)
    v5 = vec(0, 0, 0)
    c1 = ci(50, v5)
    face = Part.makeFace([Part.Wire([l1, l2, l3, l4]), c1],
                         "Part::FaceMakerBullseye")
    geom_obj = doc.addObject("Part::Feature", "Hole_Plate")
    geom_obj.Shape = face.extrude(vec(0, 0, 10))
    doc.recompute()

    if FreeCAD.GuiUp:
        geom_obj.ViewObject.Document.activeView().viewAxonometric()
        geom_obj.ViewObject.Document.activeView().fitAll()

    # analysis
    analysis = ObjectsFem.makeAnalysis(doc, "Analysis")

    # solver
    if solvertype == "calculix":
        solver = analysis.addObject(
            ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX"))[0]
    elif solvertype == "ccxtools":
        solver = analysis.addObject(
            ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools"))[0]
        solver.WorkingDir = u""
    if solvertype == "calculix" or solvertype == "ccxtools":
        solver.SplitInputWriter = False
        solver.AnalysisType = "static"
        solver.GeometricalNonlinearity = "linear"
        solver.ThermoMechSteadyState = False
        solver.MatrixSolverType = "default"
        solver.IterationsControlParameterTimeUse = False
        solver.GeometricalNonlinearity = 'nonlinear'
        solver.MaterialNonlinearity = 'nonlinear'

    # linear material
    matprop = {}
    matprop["Name"] = "CalculiX-Steel"
    matprop["YoungsModulus"] = "210000 MPa"
    matprop["PoissonRatio"] = "0.30"
    matprop["Density"] = "7900 kg/m^3"
    material = analysis.addObject(
        ObjectsFem.makeMaterialSolid(doc, "Material_lin"))[0]
    material.Material = matprop

    # nonlinear material
    nonlinear_material = analysis.addObject(
        ObjectsFem.makeMaterialMechanicalNonlinear(doc, material,
                                                   "Material_nonlin"))[0]
    nonlinear_material.YieldPoint1 = '240.0, 0.0'
    nonlinear_material.YieldPoint2 = '270.0, 0.025'
    # check solver attributes, Nonlinearity needs to be set to nonlinear

    # fixed_constraint
    fixed_constraint = analysis.addObject(
        ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed"))[0]
    fixed_constraint.References = [(geom_obj, "Face4")]

    # force constraint
    pressure_constraint = doc.Analysis.addObject(
        ObjectsFem.makeConstraintPressure(doc, "ConstraintPressure"))[0]
    pressure_constraint.References = [(geom_obj, "Face2")]
    pressure_constraint.Pressure = 130.0
    pressure_constraint.Reversed = True

    # mesh
    from .meshes.mesh_platewithhole_tetra10 import create_nodes, create_elements
    fem_mesh = Fem.FemMesh()
    control = create_nodes(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating nodes.\n")
    control = create_elements(fem_mesh)
    if not control:
        FreeCAD.Console.PrintError("Error on creating elements.\n")
    femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc,
                                                             mesh_name))[0]
    femmesh_obj.FemMesh = fem_mesh
    femmesh_obj.Part = geom_obj
    femmesh_obj.SecondOrderLinear = False

    doc.recompute()
    return doc
 def makeFace(self, fp):
     if fp.Face and len(fp.Shape.Wires) > 0:
         face = Part.makeFace(fp.Shape.Wires, "Part::FaceMakerSimple")
         fp.Shape = face
def smBend(bendR = 1.0, bendA = 90.0, miterA1 = 0.0,miterA2 = 0.0, BendType = "Material Outside", flipped = False, unfold = False, 
            offset = 0.0, extLen = 10.0, gap1 = 0.0, gap2 = 0.0,  reliefType = "Rectangle", reliefW = 0.8, reliefD = 1.0, extend1 = 0.0, 
            extend2 = 0.0, kfactor = 0.45, ReliefFactor = 0.7, UseReliefFactor = False, selFaceNames = '', MainObject = None, 
            automiter = True, sketch = None ):

  # if sketch is as wall 
  sketches = False
  if sketch :
    if sketch.Shape.Wires[0].isClosed() :
      sketches = True
    else :
      pass

  if not(sketches) :
    miterA1List1, miterA2List1, gap1List1, gap2List1, reliefDList1, wallsolid_common_list1 = smMiter(bendR = bendR, bendA = bendA, miterA1 = miterA1, miterA2 = miterA2, flipped = flipped, extLen = extLen, gap1 = gap1, 
                                      sign = 1.0, offset = offset, gap2 = gap2, reliefD = reliefD, selFaceNames = selFaceNames, automiter = automiter, MainObject = MainObject)
    bendAflip = (bendA - 180)
    miterA1List2, miterA2List2, gap1List2, gap2List2, reliefDList2, wallsolid_common_list2 = smMiter(bendR = bendR, bendA = bendAflip, miterA1 = miterA1, miterA2 = miterA2, flipped = flipped, extLen = extLen, gap1 = gap1, 
                                      sign = -1.0, offset = offset, gap2 = gap2, reliefD = reliefD, selFaceNames = selFaceNames, automiter = automiter, MainObject = MainObject)

    miterA1List = [x if a > b else y for x, y, a, b in zip(miterA1List1, miterA1List2, wallsolid_common_list1, wallsolid_common_list2)]
    miterA2List = [x if a > b else y for x, y, a, b in zip(miterA2List1, miterA2List2, wallsolid_common_list1, wallsolid_common_list2)]
    gap1List = [x + y for x, y in zip(gap1List1, gap1List2)]
    gap2List = [x + y for x, y in zip(gap2List1, gap2List2)]
    reliefDList = [min(x , y) for x, y in zip(reliefDList1, reliefDList2)]

  else :
    miterA1List, miterA2List, gap1List, gap2List, reliefDList = ( [0.0],[0.0],[gap1],[gap2],[reliefD])

  thk_faceList = []
  resultSolid = MainObject
  for i, selFaceName in enumerate(selFaceNames):
    selItem = MainObject.getElement(selFaceName)
    selFace = smFace(selItem, MainObject)
    selFace = smModifiedFace(selFace, resultSolid)
    gap1, gap2 = (gap1List[i], gap2List[i])
    reliefD = reliefDList[i]

    # find the narrow edge
    thk = 999999.0
    for edge in selFace.Edges:
      if abs( edge.Length ) < thk:
        thk = abs( edge.Length )
        thkEdge = edge

    # Add as offset to  set any distance
    if UseReliefFactor :
      reliefW = thk * ReliefFactor
      reliefD = thk * ReliefFactor

    # Add Relief factor
    if BendType == "Material Outside" :
      offset = 0.0
      inside = False
    elif BendType == "Material Inside" :
      offset = -(thk + bendR)
      inside = True
    elif BendType == "Thickness Outside" :
      offset = -bendR
      inside = True
    elif BendType == "Offset" :
      if offset < 0.0 :
        inside = True
      else :
        inside = False

    # find a length edge  =  revolve axis direction
    p0 = thkEdge.valueAt(thkEdge.FirstParameter)
    for lenEdge in selFace.Edges:
      p1 = lenEdge.valueAt(lenEdge.FirstParameter)
      p2 = lenEdge.valueAt(lenEdge.LastParameter)
      if lenEdge.isSame(thkEdge):
        continue
      if (p1 - p0).Length < smEpsilon:
        revAxisV = p2 - p1
        break
      if (p2 - p0).Length < smEpsilon:
        revAxisV = p1 - p2
        break

    # find the large face connected with selected face
    list2 = resultSolid.ancestorsOfType(lenEdge, Part.Face)
    for Cface in list2 :
      if not(Cface.isSame(selFace)) :
        break

    # Produce Offset Edge
    if offset > 0.0 :
      lenEdge.translate(selFace.normalAt(0,0) * offset)

    # main Length Edge
    MlenEdge = lenEdge
    leng = MlenEdge.Length
    revAxisV.normalize()
    thkDir = Cface.normalAt(0,0) * -1
    FaceDir = selFace.normalAt(0,0)

    # Get correct size inside face
    if inside :
      e1 = MlenEdge.copy()
      e1.translate(FaceDir * offset)
      EdgeShape = e1.common(Cface)
      lenEdge = EdgeShape.Edges[0]
      Noffset1 = abs((MlenEdge.valueAt(MlenEdge.FirstParameter)-lenEdge.valueAt(lenEdge.FirstParameter)).Length)
      Noffset2 = abs((MlenEdge.valueAt(MlenEdge.LastParameter)-lenEdge.valueAt(lenEdge.LastParameter)).Length)

    # if sketch is as wall 
    sketches = False
    if sketch :
      if sketch.Shape.Wires[0].isClosed() :
        sketches = True
      else :
        pass

    if sketches :
      sketch_face = Part.makeFace(sketch.Shape.Wires, "Part::FaceMakerBullseye")
      sketch_face.translate(thkDir * -thk )
      if inside :
        sketch_face.translate(FaceDir * offset )
      sketch_Shape = lenEdge.common(sketch_face)
      sketch_Edge = sketch_Shape.Edges[0]
      gap1 = (lenEdge.valueAt(lenEdge.FirstParameter) - sketch_Edge.valueAt(sketch_Edge.FirstParameter)).Length
      gap2 = (lenEdge.valueAt(lenEdge.LastParameter) - sketch_Edge.valueAt(sketch_Edge.LastParameter)).Length

    # Get angles of adjcent face
    Agap1 = 0.0
    Agap2 = 0.0
    if inside :
      AngleList =[]
      if MlenEdge.Vertexes[0].Orientation == "Reversed" :
        vertex1 = MlenEdge.Vertexes[0]
        vertex0 = MlenEdge.Vertexes[1]
      else : 
        vertex0 = MlenEdge.Vertexes[0]
        vertex1 = MlenEdge.Vertexes[1]
      Edgelist = Cface.ancestorsOfType(vertex0, Part.Edge)
      for ed in Edgelist :
        if not(MlenEdge.isSame(ed)):
          #Part.show(ed)
          if abs((MlenEdge.valueAt(MlenEdge.FirstParameter)- ed.valueAt(ed.LastParameter)).Length)  < smEpsilon:
            lineDir = ed.valueAt(ed.LastParameter)- ed.valueAt(ed.FirstParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.FirstParameter) - MlenEdge.valueAt(MlenEdge.LastParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("1",angle)
            AngleList.append(angle)
          elif abs((MlenEdge.valueAt(MlenEdge.FirstParameter) - ed.valueAt(ed.FirstParameter)).Length) < smEpsilon:
            lineDir = ed.valueAt(ed.FirstParameter)- ed.valueAt(ed.LastParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.FirstParameter) - MlenEdge.valueAt(MlenEdge.LastParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("2",angle)
            AngleList.append(angle)

      Edgelist = Cface.ancestorsOfType(vertex1, Part.Edge)
      for ed in Edgelist :
        if not(MlenEdge.isSame(ed)):
          if abs((MlenEdge.valueAt(MlenEdge.LastParameter)- ed.valueAt(ed.FirstParameter)).Length)  < smEpsilon:
            lineDir = ed.valueAt(ed.FirstParameter)- ed.valueAt(ed.LastParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.LastParameter) - MlenEdge.valueAt(MlenEdge.FirstParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("1",angle)
            AngleList.append(angle)
          elif abs((MlenEdge.valueAt(MlenEdge.LastParameter) - ed.valueAt(ed.LastParameter)).Length) < smEpsilon:
            lineDir = ed.valueAt(ed.LastParameter)- ed.valueAt(ed.FirstParameter)
            edgeDir = MlenEdge.valueAt(MlenEdge.LastParameter) - MlenEdge.valueAt(MlenEdge.FirstParameter)
            angle1 = edgeDir.getAngle(lineDir)
            angle = math.degrees(angle1)
            #print("2",angle)
            AngleList.append(angle)
      if AngleList : 
        if AngleList[0] > 90.01 and gap1 == 0.0 :
          Agap1 = reliefW
        if AngleList[1] > 90.01 and gap2 == 0.0 :
          Agap2 = reliefW
    
    #make sure the direction verctor is correct in respect to the normal
    if (thkDir.cross(revAxisV).normalize() - FaceDir).Length < smEpsilon:
     revAxisV = revAxisV * -1

    reliefDn = reliefD
    if inside :
      reliefDn = reliefD + abs(offset)

    # CutSolids list for collecting Solids
    CutSolids = []

    # remove relief if needed
    if reliefD > 0.0 :
      if reliefW > 0.0 and ( gap1 > 0.0 or Agap1 > 0.0 ):
        reliefFace1 = smMakeReliefFace(MlenEdge, FaceDir* -1, gap1-reliefW, reliefW, reliefDn, reliefType)
        reliefSolid1 = reliefFace1.extrude(thkDir * thk)
        #Part.show(reliefSolid1)
        CutSolids.append(reliefSolid1)
      if reliefW > 0.0 and ( gap2 > 0.0 or Agap2 > 0.0 ):
        reliefFace2 = smMakeReliefFace(MlenEdge, FaceDir* -1, leng-gap2, reliefW, reliefDn, reliefType)
        reliefSolid2 = reliefFace2.extrude(thkDir * thk)
        #Part.show(reliefSolid2)
        CutSolids.append(reliefSolid2)

    # restrict angle
    if (bendA < 0):
        bendA = -bendA
        flipped = not flipped

    if not(flipped):
      revAxisP = lenEdge.valueAt(lenEdge.FirstParameter) + thkDir * (bendR + thk)
      revAxisV = revAxisV * -1
    else:
      revAxisP = lenEdge.valueAt(lenEdge.FirstParameter) + thkDir * -bendR

    # remove bend face if present
    if inside :
      if gap1 == 0.0 or (reliefD == 0.0 and  gap1 == 0.1) :
        Edgelist = selFace.ancestorsOfType(vertex0, Part.Edge)
        for ed in Edgelist :
          if not(MlenEdge.isSame(ed)):
            list1 = resultSolid.ancestorsOfType(ed, Part.Face)
            for Rface in list1 :
              if Rface.Area != selFace.Area and issubclass(type(Rface.Surface),Part.Plane) :
                for edge in Rface.Edges:
                  if issubclass(type(edge.Curve),Part.Circle):
                    RfaceE = Rface.extrude(Rface.normalAt(0,0) * -Noffset1 )
                    CutSolids.append(RfaceE)
                    break

      if gap2 == 0.0 or (reliefD == 0.0 and  gap2 == 0.1) :
        Edgelist = selFace.ancestorsOfType(vertex1, Part.Edge)
        for ed in Edgelist :
          if not(MlenEdge.isSame(ed)):
            list1 = resultSolid.ancestorsOfType(ed, Part.Face)
            for Rface in list1 :
              if Rface.Area != selFace.Area and issubclass(type(Rface.Surface),Part.Plane) :
                for edge in Rface.Edges:
                  if issubclass(type(edge.Curve),Part.Circle):
                    RfaceE = Rface.extrude(Rface.normalAt(0,0) * -Noffset2 )
                    CutSolids.append(RfaceE)
                    break

      if reliefD == 0.0 and ( gap1 == 0.1 or gap2 == 0.1 ) :
        CutFace = smMakeFace(MlenEdge, thkDir, thk, 0, 0)
      else :
        CutFace = smMakeFace(MlenEdge, thkDir, thk, gap1, gap2)
      CutSolid = CutFace.extrude(FaceDir * offset )
      CfaceSolid = Cface.extrude(thkDir * thk)
      CutSolid = CutSolid.common(CfaceSolid)
      CutSolids.append(CutSolid)

    # Produce Main Solid for Inside Bends
    if CutSolids :
      if len(CutSolids) == 1 :
        resultSolid = resultSolid.cut(CutSolids[0])
      else :
        Solid = CutSolids[0].multiFuse(CutSolids[1:])
        Solid.removeSplitter()
        #Part.show(Solid)
        resultSolid = resultSolid.cut(Solid)

    # Produce Offset Solid
    if offset > 0.0 :
      # create wall
      offset_face = smMakeFace(lenEdge, FaceDir, -offset)
      OffsetSolid = offset_face.extrude(thkDir * thk)
      resultSolid = resultSolid.fuse(OffsetSolid)

    #wallSolid = None
    if sketches :
      Wall_face = Part.makeFace(sketch.Shape.Wires, "Part::FaceMakerBullseye")
      if inside :
        Wall_face.translate(FaceDir * offset )
      FaceAxisP = sketch_Edge.valueAt(sketch_Edge.FirstParameter) + thkDir * thk
      FaceAxisV = sketch_Edge.valueAt(sketch_Edge.FirstParameter) - sketch_Edge.valueAt(sketch_Edge.LastParameter)
      Wall_face.rotate(FaceAxisP, FaceAxisV, -90.0)
      wallSolid = Wall_face.extrude(thkDir * -thk)
      #Part.show(wallSolid)
      wallSolid.rotate(revAxisP, revAxisV, bendA)

    elif extLen > 0.0 :
      # create wall
      Wall_face = smMakeFace(lenEdge, FaceDir, extLen, gap1-extend1, gap2-extend2, miterA1List[i], miterA2List[i])
      wallSolid = Wall_face.extrude(thkDir * thk)
      #Part.show(wallSolid)
      wallSolid.rotate(revAxisP, revAxisV, bendA)
      #Part.show(wallSolid.Faces[2])
      thk_faceList.append(wallSolid.Faces[2])

    # Produce bend Solid
    if not(unfold) :
      if bendA > 0.0 :
        # create bend
        # narrow the wall if we have gaps
        revFace = smMakeFace(lenEdge, thkDir, thk, gap1, gap2)
        if revFace.normalAt(0,0) != FaceDir :
          revFace.reverse()
        bendSolid = revFace.revolve(revAxisP, revAxisV, bendA)
        #Part.show(bendSolid)
        resultSolid = resultSolid.fuse(bendSolid)
      if wallSolid :
        resultSolid = resultSolid.fuse(wallSolid)

    # Produce unfold Solid
    else :
      if bendA > 0.0 :
        # create bend
        unfoldLength = ( bendR + kfactor * thk ) * bendA * math.pi / 180.0
        # narrow the wall if we have gaps
        unfoldFace = smMakeFace(lenEdge, thkDir, thk, gap1, gap2)
        if unfoldFace.normalAt(0,0) != FaceDir :
          unfoldFace.reverse()
        unfoldSolid = unfoldFace.extrude(FaceDir * unfoldLength)
        #Part.show(unfoldSolid)
        resultSolid = resultSolid.fuse(unfoldSolid)

      if extLen > 0.0 :
        wallSolid.rotate(revAxisP, revAxisV, -bendA)
        #Part.show(wallSolid)
        wallSolid.translate(FaceDir * unfoldLength)
        resultSolid = resultSolid.fuse(wallSolid)

  #Gui.ActiveDocument.getObject(MainObject.Name).Visibility = False
  #if sketch :
    #Gui.ActiveDocument.getObject(sketch.Name).Visibility = False
  return resultSolid, thk_faceList
Example #35
0
    def execute(self, obj, getsim=False):
        PathLog.track()
        self.endVector = None

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

        commandlist = []
        toolLoad = obj.ToolController

        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)

        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

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

        isPanel = False
        if hasattr(baseobject, "Proxy"):
            if isinstance(baseobject.Proxy,
                          ArchPanel.PanelSheet):  # process the sheet
                isPanel = True
                baseobject.Proxy.execute(baseobject)
                shapes = baseobject.Proxy.getOutlines(baseobject,
                                                      transform=True)
                for shape in shapes:
                    f = Part.makeFace([shape], 'Part::FaceMakerSimple')
                    thickness = baseobject.Group[0].Source.Thickness
                    contourshape = f.extrude(FreeCAD.Vector(0, 0, thickness))
                    try:
                        (pp, sim) = self._buildPathArea(obj,
                                                        contourshape,
                                                        start=obj.StartPoint,
                                                        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 hasattr(baseobject, "Shape") and not isPanel:
            #bb = baseobject.Shape.BoundBox
            env = PathUtils.getEnvelope(partshape=baseobject.Shape,
                                        subshape=None,
                                        depthparams=self.depthparams)
            try:
                (pp, sim) = self._buildPathArea(obj,
                                                env,
                                                start=obj.StartPoint,
                                                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
        #obj.ViewObject.Visibility = True
        return sim
Example #36
0
def makeFaceDXF():
    global copper_diffuse, silks_diffuse
    global use_LinkGroups, use_AppPart

    doc = FreeCAD.ActiveDocument
    if doc is None:
        FreeCAD.newDocument()
        doc = FreeCAD.ActiveDocument
    docG = FreeCADGui.ActiveDocument
    Filter = ""
    last_pcb_path = ""
    pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/kicadStepUp")
    last_pcb_path = pg.GetString("last_pcb_path")
    fn, Filter = PySide.QtGui.QFileDialog.getOpenFileNames(
        None, "Open File...", make_unicode(last_pcb_path), "*.dxf")
    for fname in fn:
        path, name = os.path.split(fname)
        filename = os.path.splitext(name)[0]
        #importDXF.open(os.path.join(dirname,filename))
        if len(fname) > 0:
            #importDXF.open(fname)
            last_pcb_path = os.path.dirname(fname)
            pg = FreeCAD.ParamGet(
                "User parameter:BaseApp/Preferences/Mod/kicadStepUp")
            pg.SetString("last_pcb_path",
                         make_string(last_pcb_path))  # py3 .decode("utf-8")
            pg = FreeCAD.ParamGet(
                "User parameter:BaseApp/Preferences/Mod/kicadStepUpGui")
            pcb_color_pos = pg.GetInt('pcb_color')
            #print(pcb_color_pos)
            if pcb_color_pos == 9:
                silks_diffuse = (0.18, 0.18, 0.18)  #slick black
            else:
                silks_diffuse = (
                    0.98, 0.92, 0.84
                )  # #antique white  # white (0.906,0.906,0.910)
            doc = FreeCAD.ActiveDocument
            objects = []
            say("loading... ")
            t = time.time()
            if doc is not None:
                for o in doc.Objects:
                    objects.append(o.Name)
                importDXF.insert(fname, doc.Name)
            else:
                importDXF.open(fname)
            FreeCADGui.SendMsgToActiveView("ViewFit")
            timeP = time.time() - t
            say("loading time = " + str(timeP) + "s")

            edges = []
            sorted_edges = []
            w = []

            for o in doc.Objects:
                if o.Name not in str(objects):
                    if hasattr(o, 'Shape'):
                        w1 = Part.Wire(Part.__sortEdges__(o.Shape.Edges))
                        w.append(w1)
            #print (w)
            f = Part.makeFace(w, 'Part::FaceMakerBullseye')
            for o in doc.Objects:
                if o.Name not in str(objects):
                    doc.removeObject(o.Name)
            if 'Silk' in filename:
                layerName = 'Silks'
            else:
                layerName = 'Tracks'
            if 'F.' in filename or 'F_' in filename:
                layerName = 'top' + layerName
            if 'B.' in filename or 'B_' in filename:
                layerName = 'bot' + layerName

            doc.addObject('Part::Feature', layerName).Shape = f
            newShape = doc.ActiveObject
            botOffset = 1.6
            if 'Silk' in layerName:
                docG.getObject(newShape.Name).ShapeColor = silks_diffuse
            else:
                docG.getObject(
                    newShape.Name
                ).ShapeColor = brass_diffuse  #copper_diffuse  #(0.78,0.56,0.11)
            if len(doc.getObjectsByLabel('Pcb')) > 0:
                newShape.Placement = doc.getObjectsByLabel('Pcb')[0].Placement
                #botTracks.Placement = doc.Pcb.Placement
                if len(doc.getObjectsByLabel('Board_Geoms')) > 0:
                    if use_AppPart and not use_LinkGroups:
                        doc.getObject('Board_Geoms').addObject(newShape)
                    elif use_LinkGroups:
                        doc.getObject('Board_Geoms').ViewObject.dropObject(
                            newShape, None, '', [])
                if hasattr(doc.getObjectsByLabel('Pcb')[0], 'Shape'):
                    botOffset = doc.getObjectsByLabel(
                        'Pcb')[0].Shape.BoundBox.ZLength
                else:
                    botOffset = doc.getObjectsByLabel(
                        'Pcb')[0].OutList[1].Shape.BoundBox.ZLength
            #elif 'bot' in layerName:
            #    newShape.Placement.Base.z-=1.6
            if 'top' in layerName:
                newShape.Placement.Base.z += 0.07
            if 'bot' in layerName:
                newShape.Placement.Base.z -= botOffset + 0.07
            timeD = time.time() - t - timeP
            say("displaying time = " + str(timeD) + "s")
    FreeCADGui.SendMsgToActiveView("ViewFit")
    docG.activeView().viewAxonometric()
Example #37
0
def smExtrude(extLength=10.0,
              gap1=0.0,
              gap2=0.0,
              substraction=False,
              offset=0.02,
              refine=True,
              sketch='',
              selFaceNames='',
              selObject=''):

    finalShape = selObject
    for selFaceName in selFaceNames:
        selItem = selObject.getElement(selFaceName)
        selFace = smFace(selItem, selObject)

        # find the narrow edge
        thk = 999999.0
        for edge in selFace.Edges:
            if abs(edge.Length) < thk:
                thk = abs(edge.Length)
                thkEdge = edge

        # find a length edge  =  revolve axis direction
        p0 = thkEdge.valueAt(thkEdge.FirstParameter)
        for lenEdge in selFace.Edges:
            p1 = lenEdge.valueAt(lenEdge.FirstParameter)
            p2 = lenEdge.valueAt(lenEdge.LastParameter)
            if lenEdge.isSame(thkEdge):
                continue
            if (p1 - p0).Length < smEpsilon:
                revAxisV = p2 - p1
                break
            if (p2 - p0).Length < smEpsilon:
                revAxisV = p1 - p2
                break

        # find the large face connected with selected face
        list2 = selObject.ancestorsOfType(lenEdge, Part.Face)
        for Cface in list2:
            if not (Cface.isSame(selFace)):
                break
        #Part.show(Cface, "Cface")

        # Main Length Edge, Extrusion direction
        MlenEdge = lenEdge
        #    leng = MlenEdge.Length
        revAxisV.normalize()
        thkDir = Cface.normalAt(0, 0) * -1
        FaceDir = selFace.normalAt(0, 0)

        # if sketch is as wall
        sketches = False
        if sketch:
            if sketch.Shape.Wires[0].isClosed():
                sketches = True
            else:
                pass

        # Split solid Based on Top Face into two solid
        Topface_Solid = Cface.Wires[0].extrude(Cface.normalAt(0, 0) * -thk)
        #Part.show(Topface_Solid,"Topface_Solid")
        SplitSolids = BOPTools.SplitAPI.slice(finalShape, Topface_Solid.Faces,
                                              "Standard", 0.0)
        #Part.show(SplitSolids,"SplitSolids")
        for SplitSolid in SplitSolids.Solids:
            check_face = SplitSolid.common(Cface)
            if check_face.Faces:
                SplitSolid1 = SplitSolid
                break
        #Part.show(SplitSolid1,"SplitSolid1")
        for SplitSolid in SplitSolids.Solids:
            if not (SplitSolid.isSame(SplitSolid1)):
                SplitSolid2 = SplitSolid
                break
        #Part.show(SplitSolid2, "SplitSolid2")

        # Make solid from sketch, if sketch is present
        solidlist = []
        if sketches:
            Wall_face = Part.makeFace(sketch.Shape.Wires,
                                      "Part::FaceMakerBullseye")
            check_face = Wall_face.common(Cface)
            if not (check_face.Faces):
                thkDir = thkDir * -1
            wallSolid = Wall_face.extrude(thkDir * thk)
            #Part.show(wallSolid, "wallSolid")
            solidlist.append(wallSolid)

            # To find Overlapping Solid, non thickness side Face that touch Overlapping Solid
            overlap_solid = wallSolid.common(SplitSolid2)
            #Part.show(overlap_solid, "overlap_solid")
            substract_face = smTouchFace(wallSolid, SplitSolid2, thk)
            #Part.show(substract_face, "substract_face")

            # To get solids that aligned/normal to touching face
            overlap_solidlist = smgetSubface(substract_face, overlap_solid,
                                             lenEdge, thk)

            # Substract solid from Initial Solid
            if substraction:
                for solid in overlap_solidlist:
                    CutSolid = solid.makeOffsetShape(offset,
                                                     0.0,
                                                     fill=False,
                                                     join=2)
                    #Part.show(CutSolid, "CutSolid")
                    finalShape = finalShape.cut(CutSolid)
                    #Part.show(finalShape,"finalShape")

        elif extLength > 0.0:
            # create wall, if edge or face selected
            Wall_face = smMakeFace(lenEdge,
                                   FaceDir,
                                   extLength,
                                   gap1,
                                   gap2,
                                   op='SMW')
            wallSolid = Wall_face.extrude(thkDir * thk)
            #Part.show(wallSolid,"wallSolid")
            solidlist.append(wallSolid)

        # Fuse All solid created to Split solid
        if len(solidlist) > 0:
            resultSolid = SplitSolid1.fuse(solidlist[0])
            if refine:
                resultSolid = resultSolid.removeSplitter()
            #Part.show(resultSolid,"resultSolid")

            # Merge final list
            finalShape = finalShape.cut(resultSolid)
            #Part.show(finalShape,"finalShape")
            finalShape = finalShape.fuse(resultSolid)

    #Part.show(finalShape,"finalShape")
    return finalShape
Example #38
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
Example #39
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
    def execute(self,obj):
        "creates the panel shape"
        
        if self.clone(obj):
            return

        import Part, DraftGeomUtils

        # base tests
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if not obj.Base.Mesh.isSolid():
                    return
        else:
            if obj.Length.Value:
                length = obj.Length.Value
            else:
                return
            if obj.Width.Value:
                width = obj.Width.Value
            else:
                return
        if obj.Thickness.Value:
            thickness = obj.Thickness.Value
        else:
            if not obj.Base:
                return
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if not obj.Base.Shape.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if hasattr(obj,"Normal"):
            if obj.Normal.Length > 0:
                normal = Vector(obj.Normal)
                normal.normalize()
                normal.multiply(thickness)
        baseprofile = None
        if obj.Base:
            base = obj.Base.Shape.copy()
            if not base.Solids:
                p = FreeCAD.Placement(obj.Base.Placement)
                if base.Faces:
                    baseprofile = base
                    if not normal:
                        normal = baseprofile.Faces[0].normalAt(0,0).multiply(thickness)
                    base = base.extrude(normal)
                elif base.Wires:
                    fm = False
                    if hasattr(obj,"FaceMaker"):
                        if obj.FaceMaker != "None":
                            try:
                                base = Part.makeFace(base.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                                fm = True
                            except:
                                FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                return
                    if not fm:
                        closed = True
                        for w in base.Wires:
                            if not w.isClosed():
                                closed = False
                        if closed:
                            baseprofile = ArchCommands.makeFace(base.Wires)
                            if not normal:
                                normal = baseprofile.normalAt(0,0).multiply(thickness)
                            base = baseprofile.extrude(normal)
                elif obj.Base.isDerivedFrom("Mesh::Feature"):
                    if obj.Base.Mesh.isSolid():
                        if obj.Base.Mesh.countComponents() == 1:
                            sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                            if sh.isClosed() and sh.isValid() and sh.Solids:
                                base = sh
        else:
            if not normal:
                normal = Vector(0,0,1).multiply(thickness)
            l2 = length/2 or 0.5
            w2 = width/2 or 0.5
            v1 = Vector(-l2,-w2,0)
            v2 = Vector(l2,-w2,0)
            v3 = Vector(l2,w2,0)
            v4 = Vector(-l2,w2,0)
            base = Part.makePolygon([v1,v2,v3,v4,v1])
            baseprofile = Part.Face(base)
            base = baseprofile.extrude(normal)
            
        if hasattr(obj,"Area"):
            if baseprofile:
                obj.Area = baseprofile.Area
            
        if hasattr(obj,"WaveLength"):
            if baseprofile and obj.WaveLength.Value and obj.WaveHeight.Value:
                # corrugated element
                bb = baseprofile.BoundBox
                bb.enlarge(bb.DiagonalLength)
                p1 = Vector(bb.getPoint(0).x,bb.getPoint(0).y,bb.Center.z)
                if obj.WaveType == "Curved":
                    p2 = p1.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                    p3 = p2.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                    e1 = Part.Arc(p1,p2,p3).toShape()
                    p4 = p3.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                    p5 = p4.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                    e2 = Part.Arc(p3,p4,p5).toShape()
                else:
                    if obj.WaveHeight.Value < obj.WaveLength.Value:
                        p2 = p1.add(Vector(obj.WaveHeight.Value,0,obj.WaveHeight.Value))
                        p3 = p2.add(Vector(obj.WaveLength.Value-2*obj.WaveHeight.Value,0,0))
                        p4 = p3.add(Vector(obj.WaveHeight.Value,0,-obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1,p2,p3,p4])
                        p5 = p4.add(Vector(obj.WaveHeight.Value,0,-obj.WaveHeight.Value))
                        p6 = p5.add(Vector(obj.WaveLength.Value-2*obj.WaveHeight.Value,0,0))
                        p7 = p6.add(Vector(obj.WaveHeight.Value,0,obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p4,p5,p6,p7])
                    else:
                        p2 = p1.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                        p3 = p2.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1,p2,p3])
                        p4 = p3.add(Vector(obj.WaveLength.Value/2,0,-obj.WaveHeight.Value))
                        p5 = p4.add(Vector(obj.WaveLength.Value/2,0,obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p3,p4,p5])
                edges = [e1,e2]
                for i in range(int(bb.XLength/(obj.WaveLength.Value*2))):
                    e1 = e1.copy()
                    e1.translate(Vector(obj.WaveLength.Value*2,0,0))
                    e2 = e2.copy()
                    e2.translate(Vector(obj.WaveLength.Value*2,0,0))
                    edges.extend([e1,e2])
                basewire = Part.Wire(edges)
                baseface = basewire.extrude(Vector(0,bb.YLength,0))
                base = baseface.extrude(Vector(0,0,thickness))
                rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),normal)
                base.rotate(bb.Center,rot.Axis,math.degrees(rot.Angle))
                if obj.WaveDirection.Value:
                    base.rotate(bb.Center,normal,obj.WaveDirection.Value)
                n1 = normal.negative().normalize().multiply(obj.WaveHeight.Value*2)
                self.vol = baseprofile.copy()
                self.vol.translate(n1)
                self.vol = self.vol.extrude(n1.negative().multiply(2))
                base = self.vol.common(base)
                base = base.removeSplitter()
                if not base:
                    FreeCAD.Console.PrintError(transpate("Arch","Error computing shape of ")+obj.Label+"\n")
                    return False

        if base and (obj.Sheets > 1) and normal and thickness:
            bases = [base]
            for i in range(1,obj.Sheets):
                n = FreeCAD.Vector(normal).normalize().multiply(i*thickness)
                b = base.copy()
                b.translate(n)
                bases.append(b)
            base = Part.makeCompound(bases)

        if base and normal and hasattr(obj,"Offset"):
            if obj.Offset.Value:
                v = DraftVecUtils.scaleTo(normal,obj.Offset.Value)
                base.translate(v)

        # process subshapes
        base = self.processSubShapes(obj,base,pl)

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(translate("Arch","Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl