示例#1
0
 def rebase(self,shape):
     import DraftGeomUtils,math
     if not isinstance(shape,list):
         shape = [shape]
     if hasattr(shape[0],"CenterOfMass"):
         v = shape[0].CenterOfMass
     else:
         v = shape[0].BoundBox.Center
     n = DraftGeomUtils.getNormal(shape[0])
     r = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),n)
     if round(r.Angle,8) == round(math.pi,8):
         r = FreeCAD.Rotation()
     shapes = []
     for s in shape:
         s = s.copy()
         s.translate(v.negative())
         s.rotate(FreeCAD.Vector(0,0,0),r.inverted().Axis,math.degrees(r.inverted().Angle))
         shapes.append(s)
     p = FreeCAD.Placement()
     p.Base = v
     p.Rotation = r
     if len(shapes) == 1:
         return (shapes[0],p)
     else:
         return(shapes,p)
示例#2
0
 def rebase(self, shape):
     import DraftGeomUtils, math
     if not isinstance(shape, list):
         shape = [shape]
     if hasattr(shape[0], "CenterOfMass"):
         v = shape[0].CenterOfMass
     else:
         v = shape[0].BoundBox.Center
     n = DraftGeomUtils.getNormal(shape[0])
     r = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), n)
     if round(r.Angle, 8) == round(math.pi, 8):
         r = FreeCAD.Rotation()
     shapes = []
     for s in shape:
         s = s.copy()
         s.translate(v.negative())
         s.rotate(FreeCAD.Vector(0, 0, 0),
                  r.inverted().Axis, math.degrees(r.inverted().Angle))
         shapes.append(s)
     p = FreeCAD.Placement()
     p.Base = v
     p.Rotation = r
     if len(shapes) == 1:
         return (shapes[0], p)
     else:
         return (shapes, p)
示例#3
0
    def rebase(self,shape):

        """returns a shape that is a copy of the original shape
        but centered on the (0,0) origin, and a placement that is needed to
        reposition that shape to its original location/orientation"""
        import DraftGeomUtils,math
        if not isinstance(shape,list):
            shape = [shape]
        if hasattr(shape[0],"CenterOfMass"):
            v = shape[0].CenterOfMass
        else:
            v = shape[0].BoundBox.Center
        n = DraftGeomUtils.getNormal(shape[0])
        r = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),n)
        if round(abs(r.Angle),8) == round(math.pi,8):
            r = FreeCAD.Rotation()
        shapes = []
        for s in shape:
            s = s.copy()
            s.translate(v.negative())
            s.rotate(FreeCAD.Vector(0,0,0),r.Axis,math.degrees(-r.Angle))
            shapes.append(s)
        p = FreeCAD.Placement()
        p.Base = v
        p.Rotation = r
        if len(shapes) == 1:
            return (shapes[0],p)
        else:
            return(shapes,p)
示例#4
0
 def updateWire(self,v):
     pts = self.obj.Points
     editPnt = v#self.invpl.multVec(v)
     # DNC: allows to close the curve by placing ends close to each other
     tol = 0.001
     if ( ( self.editing == 0 ) and ( (editPnt - pts[-1]).Length < tol) ) or ( self.editing == len(pts) - 1 ) and ( (editPnt - pts[0]).Length < tol):
         self.obj.Closed = True
     # DNC: fix error message if edited point coincides with one of the existing points
     if ( editPnt in pts ) == True: # checks if point enter is equal to other, this could cause a OCC problem
         FreeCAD.Console.PrintMessage(translate("draft", "Is not possible to have two coincident points in this object, please try again.")+"\n")
         if Draft.getType(self.obj) in ["BezCurve"]: self.resetTrackers()
         else: self.trackers[self.editing].set(self.pl.multVec(self.obj.Points[self.editing]))
         return
     if Draft.getType(self.obj) in ["BezCurve"]:
         pts = self.recomputePointsBezier(pts,self.editing,v,self.obj.Degree,moveTrackers=False)
     # check that the new point lies on the plane of the wire
     import DraftGeomUtils, DraftVecUtils
     if self.obj.Closed:
         n = DraftGeomUtils.getNormal(self.obj.Shape)
         dv = editPnt.sub(pts[self.editing])
         rn = DraftVecUtils.project(dv,n)
         if dv.Length:
             editPnt = editPnt.add(rn.negative())
     pts[self.editing] = editPnt
     self.obj.Points = pts
     self.trackers[self.editing].set(self.pl.multVec(v))
示例#5
0
 def rebase(self,shape):
     """returns a shape that is a copy of the original shape
     but centered on the (0,0) origin, and a placement that is needed to
     reposition that shape to its original location/orientation"""
     import DraftGeomUtils,math
     if not isinstance(shape,list):
         shape = [shape]
     if hasattr(shape[0],"CenterOfMass"):
         v = shape[0].CenterOfMass
     else:
         v = shape[0].BoundBox.Center
     n = DraftGeomUtils.getNormal(shape[0])
     r = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),n)
     if round(abs(r.Angle),8) == round(math.pi,8):
         r = FreeCAD.Rotation()
     shapes = []
     for s in shape:
         s = s.copy()
         s.translate(v.negative())
         s.rotate(FreeCAD.Vector(0,0,0),r.Axis,math.degrees(-r.Angle))
         shapes.append(s)
     p = FreeCAD.Placement()
     p.Base = v
     p.Rotation = r
     if len(shapes) == 1:
         return (shapes[0],p)
     else:
         return(shapes,p)
示例#6
0
    def Activated(self):
        doc = FreeCAD.ActiveDocument
        pg = FreeCAD.ParamGet("User parameter:Plugins/MeshRemodel")
        line_width = pg.GetFloat("LineWidth", 5.0)
        point_size = pg.GetFloat("PointSize", 4.0)
        #QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        #add_varargs_method("makeCircle",&Module::makeCircle,
        #    "makeCircle(radius,[pnt,dir,angle1,angle2]) -- Make a circle with a given radius\n"
        #    "By default pnt=Vector(0,0,0), dir=Vector(0,0,1), angle1=0 and angle2=360"
        #);

        modifiers = QtGui.QApplication.keyboardModifiers()
        poly = Part.makePolygon(self.pts)
        #Part.show(poly)
        normal = DraftGeomUtils.getNormal(poly)

        A = self.pts[0]
        B = self.pts[1]
        C = self.pts[2]

        if gu.isColinear(A, B, C):
            FreeCAD.Console.PrintError(
                "MeshRemodel Error: Cannot make arc/circle from 3 colinear points\n"
            )
            return

        center = gu.circumcenter(A, B, C)
        radius = gu.circumradius(A, B, C)

        doc.openTransaction("Create circle")
        circle = Part.makeCircle(radius, center, normal)
        circName = "MR_Ref"
        if not modifiers == QtCore.Qt.ShiftModifier.__or__(
                QtCore.Qt.ControlModifier):
            Part.show(circle, "MR_Circle")
            circName = doc.ActiveObject.Name
            doc.ActiveObject.ViewObject.LineWidth = line_width
            FreeCAD.Console.PrintMessage(circName + ": radius = " +
                                         str(radius) + "\n  center at " +
                                         str(center) + "\n")
            Gui.Selection.clearSelection()
            Gui.Selection.addSelection(doc.getObject(circName))
        if modifiers == QtCore.Qt.ControlModifier or modifiers == QtCore.Qt.ControlModifier.__or__(
                QtCore.Qt.ShiftModifier):
            Part.show(
                Part.Point(center).toShape(), circName + "_Ctr"
            )  #show the center point on ctrl click or shift+ctrl click
            doc.ActiveObject.ViewObject.PointSize = point_size

        doc.recompute()
        doc.commitTransaction()
        #QtGui.QApplication.restoreOverrideCursor()
        return
示例#7
0
 def rebase(self,shape):
     import DraftGeomUtils,math
     if hasattr(shape,"CenterOfMass"):
         v = shape.CenterOfMass
     else:
         v = shape.BoundBox.Center
     n = DraftGeomUtils.getNormal(shape)
     r = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),n)
     if round(r.Angle,8) == round(math.pi,8):
         r = FreeCAD.Rotation()
     shape = shape.copy()
     shape.translate(v.negative())
     shape.rotate(FreeCAD.Vector(0,0,0),r.inverted().Axis,math.degrees(r.inverted().Angle))
     p = FreeCAD.Placement()
     p.Base = v
     p.Rotation = r
     return (shape,p)
示例#8
0
    def execute(self, obj):

        import Part, DraftGeomUtils, math
        pl = obj.Placement
        w = self.getWire(obj)
        if not w:
            FreeCAD.Console.PrintError(
                translate("Arch", "Unable to build the base path") + "\n")
            return
        if obj.OffsetStart.Value:
            e = w.Edges[0]
            v = e.Vertexes[-1].Point.sub(e.Vertexes[0].Point).normalize()
            v.multiply(obj.OffsetStart.Value)
            e = Part.LineSegment(e.Vertexes[0].Point.add(v),
                                 e.Vertexes[-1].Point).toShape()
            w = Part.Wire([e] + w.Edges[1:])
        if obj.OffsetEnd.Value:
            e = w.Edges[-1]
            v = e.Vertexes[0].Point.sub(e.Vertexes[-1].Point).normalize()
            v.multiply(obj.OffsetEnd.Value)
            e = Part.LineSegment(e.Vertexes[-1].Point.add(v),
                                 e.Vertexes[0].Point).toShape()
            w = Part.Wire(w.Edges[:-1] + [e])
        p = self.getProfile(obj)
        if not p:
            FreeCAD.Console.PrintError(
                translate("Arch", "Unable to build the profile") + "\n")
            return
        # move and rotate the profile to the first point
        delta = w.Vertexes[0].Point - p.CenterOfMass
        p.translate(delta)
        v1 = w.Vertexes[1].Point - w.Vertexes[0].Point
        v2 = DraftGeomUtils.getNormal(p)
        rot = FreeCAD.Rotation(v2, v1)
        p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
        try:
            sh = w.makePipeShell([p], True, False, 2)
        except:
            FreeCAD.Console.PrintError(
                translate("Arch", "Unable to build the pipe") + "\n")
        else:
            obj.Shape = sh
            if obj.Base:
                obj.Length = w.Length
            else:
                obj.Placement = pl
示例#9
0
 def rebase(self,shape):
     import DraftGeomUtils,math
     if hasattr(shape,"CenterOfMass"):
         v = shape.CenterOfMass
     else:
         v = shape.BoundBox.Center
     n = DraftGeomUtils.getNormal(shape)
     r = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),n)
     if round(r.Angle,8) == round(math.pi,8):
         r = FreeCAD.Rotation()
     shape = shape.copy()
     shape.translate(v.negative())
     shape.rotate(FreeCAD.Vector(0,0,0),r.inverted().Axis,math.degrees(r.inverted().Angle))
     p = FreeCAD.Placement()
     p.Base = v
     p.Rotation = r
     return (shape,p)
示例#10
0
    def Activated(self):
        doc = FreeCAD.ActiveDocument
        pg = FreeCAD.ParamGet("User parameter:Plugins/MeshRemodel")
        line_width = pg.GetFloat("LineWidth", 5.0)
        point_size = pg.GetFloat("PointSize", 4.0)
        modifiers = QtGui.QApplication.keyboardModifiers()
        poly = Part.makePolygon(self.pts)
        #        Part.show(poly)
        normal = DraftGeomUtils.getNormal(poly)

        A = self.pts[0]
        B = self.pts[1]
        C = self.pts[2]

        if gu.isColinear(A, B, C):
            FreeCAD.Console.PrintError(
                "MeshRemodel Error: Cannot make arc/circle from 3 colinear points\n"
            )
            return
        center = gu.circumcenter(A, B, C)
        radius = gu.circumradius(A, B, C)

        doc.openTransaction("Create Arc")
        arc = Part.ArcOfCircle(A, B, C)
        #on ctrl+shift click we only show center
        arcName = "MR_Ref"
        if not modifiers == QtCore.Qt.ControlModifier.__or__(
                QtCore.Qt.ShiftModifier):
            Part.show(arc.toShape(), "MR_Arc")
            arcName = doc.ActiveObject.Name
            doc.ActiveObject.ViewObject.LineWidth = line_width
            FreeCAD.Console.PrintMessage(arcName + ": radius = " +
                                         str(radius) + "\n  center at " +
                                         str(center) + "\n")
            Gui.Selection.clearSelection()
            Gui.Selection.addSelection(doc.getObject(arcName))
        if modifiers == QtCore.Qt.ControlModifier or modifiers == QtCore.Qt.ControlModifier.__or__(
                QtCore.Qt.ShiftModifier):
            Part.show(Part.Point(center).toShape(),
                      arcName + "_Ctr")  #show the center point
            doc.ActiveObject.ViewObject.PointSize = point_size
        doc.recompute()
        doc.commitTransaction()
        #QtGui.QApplication.restoreOverrideCursor()
        return
示例#11
0
def getRebarsSpanAxis(rebar):
    """getRebarsSpanAxis(Rebar):
    Returns span axis of rebars.
    """
    if (Draft.getType(rebar.Base) == "Wire"
            or rebar.Base.Shape.ShapeType == "Wire") and len(
                rebar.Base.Shape.Wires[0].Edges
            ) != 1:  # Draft Wires can have "wrong" placement
        # This works fine instead for straight rebars i.e. for rebars having
        # base wire with only one edge
        axis = DraftGeomUtils.getNormal(rebar.Base.Shape)
    else:
        axis = rebar.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
    if hasattr(rebar, "Direction"):
        if not DraftVecUtils.isNull(rebar.Direction):
            axis = FreeCAD.Vector(rebar.Direction)
            axis.normalize()
    return axis
示例#12
0
 def orientWP(self):
     """Orient the working plane."""
     import DraftGeomUtils
     if hasattr(App, "DraftWorkingPlane"):
         if len(self.node) > 1 and self.obj:
             n = DraftGeomUtils.getNormal(self.obj.Shape)
             if not n:
                 n = App.DraftWorkingPlane.axis
             p = self.node[-1]
             v = self.node[-2].sub(self.node[-1])
             v = v.negative()
             if not self.oldWP:
                 self.oldWP = App.DraftWorkingPlane.getParameters()
             App.DraftWorkingPlane.alignToPointAndAxis(p, n, upvec=v)
             if hasattr(Gui, "Snapper"):
                 Gui.Snapper.setGrid()
                 Gui.Snapper.restack()
             if self.planetrack:
                 self.planetrack.set(self.node[-1])
示例#13
0
    def execute(self,obj):

        import Part,DraftGeomUtils,math
        pl = obj.Placement
        w = self.getWire(obj)
        if not w:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the base path")+"\n")
            return
        if obj.OffsetStart.Value:
            e = w.Edges[0]
            v = e.Vertexes[-1].Point.sub(e.Vertexes[0].Point).normalize()
            v.multiply(obj.OffsetStart.Value)
            e = Part.LineSegment(e.Vertexes[0].Point.add(v),e.Vertexes[-1].Point).toShape()
            w = Part.Wire([e]+w.Edges[1:])
        if obj.OffsetEnd.Value:
            e = w.Edges[-1]
            v = e.Vertexes[0].Point.sub(e.Vertexes[-1].Point).normalize()
            v.multiply(obj.OffsetEnd.Value)
            e = Part.LineSegment(e.Vertexes[-1].Point.add(v),e.Vertexes[0].Point).toShape()
            w = Part.Wire(w.Edges[:-1]+[e])
        p = self.getProfile(obj)
        if not p:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the profile")+"\n")
            return
        # move and rotate the profile to the first point
        delta = w.Vertexes[0].Point-p.CenterOfMass
        p.translate(delta)
        v1 = w.Vertexes[1].Point-w.Vertexes[0].Point
        v2 = DraftGeomUtils.getNormal(p)
        rot = FreeCAD.Rotation(v2,v1)
        p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
        try:
            sh = w.makePipeShell([p],True,False,2)
        except:
            FreeCAD.Console.PrintError(translate("Arch","Unable to build the pipe")+"\n")
        else:
            obj.Shape = sh
            if obj.Base:
                obj.Length = w.Length
            else:
                obj.Placement = pl
示例#14
0
    def execute(self,obj):
        
        tol = 1 # tolerance for alignment. This is only visual, we can keep it low...
        ptol = 0.001 # tolerance for coincident points

        import math,Part,DraftGeomUtils,ArchCommands
        if len(obj.Pipes) < 2:
            return
        if len(obj.Pipes) > 3:
            FreeCAD.Console.PrintWarning(translate("Arch","Only the 3 first wires will be connected")+"\n")
        if obj.Radius.Value == 0:
            return
        wires = []
        order = []
        for o in obj.Pipes:
            wires.append(o.Proxy.getWire(o))
        if wires[0].Vertexes[0].Point.sub(wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["start","start"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[0].Point.sub(wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["start","end"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[-1].Point.sub(wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["end","end"]
            point = wires[0].Vertexes[-1].Point
        elif wires[0].Vertexes[-1].Point.sub(wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["end","start"]
            point = wires[0].Vertexes[-1].Point
        else:
            FreeCAD.Console.PrintError(translate("Arch","Common vertex not found")+"\n")
            return
        if order[0] == "start":
            v1 = wires[0].Vertexes[1].Point.sub(wires[0].Vertexes[0].Point).normalize()
        else:
            v1 = wires[0].Vertexes[-2].Point.sub(wires[0].Vertexes[-1].Point).normalize()
        if order[1] == "start":
            v2 = wires[1].Vertexes[1].Point.sub(wires[1].Vertexes[0].Point).normalize()
        else:
            v2 = wires[1].Vertexes[-2].Point.sub(wires[1].Vertexes[-1].Point).normalize()
        p = obj.Pipes[0].Proxy.getProfile(obj.Pipes[0])
        p = Part.Face(p)
        if len(obj.Pipes) == 2:
            if obj.ConnectorType != "Corner":
                obj.ConnectorType = "Corner"
            if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]:
                FreeCAD.Console.PrintError(translate("Arch","Pipes are already aligned")+"\n")
                return
            normal = v2.cross(v1)
            offset = math.tan(math.pi/2-v1.getAngle(v2)/2)*obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            self.setOffset(obj.Pipes[0],order[0],offset)
            self.setOffset(obj.Pipes[1],order[1],offset)
            # find center
            perp = v1.cross(normal).normalize()
            perp.multiply(obj.Radius.Value)
            center = point.add(v1).add(perp)
            # move and rotate the profile to the first point
            delta = point.add(v1)-p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp,v1)
            p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
            sh = p.revolve(center,normal,math.degrees(math.pi-v1.getAngle(v2)))
            #sh = Part.makeCompound([sh]+[Part.Vertex(point),Part.Vertex(point.add(v1)),Part.Vertex(center),Part.Vertex(point.add(v2))])
        else:
            if obj.ConnectorType != "Tee":
                obj.ConnectorType = "Tee"
            if wires[2].Vertexes[0].Point == point:
                order.append("start")
            elif wires[0].Vertexes[-1].Point == point:
                order.append("end")
            else:
                FreeCAD.Console.PrintError(translate("Arch","Common vertex not found")+"\n")
            if order[2] == "start":
                v3 = wires[2].Vertexes[1].Point.sub(wires[2].Vertexes[0].Point).normalize()
            else:
                v3 = wires[2].Vertexes[-2].Point.sub(wires[2].Vertexes[-1].Point).normalize()
            if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]:
                pair = [v1,v2,v3]
            elif round(v1.getAngle(v3),tol) in [0,round(math.pi,tol)]:
                pair = [v1,v3,v2]
            elif round(v2.getAngle(v3),tol) in [0,round(math.pi,tol)]:
                pair = [v2,v3,v1]
            else:
                FreeCAD.Console.PrintError(translate("Arch","At least 2 pipes must aligned")+"\n")
                return
            offset = obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            v3.multiply(offset)
            self.setOffset(obj.Pipes[0],order[0],offset)
            self.setOffset(obj.Pipes[1],order[1],offset)
            self.setOffset(obj.Pipes[2],order[2],offset)
            normal = pair[0].cross(pair[2])
            # move and rotate the profile to the first point
            delta = point.add(pair[0])-p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp,pair[0])
            p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
            t1 = p.extrude(pair[1].multiply(2))
            # move and rotate the profile to the second point
            delta = point.add(pair[2])-p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp,pair[2])
            p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
            t2 = p.extrude(pair[2].negative().multiply(2))
            # create a cut plane
            cp = Part.makePolygon([point,point.add(pair[0]),point.add(normal),point])
            cp = Part.Face(cp)
            if cp.normalAt(0,0).getAngle(pair[2]) < math.pi/2:
                cp.reverse()
            cf, cv, invcv = ArchCommands.getCutVolume(cp,t2)
            t2 = t2.cut(cv)
            sh = t1.fuse(t2)
        obj.Shape = sh
示例#15
0
    def execute(self,obj):
        
        if self.clone(obj):
            return
        
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj,"ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            edges = obj.Base.Shape.Edges
            if hasattr(obj,"Edges"):
                if obj.Edges == "Vertical edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                elif obj.Edges == "Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                elif obj.Edges == "Top Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                    edges = sorted(edges,key=lambda x: x.CenterOfMass.z,reverse=True)
                    z = edges[0].CenterOfMass.z
                    edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001]
                elif obj.Edges == "Bottom Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                    edges = sorted(edges,key=lambda x: x.CenterOfMass.z)
                    z = edges[0].CenterOfMass.z
                    edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001]
            for e in edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.")+"\n")
                        basepoint = basepointliste[0]
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                if hasattr(obj,"Fuse"):
                    if obj.Fuse:
                        if len(shapes) > 1:
                            s = shapes[0].multiFuse(shapes[1:])
                            s = s.removeSplitter()
                            obj.Shape = s
                            obj.Placement = pl
                            return
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
示例#16
0
def make_sketch(objectslist,
                autoconstraints=False,
                addTo=None,
                delete=False,
                name="Sketch",
                radiusPrecision=-1):
    """makeSketch(objectslist,[autoconstraints],[addTo],[delete],[name],[radiusPrecision])

    Makes a Sketch objectslist with the given Draft objects.

    Parameters
    ----------
    objectlist: can be single or list of objects of Draft type objects,
        Part::Feature, Part.Shape, or mix of them.

    autoconstraints(False): if True, constraints will be automatically added to
        wire nodes, rectangles and circles.

    addTo(None) : if set to an existing sketch, geometry will be added to it
        instead of creating a new one.

    delete(False): if True, the original object will be deleted.
        If set to a string 'all' the object and all its linked object will be
        deleted

    name('Sketch'): the name for the new sketch object

    radiusPrecision(-1): If <0, disable radius constraint. If =0, add indiviaul
        radius constraint. If >0, the radius will be rounded according to this
        precision, and 'Equal' constraint will be added to curve with equal
        radius within precision.
    """

    if not App.ActiveDocument:
        App.Console.PrintError("No active document. Aborting\n")
        return

    import Part
    from Sketcher import Constraint
    import Sketcher

    StartPoint = 1
    EndPoint = 2
    MiddlePoint = 3
    deletable = None

    if not isinstance(objectslist, (list, tuple)):
        objectslist = [objectslist]
    for obj in objectslist:
        if isinstance(obj, Part.Shape):
            shape = obj
        elif not hasattr(obj, 'Shape'):
            App.Console.PrintError(translate("draft", "not shape found"))
            return None
        else:
            shape = obj.Shape
        if not DraftGeomUtils.isPlanar(shape):
            App.Console.PrintError(
                translate("draft", "All Shapes must be co-planar"))
            return None
    if addTo:
        nobj = addTo
    else:
        nobj = App.ActiveDocument.addObject("Sketcher::SketchObject", name)
        deletable = nobj
        if App.GuiUp:
            nobj.ViewObject.Autoconstraints = False

    # Collect constraints and add in one go to improve performance
    constraints = []
    radiuses = {}

    def addRadiusConstraint(edge):
        try:
            if radiusPrecision < 0:
                return
            if radiusPrecision == 0:
                constraints.append(
                    Constraint('Radius', nobj.GeometryCount - 1,
                               edge.Curve.Radius))
                return
            r = round(edge.Curve.Radius, radiusPrecision)
            constraints.append(
                Constraint('Equal', radiuses[r], nobj.GeometryCount - 1))
        except KeyError:
            radiuses[r] = nobj.GeometryCount - 1
            constraints.append(Constraint('Radius', nobj.GeometryCount - 1, r))
        except AttributeError:
            pass

    def convertBezier(edge):
        if DraftGeomUtils.geomType(edge) == "BezierCurve":
            return (edge.Curve.toBSpline(edge.FirstParameter,
                                         edge.LastParameter).toShape())
        else:
            return (edge)

    rotation = None
    for obj in objectslist:
        ok = False
        tp = utils.get_type(obj)
        if tp in ["Circle", "Ellipse"]:
            if obj.Shape.Edges:
                if rotation is None:
                    rotation = obj.Placement.Rotation
                edge = obj.Shape.Edges[0]
                if len(edge.Vertexes) == 1:
                    newEdge = DraftGeomUtils.orientEdge(edge)
                    nobj.addGeometry(newEdge)
                else:
                    # make new ArcOfCircle
                    circle = DraftGeomUtils.orientEdge(edge)
                    angle = edge.Placement.Rotation.Angle
                    axis = edge.Placement.Rotation.Axis
                    circle.Center = DraftVecUtils.rotate(
                        edge.Curve.Center, -angle, axis)
                    first = math.radians(obj.FirstAngle)
                    last = math.radians(obj.LastAngle)
                    arc = Part.ArcOfCircle(circle, first, last)
                    nobj.addGeometry(arc)
                addRadiusConstraint(edge)
                ok = True
        elif tp == "Rectangle":
            if rotation is None:
                rotation = obj.Placement.Rotation
            if obj.FilletRadius.Value == 0:
                for edge in obj.Shape.Edges:
                    nobj.addGeometry(DraftGeomUtils.orientEdge(edge))
                if autoconstraints:
                    last = nobj.GeometryCount - 1
                    segs = [last - 3, last - 2, last - 1, last]
                    if obj.Placement.Rotation.Q == (0, 0, 0, 1):
                        constraints.append(
                            Constraint("Coincident", last - 3, EndPoint,
                                       last - 2, StartPoint))
                        constraints.append(
                            Constraint("Coincident", last - 2, EndPoint,
                                       last - 1, StartPoint))
                        constraints.append(
                            Constraint("Coincident", last - 1, EndPoint, last,
                                       StartPoint))
                        constraints.append(
                            Constraint("Coincident", last, EndPoint, last - 3,
                                       StartPoint))
                    constraints.append(Constraint("Horizontal", last - 3))
                    constraints.append(Constraint("Vertical", last - 2))
                    constraints.append(Constraint("Horizontal", last - 1))
                    constraints.append(Constraint("Vertical", last))
                ok = True
        elif tp in ["Wire", "Polygon"]:
            if obj.FilletRadius.Value == 0:
                closed = False
                if tp == "Polygon":
                    closed = True
                elif hasattr(obj, "Closed"):
                    closed = obj.Closed

                if obj.Shape.Edges:
                    if (len(obj.Shape.Vertexes) < 3):
                        e = obj.Shape.Edges[0]
                        nobj.addGeometry(
                            Part.LineSegment(e.Curve, e.FirstParameter,
                                             e.LastParameter))
                    else:
                        # Use the first three points to make a working plane. We've already
                        # checked to make sure everything is coplanar
                        plane = Part.Plane(
                            *[i.Point for i in obj.Shape.Vertexes[:3]])
                        normal = plane.Axis
                        if rotation is None:
                            axis = App.Vector(0, 0, 1).cross(normal)
                            angle = DraftVecUtils.angle(
                                normal, App.Vector(0, 0, 1)) * App.Units.Radian
                            rotation = App.Rotation(axis, angle)
                        for edge in obj.Shape.Edges:
                            # edge.rotate(App.Vector(0,0,0), rotAxis, rotAngle)
                            edge = DraftGeomUtils.orientEdge(edge, normal)
                            nobj.addGeometry(edge)
                        if autoconstraints:
                            last = nobj.GeometryCount
                            segs = list(
                                range(last - len(obj.Shape.Edges), last - 1))
                            for seg in segs:
                                constraints.append(
                                    Constraint("Coincident", seg, EndPoint,
                                               seg + 1, StartPoint))
                                if DraftGeomUtils.isAligned(
                                        nobj.Geometry[seg], "x"):
                                    constraints.append(
                                        Constraint("Vertical", seg))
                                elif DraftGeomUtils.isAligned(
                                        nobj.Geometry[seg], "y"):
                                    constraints.append(
                                        Constraint("Horizontal", seg))
                            if closed:
                                constraints.append(
                                    Constraint("Coincident", last - 1,
                                               EndPoint, segs[0], StartPoint))
                    ok = True
        elif tp == "BSpline":
            if obj.Shape.Edges:
                nobj.addGeometry(obj.Shape.Edges[0].Curve)
                nobj.exposeInternalGeometry(nobj.GeometryCount - 1)
                ok = True
        elif tp == "BezCurve":
            if obj.Shape.Edges:
                bez = obj.Shape.Edges[0].Curve
                bsp = bez.toBSpline(bez.FirstParameter, bez.LastParameter)
                nobj.addGeometry(bsp)
                nobj.exposeInternalGeometry(nobj.GeometryCount - 1)
                ok = True
        elif tp == 'Shape' or hasattr(obj, 'Shape'):
            shape = obj if tp == 'Shape' else obj.Shape

            if not DraftGeomUtils.isPlanar(shape):
                App.Console.PrintError(
                    translate(
                        "draft",
                        "The given object is not planar and cannot be converted into a sketch."
                    ))
                return None
            if rotation is None:
                #rotation = obj.Placement.Rotation
                norm = DraftGeomUtils.getNormal(shape)
                if norm:
                    rotation = App.Rotation(App.Vector(0, 0, 1), norm)
                else:
                    App.Console.PrintWarning(
                        translate(
                            "draft",
                            "Unable to guess the normal direction of this object"
                        ))
                    rotation = App.Rotation()
                    norm = obj.Placement.Rotation.Axis
            if not shape.Wires:
                for e in shape.Edges:
                    # unconnected edges
                    newedge = convertBezier(e)
                    nobj.addGeometry(
                        DraftGeomUtils.orientEdge(newedge, norm,
                                                  make_arc=True))
                    addRadiusConstraint(newedge)

            # if not addTo:
            # nobj.Placement.Rotation = DraftGeomUtils.calculatePlacement(shape).Rotation

            if autoconstraints:
                for wire in shape.Wires:
                    last_count = nobj.GeometryCount
                    edges = wire.OrderedEdges
                    for edge in edges:
                        newedge = convertBezier(edge)
                        nobj.addGeometry(
                            DraftGeomUtils.orientEdge(newedge,
                                                      norm,
                                                      make_arc=True))
                        addRadiusConstraint(newedge)
                    for i, g in enumerate(nobj.Geometry[last_count:]):
                        if edges[i].Closed:
                            continue
                        seg = last_count + i

                        if DraftGeomUtils.isAligned(g, "x"):
                            constraints.append(Constraint("Vertical", seg))
                        elif DraftGeomUtils.isAligned(g, "y"):
                            constraints.append(Constraint("Horizontal", seg))

                        if seg == nobj.GeometryCount - 1:
                            if not wire.isClosed():
                                break
                            g2 = nobj.Geometry[last_count]
                            seg2 = last_count
                        else:
                            seg2 = seg + 1
                            g2 = nobj.Geometry[seg2]

                        end1 = g.value(g.LastParameter)
                        start2 = g2.value(g2.FirstParameter)
                        if DraftVecUtils.equals(end1, start2):
                            constraints.append(
                                Constraint("Coincident", seg, EndPoint, seg2,
                                           StartPoint))
                            continue
                        end2 = g2.value(g2.LastParameter)
                        start1 = g.value(g.FirstParameter)
                        if DraftVecUtils.equals(end2, start1):
                            constraints.append(
                                Constraint("Coincident", seg, StartPoint, seg2,
                                           EndPoint))
                        elif DraftVecUtils.equals(start1, start2):
                            constraints.append(
                                Constraint("Coincident", seg, StartPoint, seg2,
                                           StartPoint))
                        elif DraftVecUtils.equals(end1, end2):
                            constraints.append(
                                Constraint("Coincident", seg, EndPoint, seg2,
                                           EndPoint))
            else:
                for wire in shape.Wires:
                    for edge in wire.OrderedEdges:
                        newedge = convertBezier(edge)
                        nobj.addGeometry(
                            DraftGeomUtils.orientEdge(newedge,
                                                      norm,
                                                      make_arc=True))
            ok = True
        gui_utils.format_object(nobj, obj)
        if ok and delete and hasattr(obj, 'Shape'):
            doc = obj.Document

            def delObj(obj):
                if obj.InList:
                    App.Console.PrintWarning(
                        translate(
                            "draft", "Cannot delete object {} with dependency".
                            format(obj.Label)) + "\n")
                else:
                    doc.removeObject(obj.Name)

            try:
                if delete == 'all':
                    objs = [obj]
                    while objs:
                        obj = objs[0]
                        objs = objs[1:] + obj.OutList
                        delObj(obj)
                else:
                    delObj(obj)
            except Exception as ex:
                App.Console.PrintWarning(
                    translate(
                        "draft", "Failed to delete object {}: {}".format(
                            obj.Label, ex)) + "\n")
    if rotation:
        nobj.Placement.Rotation = rotation
    else:
        print("-----error!!! rotation is still None...")
    nobj.addConstraint(constraints)

    return nobj
示例#17
0
    def execute(self, obj):

        import Part, DraftGeomUtils, math
        pl = obj.Placement
        w = self.getWire(obj)
        if not w:
            FreeCAD.Console.PrintError(
                translate("Arch", "Unable to build the base path") + "\n")
            return
        if obj.OffsetStart.Value:
            e = w.Edges[0]
            v = e.Vertexes[-1].Point.sub(e.Vertexes[0].Point).normalize()
            v.multiply(obj.OffsetStart.Value)
            e = Part.LineSegment(e.Vertexes[0].Point.add(v),
                                 e.Vertexes[-1].Point).toShape()
            w = Part.Wire([e] + w.Edges[1:])
        if obj.OffsetEnd.Value:
            e = w.Edges[-1]
            v = e.Vertexes[0].Point.sub(e.Vertexes[-1].Point).normalize()
            v.multiply(obj.OffsetEnd.Value)
            e = Part.LineSegment(e.Vertexes[-1].Point.add(v),
                                 e.Vertexes[0].Point).toShape()
            w = Part.Wire(w.Edges[:-1] + [e])
        p = self.getProfile(obj)
        if not p:
            FreeCAD.Console.PrintError(
                translate("Arch", "Unable to build the profile") + "\n")
            return
        # move and rotate the profile to the first point
        if hasattr(p, "CenterOfMass"):
            c = p.CenterOfMass
        else:
            c = p.BoundBox.Center
        delta = w.Vertexes[0].Point - c
        p.translate(delta)
        import Draft
        if Draft.getType(obj.Base) == "BezCurve":
            v1 = obj.Base.Placement.multVec(
                obj.Base.Points[1]) - w.Vertexes[0].Point
        else:
            v1 = w.Vertexes[1].Point - w.Vertexes[0].Point
        v2 = DraftGeomUtils.getNormal(p)
        rot = FreeCAD.Rotation(v2, v1)
        p.rotate(w.Vertexes[0].Point, rot.Axis, math.degrees(rot.Angle))
        shapes = []
        try:
            if p.Faces:
                for f in p.Faces:
                    sh = w.makePipeShell([f.OuterWire], True, False, 2)
                    for shw in f.Wires:
                        if shw.hashCode() != f.OuterWire.hashCode():
                            sh2 = w.makePipeShell([shw], True, False, 2)
                            sh = sh.cut(sh2)
                    shapes.append(sh)
            elif p.Wires:
                for pw in p.Wires:
                    sh = w.makePipeShell([pw], True, False, 2)
                    shapes.append(sh)
        except Exception:
            FreeCAD.Console.PrintError(
                translate("Arch", "Unable to build the pipe") + "\n")
        else:
            if len(shapes) == 0:
                return
            elif len(shapes) == 1:
                sh = shapes[0]
            else:
                sh = Part.makeCompound(shapes)
            obj.Shape = sh
            if obj.Base:
                obj.Length = w.Length
            else:
                obj.Placement = pl
示例#18
0
    def execute(self, obj):

        tol = 1  # tolerance for alignment. This is only visual, we can keep it low...
        ptol = 0.001  # tolerance for coincident points

        import math, Part, DraftGeomUtils, ArchCommands
        if len(obj.Pipes) < 2:
            return
        if len(obj.Pipes) > 3:
            FreeCAD.Console.PrintWarning(
                translate("Arch", "Only the 3 first wires will be connected") +
                "\n")
        if obj.Radius.Value == 0:
            return
        wires = []
        order = []
        for o in obj.Pipes:
            wires.append(o.Proxy.getWire(o))
        if wires[0].Vertexes[0].Point.sub(
                wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["start", "start"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[0].Point.sub(
                wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["start", "end"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[-1].Point.sub(
                wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["end", "end"]
            point = wires[0].Vertexes[-1].Point
        elif wires[0].Vertexes[-1].Point.sub(
                wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["end", "start"]
            point = wires[0].Vertexes[-1].Point
        else:
            FreeCAD.Console.PrintError(
                translate("Arch", "Common vertex not found") + "\n")
            return
        if order[0] == "start":
            v1 = wires[0].Vertexes[1].Point.sub(
                wires[0].Vertexes[0].Point).normalize()
        else:
            v1 = wires[0].Vertexes[-2].Point.sub(
                wires[0].Vertexes[-1].Point).normalize()
        if order[1] == "start":
            v2 = wires[1].Vertexes[1].Point.sub(
                wires[1].Vertexes[0].Point).normalize()
        else:
            v2 = wires[1].Vertexes[-2].Point.sub(
                wires[1].Vertexes[-1].Point).normalize()
        p = obj.Pipes[0].Proxy.getProfile(obj.Pipes[0])
        p = Part.Face(p)
        if len(obj.Pipes) == 2:
            if obj.ConnectorType != "Corner":
                obj.ConnectorType = "Corner"
            if round(v1.getAngle(v2), tol) in [0, round(math.pi, tol)]:
                FreeCAD.Console.PrintError(
                    translate("Arch", "Pipes are already aligned") + "\n")
                return
            normal = v2.cross(v1)
            offset = math.tan(math.pi / 2 -
                              v1.getAngle(v2) / 2) * obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            self.setOffset(obj.Pipes[0], order[0], offset)
            self.setOffset(obj.Pipes[1], order[1], offset)
            # find center
            perp = v1.cross(normal).normalize()
            perp.multiply(obj.Radius.Value)
            center = point.add(v1).add(perp)
            # move and rotate the profile to the first point
            delta = point.add(v1) - p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp, v1)
            p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
            sh = p.revolve(center, normal,
                           math.degrees(math.pi - v1.getAngle(v2)))
            #sh = Part.makeCompound([sh]+[Part.Vertex(point),Part.Vertex(point.add(v1)),Part.Vertex(center),Part.Vertex(point.add(v2))])
        else:
            if obj.ConnectorType != "Tee":
                obj.ConnectorType = "Tee"
            if wires[2].Vertexes[0].Point == point:
                order.append("start")
            elif wires[0].Vertexes[-1].Point == point:
                order.append("end")
            else:
                FreeCAD.Console.PrintError(
                    translate("Arch", "Common vertex not found") + "\n")
            if order[2] == "start":
                v3 = wires[2].Vertexes[1].Point.sub(
                    wires[2].Vertexes[0].Point).normalize()
            else:
                v3 = wires[2].Vertexes[-2].Point.sub(
                    wires[2].Vertexes[-1].Point).normalize()
            if round(v1.getAngle(v2), tol) in [0, round(math.pi, tol)]:
                pair = [v1, v2, v3]
            elif round(v1.getAngle(v3), tol) in [0, round(math.pi, tol)]:
                pair = [v1, v3, v2]
            elif round(v2.getAngle(v3), tol) in [0, round(math.pi, tol)]:
                pair = [v2, v3, v1]
            else:
                FreeCAD.Console.PrintError(
                    translate("Arch", "At least 2 pipes must align") + "\n")
                return
            offset = obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            v3.multiply(offset)
            self.setOffset(obj.Pipes[0], order[0], offset)
            self.setOffset(obj.Pipes[1], order[1], offset)
            self.setOffset(obj.Pipes[2], order[2], offset)
            normal = pair[0].cross(pair[2])
            # move and rotate the profile to the first point
            delta = point.add(pair[0]) - p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp, pair[0])
            p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
            t1 = p.extrude(pair[1].multiply(2))
            # move and rotate the profile to the second point
            delta = point.add(pair[2]) - p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp, pair[2])
            p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
            t2 = p.extrude(pair[2].negative().multiply(2))
            # create a cut plane
            cp = Part.makePolygon(
                [point, point.add(pair[0]),
                 point.add(normal), point])
            cp = Part.Face(cp)
            if cp.normalAt(0, 0).getAngle(pair[2]) < math.pi / 2:
                cp.reverse()
            cf, cv, invcv = ArchCommands.getCutVolume(cp, t2)
            t2 = t2.cut(cv)
            sh = t1.fuse(t2)
        obj.Shape = sh
示例#19
0
 def execute(self, obj):
     pl = obj.Placement
     if obj.Source:
         base = None
         if Draft.getType(obj.Source) == "Panel":
             import Part, DraftGeomUtils
             baseobj = None
             if obj.Source.CloneOf:
                 baseobj = obj.Source.CloneOf.Base
             if obj.Source.Base:
                 baseobj = obj.Source.Base
             if baseobj:
                 if baseobj.isDerivedFrom("Part::Feature"):
                     if baseobj.Shape.Solids:
                         return
                     else:
                         base = Part.makeCompound(baseobj.Shape.Wires)
                         n = None
                         for w in base.Wires:
                             n = DraftGeomUtils.getNormal(w)
                             if n:
                                 break
                         if not n:
                             n = Vector(0, 0, 1)
                         base.translate(base.Vertexes[0].Point.negative())
                         r = FreeCAD.Rotation(n, Vector(0, 0, 1))
                         base.rotate(Vector(0, 0, 0), r.Axis,
                                     math.degrees(r.Angle))
                 elif baseobj.isDerivedFrom("Mesh::Feature"):
                     return
             else:
                 l2 = obj.Source.Length / 2
                 w2 = obj.Source.Width / 2
                 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])
             if base:
                 self.outline = base
                 if obj.FontFile and obj.TagText and obj.TagSize.Value:
                     if obj.TagPosition.Length == 0:
                         pos = base.BoundBox.Center
                     else:
                         pos = obj.TagPosition
                     if obj.TagText == "%tag%":
                         string = obj.Source.Tag
                     elif obj.TagText == "%label%":
                         string = obj.Source.Label
                     elif obj.TagText == "%description%":
                         string = obj.Source.Description
                     else:
                         string = obj.TagText
                     chars = []
                     for char in Part.makeWireString(
                             string, obj.FontFile, obj.TagSize.Value, 0):
                         chars.extend(char)
                     textshape = Part.Compound(chars)
                     textshape.translate(pos.sub(textshape.BoundBox.Center))
                     textshape.rotate(textshape.BoundBox.Center,
                                      Vector(0, 0, 1),
                                      obj.TagRotation.Value)
                     self.tag = textshape
                     base = Part.Compound([base, textshape])
                 else:
                     base = Part.Compound([base])
                 obj.Shape = base
                 obj.Placement = pl
示例#20
0
    def execute(self, obj):
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(
                        FreeCAD.Vector(0, 0, 1))
                    angle = bvec.getAngle(axis)
                    if round(angle, Draft.precision()) != 0:
                        if round(angle, Draft.precision()) != round(
                                math.pi, Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint),
                                           DraftVecUtils.tup(rotaxis),
                                           math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(
                        DraftVecUtils.tup(bpoint),
                        DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()),
                        obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
 def execute(self, obj):
     pl = obj.Placement
     if obj.Source:
         base = None
         if Draft.getType(obj.Source) == "Panel":
             import Part,DraftGeomUtils
             baseobj = None
             if obj.Source.CloneOf:
                 baseobj = obj.Source.CloneOf.Base
             if obj.Source.Base:
                 baseobj = obj.Source.Base
             if baseobj:
                 if baseobj.isDerivedFrom("Part::Feature"):
                     if baseobj.Shape.Solids:
                         return
                     else:
                         base = Part.makeCompound(baseobj.Shape.Wires)
                         n = None
                         for w in base.Wires:
                             n = DraftGeomUtils.getNormal(w)
                             if n:
                                 break
                         if not n:
                             n = Vector(0,0,1)
                         base.translate(base.Vertexes[0].Point.negative())
                         r = FreeCAD.Rotation(n,Vector(0,0,1))
                         base.rotate(Vector(0,0,0),r.Axis,math.degrees(r.Angle))
                 elif baseobj.isDerivedFrom("Mesh::Feature"):
                     return
             else:
                 l2 = obj.Source.Length/2
                 w2 = obj.Source.Width/2
                 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])
             if base:
                 self.outline = base
                 if obj.FontFile and obj.TagText and obj.TagSize.Value:
                     if obj.TagPosition.Length == 0:
                         pos = base.BoundBox.Center
                     else:
                         pos = obj.TagPosition
                     if obj.TagText == "%tag%":
                         string = obj.Source.Tag
                     elif obj.TagText == "%label%":
                         string = obj.Source.Label
                     elif obj.TagText == "%description%":
                         string = obj.Source.Description
                     else:
                         string = obj.TagText
                     chars = []
                     for char in Part.makeWireString(string,obj.FontFile,obj.TagSize.Value,0):
                         chars.extend(char)
                     textshape = Part.Compound(chars)
                     textshape.translate(pos.sub(textshape.BoundBox.Center))
                     textshape.rotate(textshape.BoundBox.Center,Vector(0,0,1),obj.TagRotation.Value)
                     self.tag = textshape
                     base = Part.Compound([base,textshape])
                 else:
                     base = Part.Compound([base])
                 obj.Shape = base
                 obj.Placement = pl
示例#22
0
    def execute(self,obj):
        "creates the structure shape"

        import Part, DraftGeomUtils
        
        if self.clone(obj):
            return

        normal,length,width,height = self.getDefaultValues(obj)

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
                if not obj.Base.Shape.isValid():
                    if not obj.Base.Shape.Solids:
                        # let pass invalid objects if they have solids...
                        return
                if hasattr(obj,"Tool"):
                    if obj.Tool:
                        try:
                            base = obj.Tool.Shape.copy().makePipe(obj.Base.Shape.copy())
                        except Part.OCCError:
                            FreeCAD.Console.PrintError(translate("Arch","Error: The base shape couldn't be extruded along this tool object"))
                            return
                if not base:
                    if not height:
                        return
                    if obj.Normal == Vector(0,0,0):
                        if len(obj.Base.Shape.Faces) > 0 :
                            normal=obj.Base.Shape.Faces[0].normalAt(.5,.5)
                        else:
                            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
                            if not normal:
                                normal = FreeCAD.Vector(0,0,1)
                            #p = FreeCAD.Placement(obj.Base.Placement)
                            #normal = p.Rotation.multVec(normal)
                    else:
                        normal = Vector(obj.Normal)
                    normal = normal.multiply(height)
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces:
                        base = base.extrude(normal)
                    elif (len(base.Wires) == 1):
                        if base.Wires[0].isClosed():
                            try:
                                base = Part.Face(base.Wires[0])
                                base = base.extrude(normal)
                            except Part.OCCError:
                                FreeCAD.Console.PrintError(obj.Label+" : "+str(translate("Arch","Unable to extrude the base shape\n")))
                                return

            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 and (not sh.isNull()):
                            base = sh
                        else:
                            FreeCAD.Console.PrintWarning(str(translate("Arch","This mesh is an invalid solid")))
                            obj.Base.ViewObject.show()
        else:
            base = self.getProfiles(obj)
            if base:
                if length > height:
                    normal = normal.multiply(length)
                else:
                    normal = normal.multiply(height)
                base = Part.Face(base[0])
                base = base.extrude(normal)

        base = self.processSubShapes(obj,base,pl)
        self.applyShape(obj,base,pl)
示例#23
0
    def execute(self, obj):
        "creates the structure shape"

        import Part, DraftGeomUtils

        if self.clone(obj):
            return

        normal, length, width, height = self.getDefaultValues(obj)

        # creating base shape
        pl = obj.Placement
        base = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
                if not obj.Base.Shape.isValid():
                    if not obj.Base.Shape.Solids:
                        # let pass invalid objects if they have solids...
                        return
                if hasattr(obj, "Tool"):
                    if obj.Tool:
                        try:
                            base = obj.Tool.Shape.copy().makePipe(
                                obj.Base.Shape.copy())
                        except Part.OCCError:
                            FreeCAD.Console.PrintError(
                                translate(
                                    "Arch",
                                    "Error: The base shape couldn't be extruded along this tool object"
                                ))
                            return
                if not base:
                    if not height:
                        return
                    if obj.Normal == Vector(0, 0, 0):
                        if len(obj.Base.Shape.Faces) > 0:
                            normal = obj.Base.Shape.Faces[0].normalAt(.5, .5)
                        else:
                            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
                            if not normal:
                                normal = FreeCAD.Vector(0, 0, 1)
                            #p = FreeCAD.Placement(obj.Base.Placement)
                            #normal = p.Rotation.multVec(normal)
                    else:
                        normal = Vector(obj.Normal)
                    normal = normal.multiply(height)
                    base = obj.Base.Shape.copy()
                    if base.Solids:
                        pass
                    elif base.Faces:
                        base = base.extrude(normal)
                    elif (len(base.Wires) == 1):
                        if base.Wires[0].isClosed():
                            try:
                                base = Part.Face(base.Wires[0])
                                base = base.extrude(normal)
                            except Part.OCCError:
                                FreeCAD.Console.PrintError(
                                    obj.Label + " : " + str(
                                        translate(
                                            "Arch",
                                            "Unable to extrude the base shape\n"
                                        )))
                                return

            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 and (
                                not sh.isNull()):
                            base = sh
                        else:
                            FreeCAD.Console.PrintWarning(
                                str(
                                    translate(
                                        "Arch",
                                        "This mesh is an invalid solid")))
                            obj.Base.ViewObject.show()
        else:
            base = self.getProfiles(obj)
            if base:
                if length > height:
                    normal = normal.multiply(length)
                else:
                    normal = normal.multiply(height)
                base = Part.Face(base[0])
                base = base.extrude(normal)

        base = self.processSubShapes(obj, base, pl)
        self.applyShape(obj, base, pl)
示例#24
0
    def getRebarData(self,obj):

        if not obj.Host:
            return
        if Draft.getType(obj.Host) != "Structure":
            return
        if not obj.Host.Shape:
            return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.Host
        wire = obj.Base.Shape.Wires[0]
        if Draft.getType(obj.Base) == "Wire": # Draft Wires can have "wrong" placement
            import DraftGeomUtils
            axis = DraftGeomUtils.getNormal(obj.Base.Shape)
        else:
            axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,0,-1))
        size = (ArchCommands.projectToVector(father.Shape.copy(),axis)).Length
        if hasattr(obj,"Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
        if hasattr(obj,"Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        if hasattr(obj,"Rounding"):
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire,radius)
        wires = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis,size/2)
            wire.translate(offset)
            wires.append(wire)
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis,obj.OffsetStart.Value)
            else:
                baseoffset = None
            if obj.ViewObject.RebarShape == "Stirrup":
                interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value + obj.Diameter.Value)
            else:
                interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            vinterval = DraftVecUtils.scaleTo(axis,interval)
            for i in range(obj.Amount):
                if i == 0:
                    if baseoffset:
                        wire.translate(baseoffset)
                    wires.append(wire)
                else:
                    wire = wire.copy()
                    wire.translate(vinterval)
                    wires.append(wire)
        return [wires,obj.Diameter.Value/2]
示例#25
0
    def execute(self,obj):
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
示例#26
0
    def execute(self, obj):

        if self.clone(obj):
            return

        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj, "ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(
                        baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj, "BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(
                            DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(
                            translate(
                                "Arch",
                                "Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else:
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(
                        FreeCAD.Vector(0, 0, 1))
                    angle = bvec.getAngle(axis)
                    if round(angle, Draft.precision()) != 0:
                        if round(angle, Draft.precision()) != round(
                                math.pi, Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint),
                                           DraftVecUtils.tup(rotaxis),
                                           math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(
                        DraftVecUtils.tup(bpoint),
                        DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()),
                        obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
示例#27
0
    def execute(self,obj):
        
        if self.clone(obj):
            return
        
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj,"ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
示例#28
0
    def execute(self,obj):
        
        if self.clone(obj):
            return
        
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj,"ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            edges = obj.Base.Shape.Edges
            if hasattr(obj,"Edges"):
                if obj.Edges == "Vertical edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                elif obj.Edges == "Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                elif obj.Edges == "Top Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                    edges = sorted(edges,key=lambda x: x.CenterOfMass.z,reverse=True)
                    z = edges[0].CenterOfMass.z
                    edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001]
                elif obj.Edges == "Bottom Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
                    edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]]
                    edges = sorted(edges,key=lambda x: x.CenterOfMass.z)
                    z = edges[0].CenterOfMass.z
                    edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001]
            for e in edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                if hasattr(obj,"Fuse"):
                    if obj.Fuse:
                        if len(shapes) > 1:
                            s = shapes[0].multiFuse(shapes[1:])
                            s = s.removeSplitter()
                            obj.Shape = s
                            obj.Placement = pl
                            return
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
示例#29
0
    def execute(self, obj):

        if self.clone(obj):
            return

        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.Shape:
                return
            if obj.Profile.Shape.findPlane() is None:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj, "ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(
                        baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            edges = obj.Base.Shape.Edges
            if hasattr(obj, "Edges"):
                if obj.Edges == "Vertical edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(0, 1, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                elif obj.Edges == "Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                elif obj.Edges == "Top Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                    edges = sorted(edges,
                                   key=lambda x: x.CenterOfMass.z,
                                   reverse=True)
                    z = edges[0].CenterOfMass.z
                    edges = [
                        e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001
                    ]
                elif obj.Edges == "Bottom Horizontal edges":
                    rv = obj.Base.Placement.Rotation.multVec(
                        FreeCAD.Vector(1, 0, 0))
                    edges = [
                        e for e in edges
                        if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4)
                        in [0, 3.1416]
                    ]
                    edges = sorted(edges, key=lambda x: x.CenterOfMass.z)
                    z = edges[0].CenterOfMass.z
                    edges = [
                        e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001
                    ]
            for e in edges:
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                rot = None  # New rotation.
                # Supplying FreeCAD.Rotation() with two parallel vectors and
                # a null vector may seem strange, but the function is perfectly
                # able to handle this. Its algorithm will use default axes in
                # such cases.
                if obj.Align:
                    if normal is None:
                        rot = FreeCAD.Rotation(FreeCAD.Vector(), bvec, bvec,
                                               "ZYX")
                    else:
                        rot = FreeCAD.Rotation(FreeCAD.Vector(), normal, bvec,
                                               "ZYX")
                    profile.Placement.Rotation = rot
                if hasattr(obj, "BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.Placement.Base]
                    for edge in edges:
                        basepointliste.append(
                            DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(
                            translate("Arch",
                                      "Crossing point not found in profile.") +
                            "\n")
                        basepoint = basepointliste[0]
                else:
                    basepoint = profile.Placement.Base
                delta = bpoint.sub(basepoint)  # Translation vector.
                if obj.Offset and (not DraftVecUtils.isNull(obj.Offset)):
                    if rot is None:
                        delta = delta + obj.Offset
                    else:
                        delta = delta + rot.multVec(obj.Offset)
                profile.translate(delta)
                if obj.Rotation:
                    profile.rotate(bpoint, bvec, obj.Rotation)
                # profile = wire.makePipeShell([profile], True, False, 2) TODO buggy
                profile = profile.extrude(bvec)
                shapes.append(profile)
            if shapes:
                if hasattr(obj, "Fuse"):
                    if obj.Fuse:
                        if len(shapes) > 1:
                            s = shapes[0].multiFuse(shapes[1:])
                            s = s.removeSplitter()
                            obj.Shape = s
                            obj.Placement = pl
                            return
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
示例#30
0
    def getRebarData(self, obj):

        #if not obj.Host:
        #    return
        #if Draft.getType(obj.Host) != "Structure":
        #    return
        #if not obj.Host.Shape:
        #    return
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = None
        if obj.Host:
            father = obj.Host
        wire = obj.Base.Shape.Wires[0]
        axis = None
        if Draft.getType(
                obj.Base) == "Wire":  # Draft Wires can have "wrong" placement
            import DraftGeomUtils
            axis = DraftGeomUtils.getNormal(obj.Base.Shape)
        if not axis:
            axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(
                0, 0, -1))
        size = 0
        if father:
            size = (ArchCommands.projectToVector(father.Shape.copy(),
                                                 axis)).Length
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
        if hasattr(obj, "Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        if hasattr(obj, "Rounding"):
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        wires = []
        if obj.Amount == 1:
            if size and father:
                offset = DraftVecUtils.scaleTo(axis, size / 2)
            else:
                offset = FreeCAD.Vector()
            wire.translate(offset)
            wires.append(wire)
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            if hasattr(obj, "RebarShape") and obj.RebarShape == "Stirrup":
                interval = size - (obj.OffsetStart.Value +
                                   obj.OffsetEnd.Value + obj.Diameter.Value)
            else:
                interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            vinterval = DraftVecUtils.scaleTo(axis, interval)
            for i in range(obj.Amount):
                if i == 0:
                    if baseoffset:
                        wire.translate(baseoffset)
                    wires.append(wire)
                else:
                    wire = wire.copy()
                    wire.translate(vinterval)
                    wires.append(wire)
        return [wires, obj.Diameter.Value / 2]
示例#31
0
def calculatePlacementsOnPath(shapeRotation, pathwire, count, xlate, align,
        mode = 'Original', forceNormal=False, normalOverride=None):
    """Calculates the placements of a shape along a given path so that each copy will be distributed evenly"""
    import Part
    import DraftGeomUtils
    closedpath = DraftGeomUtils.isReallyClosed(pathwire)

    normal = DraftGeomUtils.getNormal(pathwire)
    if forceNormal and normalOverride:
            normal = normalOverride

    path = Part.__sortEdges__(pathwire.Edges)
    ends = []
    cdist = 0

    for e in path:                                                 # find cumulative edge end distance
        cdist += e.Length
        ends.append(cdist)

    placements = []

    # place the start shape
    pt = path[0].Vertexes[0].Point
    placements.append(calculatePlacement(
        shapeRotation, path[0], 0, pt, xlate, align, normal, mode, forceNormal))

    # closed path doesn't need shape on last vertex
    if not(closedpath):
        # place the end shape
        pt = path[-1].Vertexes[-1].Point
        placements.append(calculatePlacement(
            shapeRotation, path[-1], path[-1].Length, pt, xlate, align, normal, mode, forceNormal))

    if count < 3:
        return placements

    # place the middle shapes
    if closedpath:
        stop = count
    else:
        stop = count - 1
    step = float(cdist) / stop
    remains = 0
    travel = step
    for i in range(1, stop):
        # which edge in path should contain this shape?
        # avoids problems with float math travel > ends[-1]
        iend = len(ends) - 1

        for j in range(0, len(ends)):
            if travel <= ends[j]:
                iend = j
                break

        # place shape at proper spot on proper edge
        remains = ends[iend] - travel
        offset = path[iend].Length - remains
        pt = path[iend].valueAt(getParameterFromV0(path[iend], offset))

        placements.append(calculatePlacement(
            shapeRotation, path[iend], offset, pt, xlate, align, normal, mode, forceNormal))

        travel += step

    return placements