Ejemplo n.º 1
0
    def makeStraightStairsWithLanding(self,obj,edge):
        
        "builds a straight staircase with a landing in the middle"

        if obj.NumberOfSteps < 3:
            return
        import Part,DraftGeomUtils
        v = DraftGeomUtils.vec(edge)
        reslength = edge.Length - obj.Width.Value
        vLength = DraftVecUtils.scaleTo(v,float(reslength)/(obj.NumberOfSteps-2))
        vLength = Vector(vLength.x,vLength.y,0)
        vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        p1 = edge.Vertexes[0].Point
        if round(v.z,Draft.precision()) != 0:
            h = v.z
        else:
            h = obj.Height.Value
        hstep = h/obj.NumberOfSteps
        landing = obj.NumberOfSteps/2
        p2 = p1.add(DraftVecUtils.scale(vLength,landing-1).add(Vector(0,0,landing*hstep)))
        p3 = p2.add(DraftVecUtils.scaleTo(vLength,obj.Width.Value))
        p4 = p3.add(DraftVecUtils.scale(vLength,obj.NumberOfSteps-(landing+1)).add(Vector(0,0,(obj.NumberOfSteps-landing)*hstep)))
        self.makeStraightStairs(obj,Part.Line(p1,p2).toShape(),landing)
        self.makeStraightLanding(obj,Part.Line(p2,p3).toShape())
        self.makeStraightStairs(obj,Part.Line(p3,p4).toShape(),obj.NumberOfSteps-landing)
Ejemplo n.º 2
0
 def align(self,basepoint,align,width,widthvec):
     "moves a given basepoint according to the alignment"
     if align == "Center":
         basepoint = basepoint.add(DraftVecUtils.scaleTo(widthvec,-width/2))
     elif align == "Right":
         basepoint = basepoint.add(DraftVecUtils.scaleTo(widthvec,-width))
     return basepoint
Ejemplo n.º 3
0
    def getRebarData(self,obj):

        if len(obj.InList) != 1:
            return
        if Draft.getType(obj.InList[0]) != "Structure":
            return
        if not obj.InList[0].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.InList[0]
        wire = obj.Base.Shape.Wires[0]
        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
            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]
Ejemplo n.º 4
0
 def createGeometry(self,obj):
     import Part, DraftGeomUtils
     pl = obj.Placement
     base = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if hasattr(obj,"WindowParts"):
                 if obj.WindowParts and (len(obj.WindowParts)%5 == 0):
                     shapes = []
                     for i in range(len(obj.WindowParts)/5):
                         wires = []
                         wstr = obj.WindowParts[(i*5)+2].split(',')
                         for s in wstr:
                             j = int(s[4:])
                             if obj.Base.Shape.Wires:
                                 if len(obj.Base.Shape.Wires) >= j:
                                     wires.append(obj.Base.Shape.Wires[j])
                         if wires:
                             max_length = 0
                             for w in wires:
                                 if w.BoundBox.DiagonalLength > max_length:
                                     max_length = w.BoundBox.DiagonalLength
                                     ext = w
                             wires.remove(ext)
                             shape = Part.Face(ext)
                             norm = shape.normalAt(0,0)
                             thk = float(obj.WindowParts[(i*5)+3])
                             if thk:
                                 exv = DraftVecUtils.scaleTo(norm,thk)
                                 shape = shape.extrude(exv)
                                 for w in wires:
                                     f = Part.Face(w)
                                     f = f.extrude(exv)
                                     shape = shape.cut(f)
                             if obj.WindowParts[(i*5)+4]:
                                 zof = float(obj.WindowParts[(i*5)+4])
                                 if zof:
                                     zov = DraftVecUtils.scaleTo(norm,zof)
                                     shape.translate(zov)
                             shapes.append(shape)
                     if shapes:
                         base = Part.makeCompound(shapes)
                         if not DraftGeomUtils.isNull(pl):
                             base.Placement = pl
                         
     base = self.processSubShapes(obj,base)
     if base:
         if not base.isNull():
             obj.Shape = base
Ejemplo n.º 5
0
    def update(self, line=None, normal=None):
        import WorkingPlane, DraftGeomUtils

        if not normal:
            normal = FreeCAD.DraftWorkingPlane.axis
        if line:
            if isinstance(line, list):
                bp = line[0]
                lvec = line[1].sub(line[0])
            else:
                lvec = DraftGeomUtils.vec(line.Shape.Edges[0])
                bp = line.Shape.Edges[0].Vertexes[0].Point
        elif self.baseline:
            lvec = DraftGeomUtils.vec(self.baseline.Shape.Edges[0])
            bp = self.baseline.Shape.Edges[0].Vertexes[0].Point
        else:
            return
        right = lvec.cross(normal)
        self.cube.width.setValue(lvec.Length)
        p = WorkingPlane.getPlacementFromPoints([bp, bp.add(lvec), bp.add(right)])
        if p:
            self.trans.rotation.setValue(p.Rotation.Q)
        bp = bp.add(lvec.multiply(0.5))
        bp = bp.add(DraftVecUtils.scaleTo(normal, self.cube.depth.getValue() / 2))
        self.pos(bp)
Ejemplo n.º 6
0
 def getSubVolume(self,obj,extension=10000):
     "returns a volume to be subtracted"
     if hasattr(self,"baseface"):
         if self.baseface:
             norm = self.baseface.normalAt(0,0)
             norm = DraftVecUtils.scaleTo(norm,extension)
             return self.baseface.extrude(norm)
     return None
Ejemplo n.º 7
0
    def getBase(self, obj, wire, normal, width, height):
        "returns a full shape from a base wire"
        import DraftGeomUtils, Part

        flat = False
        if hasattr(obj.ViewObject, "DisplayMode"):
            flat = obj.ViewObject.DisplayMode == "Flat 2D"
        dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
        if not DraftVecUtils.isNull(dvec):
            dvec.normalize()
        if obj.Align == "Left":
            dvec.multiply(width)
            if hasattr(obj, "Offset"):
                if obj.Offset:
                    dvec2 = DraftVecUtils.scaleTo(dvec, obj.Offset)
                    wire = DraftGeomUtils.offsetWire(wire, dvec2)
            w2 = DraftGeomUtils.offsetWire(wire, dvec)
            w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
            sh = DraftGeomUtils.bind(w1, w2)
        elif obj.Align == "Right":
            dvec.multiply(width)
            dvec = dvec.negative()
            if hasattr(obj, "Offset"):
                if obj.Offset:
                    dvec2 = DraftVecUtils.scaleTo(dvec, obj.Offset)
                    wire = DraftGeomUtils.offsetWire(wire, dvec2)
            w2 = DraftGeomUtils.offsetWire(wire, dvec)
            w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
            sh = DraftGeomUtils.bind(w1, w2)
        elif obj.Align == "Center":
            dvec.multiply(width / 2)
            w1 = DraftGeomUtils.offsetWire(wire, dvec)
            dvec = dvec.negative()
            w2 = DraftGeomUtils.offsetWire(wire, dvec)
            sh = DraftGeomUtils.bind(w1, w2)
        # fixing self-intersections
        sh.fix(0.1, 0, 1)
        self.BaseProfile = sh
        if height and (not flat):
            self.ExtrusionVector = Vector(normal).multiply(height)
            sh = sh.extrude(self.ExtrusionVector)
        return sh
Ejemplo n.º 8
0
def CalculatePlacement(baramount, barnumber, size, axis, rotation, offsetstart, offsetend):
    """ CalculatePlacement([baramount, barnumber, size, axis, rotation, offsetstart, offsetend]):
    Calculate the placement of the bar from given values."""
    if baramount == 1:
        interval = offsetstart
    else:
        interval = size - (offsetstart + offsetend)
        interval = interval / (baramount - 1)
    bardistance = (interval * (barnumber - 1)) + offsetstart
    barplacement = DraftVecUtils.scaleTo(axis, bardistance)
    placement = FreeCAD.Placement(barplacement, rotation)
    return placement
Ejemplo n.º 9
0
def CustomSpacingPlacement(spacinglist, barnumber, axis, rotation, offsetstart, offsetend):
    """ CustomSpacingPlacement(spacinglist, barnumber, axis, rotation, offsetstart, offsetend):
    Calculate placement of the bar from custom spacing list."""
    if barnumber == 1:
        bardistance = offsetstart
    else:
        bardistance = sum(spacinglist[0:barnumber])
        bardistance = bardistance - spacinglist[0] / 2
        bardistance = bardistance - spacinglist[barnumber - 1] / 2
        bardistance = bardistance + offsetstart
    barplacement = DraftVecUtils.scaleTo(axis, bardistance)
    placement = FreeCAD.Placement(barplacement, rotation)
    return placement
Ejemplo n.º 10
0
 def projectPoint(self, p, direction=None):
     '''project point onto plane, default direction is orthogonal'''
     if not direction:
         direction = self.axis
     lp = self.getLocalCoords(p)
     gp = self.getGlobalCoords(Vector(lp.x,lp.y,0))
     a = direction.getAngle(gp.sub(p))
     if a > math.pi/2:
         direction = direction.negative()
         a = math.pi - a
     ld = self.getLocalRot(direction)
     gd = self.getGlobalRot(Vector(ld.x,ld.y,0))
     hyp = abs(math.tan(a) * lp.z)
     return gp.add(DraftVecUtils.scaleTo(gd,hyp))
Ejemplo n.º 11
0
 def update(self,point):
     "this function is called by the Snapper when the mouse is moved"
     b = self.points[0]
     n = FreeCAD.DraftWorkingPlane.axis
     bv = point.sub(b)
     dv = bv.cross(n)
     dv = DraftVecUtils.scaleTo(dv,self.Width/2)
     if self.Align == "Center":
         self.tracker.update([b,point])
     elif self.Align == "Left":
         self.tracker.update([b.add(dv),point.add(dv)])
     else:
         dv = DraftVecUtils.neg(dv)
         self.tracker.update([b.add(dv),point.add(dv)])
Ejemplo n.º 12
0
def getCutVolume(cutplane, shapes):
    """getCutVolume(cutplane,shapes): returns a cut face and a cut volume
    from the given shapes and the given cutting plane"""
    import Part

    placement = FreeCAD.Placement(cutplane.Placement)
    # building boundbox
    bb = shapes[0].BoundBox
    for sh in shapes[1:]:
        bb.add(sh.BoundBox)
    bb.enlarge(1)
    um = vm = wm = 0
    ax = placement.Rotation.multVec(FreeCAD.Vector(0, 0, 1))
    u = placement.Rotation.multVec(FreeCAD.Vector(1, 0, 0))
    v = placement.Rotation.multVec(FreeCAD.Vector(0, 1, 0))
    if not bb.isCutPlane(placement.Base, ax):
        FreeCAD.Console.PrintMessage(str(translate("Arch", "No objects are cut by the plane")))
        return None, None, None
    else:
        corners = [
            FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin),
            FreeCAD.Vector(bb.XMin, bb.YMax, bb.ZMin),
            FreeCAD.Vector(bb.XMax, bb.YMin, bb.ZMin),
            FreeCAD.Vector(bb.XMax, bb.YMax, bb.ZMin),
            FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMax),
            FreeCAD.Vector(bb.XMin, bb.YMax, bb.ZMax),
            FreeCAD.Vector(bb.XMax, bb.YMin, bb.ZMax),
            FreeCAD.Vector(bb.XMax, bb.YMax, bb.ZMax),
        ]
        for c in corners:
            dv = c.sub(placement.Base)
            um1 = DraftVecUtils.project(dv, u).Length
            um = max(um, um1)
            vm1 = DraftVecUtils.project(dv, v).Length
            vm = max(vm, vm1)
            wm1 = DraftVecUtils.project(dv, ax).Length
            wm = max(wm, wm1)
        p1 = FreeCAD.Vector(-um, vm, 0)
        p2 = FreeCAD.Vector(um, vm, 0)
        p3 = FreeCAD.Vector(um, -vm, 0)
        p4 = FreeCAD.Vector(-um, -vm, 0)
        cutface = Part.makePolygon([p1, p2, p3, p4, p1])
        cutface = Part.Face(cutface)
        cutface.Placement = placement
        cutnormal = DraftVecUtils.scaleTo(ax, wm)
        cutvolume = cutface.extrude(cutnormal)
        cutnormal = DraftVecUtils.neg(cutnormal)
        invcutvolume = cutface.extrude(cutnormal)
        return cutface, cutvolume, invcutvolume
Ejemplo n.º 13
0
def projectToVector(shape, vector):
    """projectToVector(shape,vector): projects the given shape on the given
    vector"""
    projpoints = []
    minl = 10000000000
    maxl = -10000000000
    for v in shape.Vertexes:
        p = DraftVecUtils.project(v.Point, vector)
        projpoints.append(p)
        l = p.Length
        if p.getAngle(vector) > 1:
            l = -l
        if l > maxl:
            maxl = l
        if l < minl:
            minl = l
    return DraftVecUtils.scaleTo(vector, maxl - minl)
Ejemplo n.º 14
0
def getCutVolume(cutplane,shapes):
    """getCutVolume(cutplane,shapes): returns a cut face and a cut volume
    from the given shapes and the given cutting plane"""
    import Part
    placement = FreeCAD.Placement(cutplane.Placement)
    # building boundbox
    bb = shapes[0].BoundBox 
    for sh in shapes[1:]:
        bb.add(sh.BoundBox)
    bb.enlarge(1)
    um = vm = wm = 0
    ax = placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
    u = placement.Rotation.multVec(FreeCAD.Vector(1,0,0))
    v = placement.Rotation.multVec(FreeCAD.Vector(0,1,0))
    if not bb.isCutPlane(placement.Base,ax):
        FreeCAD.Console.PrintMessage(str(translate("Arch","No objects are cut by the plane")))
        return None,None,None
    else:
        corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
                   FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin),
                   FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMin),
                   FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMin),
                   FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMax),
                   FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMax),
                   FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
                   FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
        for c in corners:
            dv = c.sub(placement.Base)
            um1 = DraftVecUtils.project(dv,u).Length
            um = max(um,um1)
            vm1 = DraftVecUtils.project(dv,v).Length
            vm = max(vm,vm1)
            wm1 = DraftVecUtils.project(dv,ax).Length
            wm = max(wm,wm1)
        p1 = FreeCAD.Vector(-um,vm,0)
        p2 = FreeCAD.Vector(um,vm,0)
        p3 = FreeCAD.Vector(um,-vm,0)
        p4 = FreeCAD.Vector(-um,-vm,0)
        cutface = Part.makePolygon([p1,p2,p3,p4,p1])
        cutface = Part.Face(cutface)
        cutface.Placement = placement
        cutnormal = DraftVecUtils.scaleTo(ax,wm)
        cutvolume = cutface.extrude(cutnormal)
        cutnormal = DraftVecUtils.neg(cutnormal)
        invcutvolume = cutface.extrude(cutnormal)
        return cutface,cutvolume,invcutvolume
Ejemplo n.º 15
0
 def makeStairsTread(self,basepoint,depthvec,widthvec,nosing=0,thickness=0):
     "returns the shape of a single tread"
     import Part
     if thickness:
         basepoint = basepoint.add(Vector(0,0,-abs(thickness)))
     if nosing:
         nosevec = DraftVecUtils.scaleTo(DraftVecUtils.neg(depthvec),nosing)
     else:
         nosevec = Vector(0,0,0)
     p1 = basepoint.add(nosevec)
     p2 = p1.add(DraftVecUtils.neg(nosevec)).add(depthvec)
     p3 = p2.add(widthvec)
     p4 = p3.add(DraftVecUtils.neg(depthvec)).add(nosevec)
     step = Part.Face(Part.makePolygon([p1,p2,p3,p4,p1]))
     if thickness:
         step = step.extrude(Vector(0,0,abs(thickness)))
     return step
Ejemplo n.º 16
0
 def update(self, point, info):
     "this function is called by the Snapper when the mouse is moved"
     if FreeCADGui.Control.activeDialog():
         b = self.points[0]
         n = FreeCAD.DraftWorkingPlane.axis
         bv = point.sub(b)
         dv = bv.cross(n)
         dv = DraftVecUtils.scaleTo(dv, self.Width / 2)
         if self.Align == "Center":
             self.tracker.update([b, point])
         elif self.Align == "Left":
             self.tracker.update([b.add(dv), point.add(dv)])
         else:
             dv = dv.negative()
             self.tracker.update([b.add(dv), point.add(dv)])
         if self.Length:
             self.Length.setText(self.FORMAT % bv.Length)
Ejemplo n.º 17
0
def projectToVector(shape,vector):
    '''projectToVector(shape,vector): projects the given shape on the given
    vector'''
    projpoints = []
    minl = 10000000000
    maxl = -10000000000
    for v in shape.Vertexes:
        p = DraftVecUtils.project(v.Point,vector)
        projpoints.append(p)
        l = p.Length
        if p.getAngle(vector) > 1:
            l = -l
        if l > maxl:
            maxl = l
        if l < minl:
            minl = l
    return DraftVecUtils.scaleTo(vector,maxl-minl)
Ejemplo n.º 18
0
 def update(self,point,info):
     "this function is called by the Snapper when the mouse is moved"
     if FreeCADGui.Control.activeDialog():
         b = self.points[0]
         n = FreeCAD.DraftWorkingPlane.axis
         bv = point.sub(b)
         dv = bv.cross(n)
         dv = DraftVecUtils.scaleTo(dv,self.Width/2)
         if self.Align == "Center":
             self.tracker.update([b,point])
         elif self.Align == "Left":
             self.tracker.update([b.add(dv),point.add(dv)])
         else:
             dv = dv.negative()
             self.tracker.update([b.add(dv),point.add(dv)])
         if self.Length:
             self.Length.setText(FreeCAD.Units.Quantity(bv.Length,FreeCAD.Units.Length).UserString)
Ejemplo n.º 19
0
    def getCenterPoint(self, x, y, z):

        if not self.taskd.form.checkCenter.isChecked():
            return FreeCAD.Vector()
        v = FreeCAD.Vector(x, y, z)
        cam1 = FreeCAD.Vector(FreeCADGui.ActiveDocument.ActiveView.
                              getCameraNode().position.getValue().getValue())
        cam2 = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
        vcam1 = DraftVecUtils.project(cam1, v)
        a = vcam1.getAngle(cam2)
        if a < 0.0001:
            return FreeCAD.Vector()
        d = vcam1.Length
        L = d / math.cos(a)
        vcam2 = DraftVecUtils.scaleTo(cam2, L)
        cp = cam1.add(vcam2)
        return cp
Ejemplo n.º 20
0
def shp_cyl(r, h, normal=VZ, pos=V0):
    # we have to bring the active document
    doc = FreeCAD.ActiveDocument

    cir = Part.makeCircle(
        r,  # Radius
        pos,  # Position
        normal)  # direction

    #print "circle: %", cir_out.Curve

    wire_cir = Part.Wire(cir)
    face_cir = Part.Face(wire_cir)

    dir_extrus = DraftVecUtils.scaleTo(normal, h)
    shpcyl = face_cir.extrude(dir_extrus)

    return shpcyl
Ejemplo n.º 21
0
 def snapToPerpendicular(self, shape, last):
     "returns a list of perpendicular snap locations"
     snaps = []
     if self.isEnabled("perpendicular"):
         if last:
             if isinstance(shape, Part.Edge):
                 if DraftGeomUtils.geomType(shape) == "Line":
                     np = self.getPerpendicular(shape, last)
                 elif DraftGeomUtils.geomType(shape) == "Circle":
                     dv = last.sub(shape.Curve.Center)
                     dv = DraftVecUtils.scaleTo(dv, shape.Curve.Radius)
                     np = (shape.Curve.Center).add(dv)
                 elif DraftGeomUtils.geomType(shape) == "BSplineCurve":
                     pr = shape.Curve.parameter(last)
                     np = shape.Curve.value(pr)
                 else:
                     return snaps
                 snaps.append([np, 'perpendicular', np])
     return snaps
Ejemplo n.º 22
0
 def snapToPerpendicular(self,shape,last):
     "returns a list of perpendicular snap locations"
     snaps = []
     if self.isEnabled("perpendicular"):
         if last:
             if isinstance(shape,Part.Edge):
                 if DraftGeomUtils.geomType(shape) == "Line":
                     np = self.getPerpendicular(shape,last)
                 elif DraftGeomUtils.geomType(shape) == "Circle":
                     dv = last.sub(shape.Curve.Center)
                     dv = DraftVecUtils.scaleTo(dv,shape.Curve.Radius)
                     np = (shape.Curve.Center).add(dv)
                 elif DraftGeomUtils.geomType(shape) == "BSplineCurve":
                     pr = shape.Curve.parameter(last)
                     np = shape.Curve.value(pr)
                 else:
                     return snaps
                 snaps.append([np,'perpendicular',np])
     return snaps
Ejemplo n.º 23
0
 def getSubVolume(self, base, width, plac=None):
     "returns a subvolume from a base object"
     import Part
     max_length = 0
     f = None
     for w in base.Shape.Wires:
         if w.BoundBox.DiagonalLength > max_length:
             max_length = w.BoundBox.DiagonalLength
             f = w
     if f:
         f = Part.Face(f)
         n = f.normalAt(0, 0)
         v1 = DraftVecUtils.scaleTo(n, width)
         f.translate(v1)
         v2 = DraftVecUtils.neg(v1)
         v2 = DraftVecUtils.scale(v1, -2)
         f = f.extrude(v2)
         if plac:
             f.Placement = plac
         return f
     return None
Ejemplo n.º 24
0
def addCylPos(r, h, name, normal=VZ, pos=V0):
    # we have to bring the active document
    doc = FreeCAD.ActiveDocument

    cir = Part.makeCircle(
        r,  # Radius
        pos,  # Position
        normal)  # direction

    #print "circle: %", cir_out.Curve

    wire_cir = Part.Wire(cir)
    face_cir = Part.Face(wire_cir)

    dir_extrus = DraftVecUtils.scaleTo(normal, h)
    shp_cyl = face_cir.extrude(dir_extrus)

    cyl = doc.addObject("Part::Feature", name)
    cyl.Shape = shp_cyl

    return cyl
Ejemplo n.º 25
0
 def getSubVolume(self,base,width,plac=None):
     "returns a subvolume from a base object"
     import Part
     max_length = 0
     f = None
     for w in base.Shape.Wires:
         if w.BoundBox.DiagonalLength > max_length:
             max_length = w.BoundBox.DiagonalLength
             f = w
     if f:
         f = Part.Face(f)
         n = f.normalAt(0,0)
         v1 = DraftVecUtils.scaleTo(n,width)
         f.translate(v1)
         v2 = DraftVecUtils.neg(v1)
         v2 = DraftVecUtils.scale(v1,-2)
         f = f.extrude(v2)
         if plac:
             f.Placement = plac
         return f
     return None
Ejemplo n.º 26
0
    def onChanged(self, obj, prop):
        if prop == "Start":
            pts = obj.Points
            invpl = App.Placement(obj.Placement).inverse()
            realfpstart = invpl.multVec(obj.Start)
            if pts:
                if pts[0] != realfpstart:
                    pts[0] = realfpstart
                    obj.Points = pts

        elif prop == "End":
            pts = obj.Points
            invpl = App.Placement(obj.Placement).inverse()
            realfpend = invpl.multVec(obj.End)
            if len(pts) > 1:
                if pts[-1] != realfpend:
                    pts[-1] = realfpend
                    obj.Points = pts

        elif prop == "Length":
            if (len(obj.Points) == 2
                    and obj.Length.Value > 1e-7
                    and obj.Shape
                    and (not obj.Shape.isNull())
                    and obj.Length.Value != obj.Shape.Length):
                v = obj.Points[-1].sub(obj.Points[0])
                v = DraftVecUtils.scaleTo(v, obj.Length.Value)
                obj.Points = [obj.Points[0], obj.Points[0].add(v)]

        elif prop == "Placement":
            pl = App.Placement(obj.Placement)
            if len(obj.Points) >= 2:
                displayfpstart = pl.multVec(obj.Points[0])
                displayfpend = pl.multVec(obj.Points[-1])
                if obj.Start != displayfpstart:
                    obj.Start = displayfpstart
                if obj.End != displayfpend:
                    obj.End = displayfpend
Ejemplo n.º 27
0
 def getSubVolume(self,base,width,plac=None):
     "returns a subvolume from a base object"
     import Part,DraftVecUtils
     
     # finding biggest wire in the base shape
     max_length = 0
     f = None
     for w in base.Shape.Wires:
         if w.BoundBox.DiagonalLength > max_length:
             max_length = w.BoundBox.DiagonalLength
             f = w
     if f:
         f = Part.Face(f)
         n = f.normalAt(0,0)
         v1 = DraftVecUtils.scaleTo(n,width*1.1) # we extrude a little more to avoid face-on-face
         f.translate(v1)
         v2 = DraftVecUtils.neg(v1)
         v2 = DraftVecUtils.scale(v1,-2)
         f = f.extrude(v2)
         if plac:
             f.Placement = plac
         return f
     return None
Ejemplo n.º 28
0
 def update(self,line=None,normal=None):
     import WorkingPlane, DraftGeomUtils
     if not normal:
         normal = FreeCAD.DraftWorkingPlane.axis
     if line:
         if isinstance(line,list):
             bp = line[0]
             lvec = line[1].sub(line[0])
         else:
             lvec = DraftGeomUtils.vec(line.Shape.Edges[0])
             bp = line.Shape.Edges[0].Vertexes[0].Point
     elif self.baseline:
         lvec = DraftGeomUtils.vec(self.baseline.Shape.Edges[0])
         bp = self.baseline.Shape.Edges[0].Vertexes[0].Point
     else:
         return
     right = lvec.cross(normal)
     self.cube.width.setValue(lvec.Length)
     p = WorkingPlane.getPlacementFromPoints([bp,bp.add(lvec),bp.add(right)])
     self.trans.rotation.setValue(p.Rotation.Q)
     bp = bp.add(DraftVecUtils.scale(lvec,0.5))
     bp = bp.add(DraftVecUtils.scaleTo(normal,self.cube.depth.getValue()/2))
     self.pos(bp)
Ejemplo n.º 29
0
def CalculatePlacement(baramount,
                       barnumber,
                       bardiameter,
                       size,
                       axis,
                       rotation,
                       offsetstart,
                       offsetend,
                       RebarShape=""):
    """ CalculatePlacement([baramount, barnumber, bardiameter, size, axis, rotation, offsetstart, offsetend, RebarShape]):
    Calculate the placement of the bar from given values."""
    if baramount == 1:
        interval = offsetstart
    else:
        if RebarShape == "Stirrup":
            interval = size - (offsetstart + offsetend + bardiameter)
        else:
            interval = size - (offsetstart + offsetend)
        interval = interval / (baramount - 1)
    bardistance = (interval * (barnumber - 1)) + offsetstart
    barplacement = DraftVecUtils.scaleTo(axis, bardistance)
    placement = FreeCAD.Placement(barplacement, rotation)
    return placement
Ejemplo n.º 30
0
 def getSubVolume(self,base,width,plac=None):
     "returns a subvolume from a base object"
     import Part,DraftVecUtils
     
     # finding biggest wire in the base shape
     max_length = 0
     f = None
     for w in base.Shape.Wires:
         if w.BoundBox.DiagonalLength > max_length:
             max_length = w.BoundBox.DiagonalLength
             f = w
     if f:
         f = Part.Face(f)
         n = f.normalAt(0,0)
         v1 = DraftVecUtils.scaleTo(n,width*1.1) # we extrude a little more to avoid face-on-face
         f.translate(v1)
         v2 = DraftVecUtils.neg(v1)
         v2 = DraftVecUtils.scale(v1,-2)
         f = f.extrude(v2)
         if plac:
             f.Placement = plac
         return f
     return None
Ejemplo n.º 31
0
    def makeStraightStairs(self,obj,edge,numberofsteps=None):

        "builds a simple, straight staircase from a straight edge"

        # general data
        import Part,DraftGeomUtils
        if not numberofsteps:
            numberofsteps = obj.NumberOfSteps
        v = DraftGeomUtils.vec(edge)
        vLength = DraftVecUtils.scaleTo(v,float(edge.Length)/(numberofsteps-1))
        vLength = Vector(vLength.x,vLength.y,0)
        if round(v.z,Draft.precision()) != 0:
            h = v.z
        else:
            h = obj.Height.Value
        vHeight = Vector(0,0,float(h)/numberofsteps)
        vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        vBase = edge.Vertexes[0].Point
        vNose = DraftVecUtils.scaleTo(vLength,-abs(obj.Nosing.Value))
        a = math.atan(vHeight.Length/vLength.Length)
        #print "stair data:",vLength.Length,":",vHeight.Length

        # steps
        for i in range(numberofsteps-1):
            p1 = vBase.add((Vector(vLength).multiply(i)).add(Vector(vHeight).multiply(i+1)))
            p1 = self.align(p1,obj.Align,vWidth)
            p1 = p1.add(vNose).add(Vector(0,0,-abs(obj.TreadThickness.Value)))
            p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength)
            p3 = p2.add(vWidth)
            p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose)
            step = Part.Face(Part.makePolygon([p1,p2,p3,p4,p1]))
            if obj.TreadThickness.Value:
                step = step.extrude(Vector(0,0,abs(obj.TreadThickness.Value)))
                self.steps.append(step)
            else:
                self.pseudosteps.append(step)

        # structure
        lProfile = []
        struct = None
        if obj.Structure == "Massive":
            if obj.StructureThickness.Value:
                for i in range(numberofsteps-1):
                    if not lProfile:
                        lProfile.append(vBase)
                    last = lProfile[-1]
                    if len(lProfile) == 1:
                        last = last.add(Vector(0,0,-abs(obj.TreadThickness.Value)))
                    lProfile.append(last.add(vHeight))
                    lProfile.append(lProfile[-1].add(vLength))
                resHeight1 = obj.StructureThickness.Value/math.cos(a)
                lProfile.append(lProfile[-1].add(Vector(0,0,-resHeight1)))
                resHeight2 = ((numberofsteps-1)*vHeight.Length)-(resHeight1+obj.TreadThickness.Value)
                resLength = (vLength.Length/vHeight.Length)*resHeight2
                h = DraftVecUtils.scaleTo(vLength,-resLength)
                lProfile.append(lProfile[-1].add(Vector(h.x,h.y,-resHeight2)))
                lProfile.append(vBase)
                #print lProfile
                pol = Part.makePolygon(lProfile)
                struct = Part.Face(pol)
                evec = vWidth
                if obj.StructureOffset.Value:
                    mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    struct.translate(mvec)
                    evec = DraftVecUtils.scaleTo(evec,evec.Length-(2*mvec.Length))
                struct = struct.extrude(evec)
        elif obj.Structure in ["One stringer","Two stringers"]:
            if obj.StringerWidth.Value and obj.StructureThickness.Value:
                hyp = math.sqrt(vHeight.Length**2 + vLength.Length**2)
                l1 = Vector(vLength).multiply(numberofsteps-1)
                h1 = Vector(vHeight).multiply(numberofsteps-1).add(Vector(0,0,-abs(obj.TreadThickness.Value)))
                p1 = vBase.add(l1).add(h1)
                p1 = self.align(p1,obj.Align,vWidth)
                lProfile.append(p1)
                h2 = (obj.StructureThickness.Value/vLength.Length)*hyp
                lProfile.append(lProfile[-1].add(Vector(0,0,-abs(h2))))
                h3 = lProfile[-1].z-vBase.z
                l3 = (h3/vHeight.Length)*vLength.Length
                v3 = DraftVecUtils.scaleTo(vLength,-l3)
                lProfile.append(lProfile[-1].add(Vector(0,0,-abs(h3))).add(v3))
                l4 = (obj.StructureThickness.Value/vHeight.Length)*hyp
                v4 = DraftVecUtils.scaleTo(vLength,-l4)
                lProfile.append(lProfile[-1].add(v4))
                lProfile.append(lProfile[0])
                #print lProfile
                pol = Part.makePolygon(lProfile)
                pol = Part.Face(pol)
                evec = DraftVecUtils.scaleTo(vWidth,obj.StringerWidth.Value)
                if obj.Structure == "One stringer":
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    else:
                        mvec = DraftVecUtils.scaleTo(vWidth,(vWidth.Length/2)-obj.StringerWidth.Value/2)
                    pol.translate(mvec)
                    struct = pol.extrude(evec)
                elif obj.Structure == "Two stringers":
                    pol2 = pol.copy()
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                        pol.translate(mvec)
                        mvec = vWidth.add(mvec.negative())
                        pol2.translate(mvec)
                    else:
                        pol2.translate(vWidth)
                    s1 = pol.extrude(evec)
                    s2 = pol2.extrude(evec.negative())
                    struct = Part.makeCompound([s1,s2])
        if struct:
            self.structures.append(struct)
Ejemplo n.º 32
0
    def makeStraightLanding(self,obj,edge,numberofsteps=None):

        "builds a landing from a straight edge"

        # general data
        if not numberofsteps:
            numberofsteps = obj.NumberOfSteps
        import Part,DraftGeomUtils
        v = DraftGeomUtils.vec(edge)
        vLength = Vector(v.x,v.y,0)
        vWidth = vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0,0,1)),obj.Width.Value)
        vBase = edge.Vertexes[0].Point
        vNose = DraftVecUtils.scaleTo(vLength,-abs(obj.Nosing.Value))
        h = obj.Height.Value
        l = obj.Length.Value
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                l = obj.Base.Shape.Length
                if obj.Base.Shape.BoundBox.ZLength:
                    h = obj.Base.Shape.BoundBox.ZLength
        fLength = float(l-obj.Width.Value)/(numberofsteps-2)
        fHeight = float(h)/numberofsteps
        a = math.atan(fHeight/fLength)
        print "landing data:",fLength,":",fHeight

        # step
        p1 = self.align(vBase,obj.Align,vWidth)
        p1 = p1.add(vNose).add(Vector(0,0,-abs(obj.TreadThickness.Value)))
        p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength)
        p3 = p2.add(vWidth)
        p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose)
        step = Part.Face(Part.makePolygon([p1,p2,p3,p4,p1]))
        if obj.TreadThickness.Value:
            step = step.extrude(Vector(0,0,abs(obj.TreadThickness.Value)))
            self.steps.append(step)
        else:
            self.pseudosteps.append(step)

        # structure
        lProfile = []
        struct = None
        p7 = None
        p1 = p1.add(DraftVecUtils.neg(vNose))
        p2 = p1.add(Vector(0,0,-fHeight)).add(Vector(0,0,-obj.StructureThickness.Value/math.cos(a)))
        resheight = p1.sub(p2).Length - obj.StructureThickness.Value
        reslength = resheight / math.tan(a)
        p3 = p2.add(DraftVecUtils.scaleTo(vLength,reslength)).add(Vector(0,0,resheight))
        p6 = p1.add(vLength)
        if obj.TreadThickness.Value:
            p7 = p6.add(Vector(0,0,obj.TreadThickness.Value))

        reslength = fLength + (obj.StructureThickness.Value/math.sin(a)-(fHeight-obj.TreadThickness.Value)/math.tan(a))
        if p7:
            p5 = p7.add(DraftVecUtils.scaleTo(vLength,reslength))
        else:
            p5 = p6.add(DraftVecUtils.scaleTo(vLength,reslength))
        resheight = obj.StructureThickness.Value + obj.TreadThickness.Value
        reslength = resheight/math.tan(a)
        p4 = p5.add(DraftVecUtils.scaleTo(vLength,-reslength)).add(Vector(0,0,-resheight))
        if obj.Structure == "Massive":
            if obj.StructureThickness.Value:
                if p7:
                    struct = Part.Face(Part.makePolygon([p1,p2,p3,p4,p5,p7,p6,p1]))
                else:
                    struct = Part.Face(Part.makePolygon([p1,p2,p3,p4,p5,p6,p1]))
                evec = vWidth
                if obj.StructureOffset.Value:
                    mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    struct.translate(mvec)
                    evec = DraftVecUtils.scaleTo(evec,evec.Length-(2*mvec.Length))
                struct = struct.extrude(evec)
        elif obj.Structure in ["One stringer","Two stringers"]:
            if obj.StringerWidth.Value and obj.StructureThickness.Value:
                p1b = p1.add(Vector(0,0,-fHeight))
                reslength = fHeight/math.tan(a)
                p1c = p1.add(DraftVecUtils.scaleTo(vLength,reslength))
                p5b = None
                p5c = None
                if obj.TreadThickness.Value:
                    reslength = obj.StructureThickness.Value/math.sin(a)
                    p5b = p5.add(DraftVecUtils.scaleTo(vLength,-reslength))
                    reslength = obj.TreadThickness.Value/math.tan(a)
                    p5c = p5b.add(DraftVecUtils.scaleTo(vLength,-reslength)).add(Vector(0,0,-obj.TreadThickness.Value))
                    pol = Part.Face(Part.makePolygon([p1c,p1b,p2,p3,p4,p5,p5b,p5c,p1c]))
                else:
                    pol = Part.Face(Part.makePolygon([p1c,p1b,p2,p3,p4,p5,p1c]))
                evec = DraftVecUtils.scaleTo(vWidth,obj.StringerWidth.Value)
                if obj.Structure == "One stringer":
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                    else:
                        mvec = DraftVecUtils.scaleTo(vWidth,(vWidth.Length/2)-obj.StringerWidth.Value/2)
                    pol.translate(mvec)
                    struct = pol.extrude(evec)
                elif obj.Structure == "Two stringers":
                    pol2 = pol.copy()
                    if obj.StructureOffset.Value:
                        mvec = DraftVecUtils.scaleTo(vWidth,obj.StructureOffset.Value)
                        pol.translate(mvec)
                        mvec = vWidth.add(mvec.negative())
                        pol2.translate(mvec)
                    else:
                        pol2.translate(vWidth)
                    s1 = pol.extrude(evec)
                    s2 = pol2.extrude(evec.negative())
                    struct = Part.makeCompound([s1,s2])
        if struct:
            self.structures.append(struct)
Ejemplo n.º 33
0
    def __init__(self,
                 size,
                 length,
                 shaft_l,
                 circle_r,
                 circle_h,
                 name="nemamotor",
                 chmf=1,
                 rshaft_l=0,
                 bolt_depth=3,
                 bolt_out=2,
                 container=1,
                 normal=VZ,
                 pos=V0):

        doc = FreeCAD.ActiveDocument
        self.base_place = (0, 0, 0)
        self.size = size
        self.width = kcomp.NEMA_W[size]
        self.length = length
        self.shaft_l = shaft_l
        self.circle_r = circle_r
        self.circle_h = circle_h
        self.chmf = chmf
        self.rshaft_l = rshaft_l
        self.bolt_depth = bolt_depth
        self.bolt_out = bolt_out
        self.container = container
        nnormal = DraftVecUtils.scaleTo(normal, 1)
        self.normal = nnormal
        self.pos = pos
        nemabolt_d = kcomp.NEMA_BOLT_D[size]
        self.nemabolt_d = nemabolt_d
        mtol = kcomp.TOL - 0.1

        lnormal = DraftVecUtils.scaleTo(nnormal, length)
        neg_lnormal = DraftVecUtils.neg(lnormal)

        # motor shape
        v1 = FreeCAD.Vector(self.width / 2. - chmf, self.width / 2., 0)
        v2 = FreeCAD.Vector(self.width / 2., self.width / 2. - chmf, 0)
        motorwire = fcfun.wire_sim_xy([v1, v2])
        # motor wire normal is VZ
        # DraftVecUtils doesnt work as well
        # rot = DraftVecUtils.getRotation(VZ, nnormal)
        # the order matter VZ, nnormal. It seems it doent matter VZ or VZN
        # this is valid:
        #rot = DraftGeomUtils.getRotation(VZ,nnormal)
        #print rot
        rot = FreeCAD.Rotation(VZ, nnormal)
        print rot
        motorwire.Placement.Rotation = rot
        motorwire.Placement.Base = pos
        motorface = Part.Face(motorwire)
        shp_motorbox = motorface.extrude(neg_lnormal)
        # shaft shape
        if rshaft_l == 0:  # no rear shaft
            shp_shaft = fcfun.shp_cyl(r=kcomp.NEMA_SHAFT_D[size] / 2.,
                                      h=shaft_l,
                                      normal=nnormal,
                                      pos=pos)
        else:
            rshaft_posend = DraftVecUtils.scaleTo(neg_lnormal,
                                                  rshaft_l + length)
            shp_shaft = fcfun.shp_cyl(r=kcomp.NEMA_SHAFT_D[size] / 2.,
                                      h=shaft_l + rshaft_l + length,
                                      normal=nnormal,
                                      pos=pos + rshaft_posend)

        shp_motorshaft = shp_motorbox.fuse(shp_shaft)
        # Bolt holes
        # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        # There is something wrong with the position of these bolts
        #        bhole00_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size]/2,
        #                                     -kcomp.NEMA_BOLT_SEP[size]/2,
        #                                     -bolt_depth) + pos
        #        bhole01_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size]/2,
        #                                      kcomp.NEMA_BOLT_SEP[size]/2,
        #                                     -bolt_depth) + pos
        #        bhole10_pos = FreeCAD.Vector( kcomp.NEMA_BOLT_SEP[size]/2,
        #                                     -kcomp.NEMA_BOLT_SEP[size]/2,
        #                                     -bolt_depth) + pos
        #        bhole11_pos = FreeCAD.Vector( kcomp.NEMA_BOLT_SEP[size]/2,
        #                                      kcomp.NEMA_BOLT_SEP[size]/2,
        #                                     -bolt_depth) + pos
        #        bhole00_posrot = DraftVecUtils.rotate(bhole00_pos, rot.Angle, rot.Axis)
        #        bhole01_posrot = DraftVecUtils.rotate(bhole01_pos, rot.Angle, rot.Axis)
        #        bhole10_posrot = DraftVecUtils.rotate(bhole10_pos, rot.Angle, rot.Axis)
        #        bhole11_posrot = DraftVecUtils.rotate(bhole11_pos, rot.Angle, rot.Axis)
        #        shp_bolt00 = fcfun.shp_cyl (
        #                                   r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
        #                                   h=bolt_depth + shaft_l,
        #                                   normal = nnormal,
        #                                   pos= bhole00_posrot)
        #        shp_bolt01 = fcfun.shp_cyl (
        #                                   r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
        #                                   h=bolt_depth + shaft_l,
        #                                   normal = nnormal,
        #                                   pos= bhole01_posrot)
        #        shp_bolt10 = fcfun.shp_cyl (
        #                                   r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
        #                                   h=bolt_depth + shaft_l,
        #                                   normal = nnormal,
        #                                   pos= bhole10_posrot)
        #        shp_bolt11 = fcfun.shp_cyl (
        #                                   r=kcomp.NEMA_BOLT_D[size]/2.+kcomp.TOL/2.,
        #                                   h=bolt_depth + shaft_l,
        #                                   normal = nnormal,
        #                                   pos= bhole11_posrot)
        #        shp_bolts = shp_bolt00.multiFuse([shp_bolt01, shp_bolt10, shp_bolt11])

        # list of shapes to make a fusion of the container
        shp_contfuselist = []
        #        shp_contfuselist.append(shp_bolts)

        b2hole00_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size] / 2,
                                      -kcomp.NEMA_BOLT_SEP[size] / 2,
                                      -bolt_depth)
        b2hole01_pos = FreeCAD.Vector(-kcomp.NEMA_BOLT_SEP[size] / 2,
                                      kcomp.NEMA_BOLT_SEP[size] / 2,
                                      -bolt_depth)
        b2hole10_pos = FreeCAD.Vector(kcomp.NEMA_BOLT_SEP[size] / 2,
                                      -kcomp.NEMA_BOLT_SEP[size] / 2,
                                      -bolt_depth)
        b2hole11_pos = FreeCAD.Vector(kcomp.NEMA_BOLT_SEP[size] / 2,
                                      kcomp.NEMA_BOLT_SEP[size] / 2,
                                      -bolt_depth)

        b2hole00 = addBolt(r_shank=nemabolt_d / 2. + mtol / 2.,
                           l_bolt=bolt_out + bolt_depth,
                           r_head=kcomp.D912_HEAD_D[nemabolt_d] / 2. +
                           mtol / 2.,
                           l_head=kcomp.D912_HEAD_L[nemabolt_d] + mtol,
                           hex_head=0,
                           extra=1,
                           support=1,
                           headdown=0,
                           name="b2hole00")

        b2hole01 = Draft.clone(b2hole00)
        b2hole01.Label = "b2hole01"
        b2hole10 = Draft.clone(b2hole00)
        b2hole10.Label = "b2hole10"
        b2hole11 = Draft.clone(b2hole00)
        b2hole11.Label = "b2hole11"

        b2hole00.ViewObject.Visibility = False
        b2hole01.ViewObject.Visibility = False
        b2hole10.ViewObject.Visibility = False
        b2hole11.ViewObject.Visibility = False

        b2hole00.Placement.Base = b2hole00_pos
        b2hole01.Placement.Base = b2hole01_pos
        b2hole10.Placement.Base = b2hole10_pos
        b2hole11.Placement.Base = b2hole11_pos

        # it doesnt work if dont recompute here! probably the clones
        doc.recompute()

        b2holes_list = [b2hole00, b2hole01, b2hole10, b2hole11]
        # not an efficient way, either use shapes or fco, but not both
        shp_b2holes = b2hole00.Shape.multiFuse(
            [b2hole01.Shape, b2hole10.Shape, b2hole11.Shape])
        #Part.show(shp_b2holes)

        b2holes = doc.addObject("Part::MultiFuse", "b2holes")
        b2holes.Shapes = b2holes_list
        b2holes.ViewObject.Visibility = False

        shp_b2holes.Placement.Base = pos
        shp_b2holes.Placement.Rotation = rot
        shp_contfuselist.append(shp_b2holes)

        # Circle on the base of the shaft
        if circle_r == 0:
            calcircle_r = kcomp.NEMA_BOLT_SEP[size] / 2.
        else:
            calcircle_r = circle_r
        if circle_h != 0:
            shp_circle = fcfun.shp_cyl(
                r=calcircle_r,
                h=circle_h + 1,  #supperposition for union
                normal=nnormal,
                #supperposition for union
                pos=pos - nnormal)
            # fmotor: fused motor
            shp_fmotor = shp_motorshaft.fuse(shp_circle)
        else:
            shp_fmotor = shp_motorshaft

        #fmotor = doc.addObject("Part::Feature", "fmotor")
        #fmotor.Shape = shp_fmotor

        #shp_motor = shp_fmotor.cut(shp_bolts)
        shp_motor = shp_fmotor.cut(shp_b2holes)
        #Part.show(shp_bolts)

        # container
        if container == 1:
            # 2*TOL to make sure it fits
            v1 = FreeCAD.Vector(self.width / 2. - chmf / 2. + 2 * kcomp.TOL,
                                self.width / 2. + 2 * kcomp.TOL, 0)
            v2 = FreeCAD.Vector(self.width / 2. + 2 * kcomp.TOL,
                                self.width / 2. - chmf / 2. + 2 * kcomp.TOL, 0)
            cont_motorwire = fcfun.wire_sim_xy([v1, v2])
            cont_motorwire.Placement.Rotation = rot
            cont_motorwire.Placement.Base = pos
            cont_motorface = Part.Face(cont_motorwire)
            shp_contmotor_box = cont_motorface.extrude(neg_lnormal)

            # the container is much wider than the shaft

            if rshaft_l == 0:  # no rear shaft
                shp_contshaft = fcfun.shp_cyl(r=calcircle_r + kcomp.TOL,
                                              h=shaft_l + 1,
                                              normal=nnormal,
                                              pos=pos - nnormal)
            else:
                shp_contshaft = fcfun.shp_cyl(r=calcircle_r + kcomp.TOL,
                                              h=shaft_l + rshaft_l + length,
                                              normal=nnormal,
                                              pos=pos + rshaft_posend)
            shp_contfuselist.append(shp_contshaft)
            shp_contmotor = shp_contmotor_box.multiFuse(shp_contfuselist)
        else:
            shp_contmotor = shp_motor  # we put the same shape

        doc.recompute()

        #fco_motor = doc.addObject("Part::Cut", name)
        #fco_motor.Base = fmotor
        #fco_motor.Tool = b2holes
        fco_motor = doc.addObject("Part::Feature", name)
        fco_motor.Shape = shp_motor

        self.fco = fco_motor
        self.shp_cont = shp_contmotor
        #Part.show(shp_contmotor)

        doc.recompute()
Ejemplo n.º 34
0
    def execute(self, obj):

        if self.clone(obj):
            return
        if not obj.Base and ((not obj.Shape) or (not obj.Shape.isNull())):
            # let pass without error if we already have a shape
            return
        if not obj.Base:
            FreeCAD.Console.PrintError(
                "No Base, return without a rebar shape for {}.\n".format(
                    obj.Name))
            return
        if not hasattr(obj.Base, "Shape") or (
                not obj.Base.Shape) or obj.Base.Shape.isNull():
            FreeCAD.Console.PrintError(
                "No Shape in Base, return without a rebar shape for {}.\n".
                format(obj.Name))
            return
        if obj.Base.Shape.Faces:
            FreeCAD.Console.PrintError(
                "Faces in Shape of Base, return without a rebar shape for {}.\n"
                .format(obj.Name))
            return
        if not obj.Base.Shape.Edges:
            FreeCAD.Console.PrintError(
                "No Edges in Shape of Base, return without a rebar shape for {}.\n"
                .format(obj.Name))
            return
        if not obj.Diameter.Value:
            FreeCAD.Console.PrintError(
                "No Diameter Value, return without a rebar shape for {}.\n".
                format(obj.Name))
            return
        if not obj.Amount:
            FreeCAD.Console.PrintError(
                "No Amount, return without a rebar shape for {}.\n".format(
                    obj.Name))
            return
        father = obj.Host
        fathershape = None
        if not father:
            # support for old-style rebars
            if obj.InList:
                if hasattr(obj.InList[0], "Armatures"):
                    if obj in obj.InList[0].Armatures:
                        father = obj.InList[0]
        if father:
            if hasattr(father, 'Shape'):
                fathershape = father.Shape

        import Part
        # corner cases:
        #    compound from more Wires
        #    compound without Wires but with multiple Edges
        # Does they make sense? If yes handle them.
        # Does it makes sense to handle Shapes with Faces or even Solids?
        if not obj.Base.Shape.Wires and len(obj.Base.Shape.Edges) == 1:
            wire = Part.Wire(obj.Base.Shape.Edges[0])
        else:
            wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print(obj.Rounding)
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                from DraftGeomUtils import filletWire
                wire = filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
        if fathershape:
            size = (ArchCommands.projectToVector(fathershape.copy(),
                                                 axis)).Length
        else:
            size = 1
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
                if fathershape:
                    size = (ArchCommands.projectToVector(
                        fathershape.copy(), axis)).Length
                else:
                    size = 1
        if hasattr(obj, "Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        spacinglist = None
        if hasattr(obj, "CustomSpacing"):
            if obj.CustomSpacing:
                spacinglist = strprocessOfCustomSpacing(obj.CustomSpacing)
                influenceArea = sum(
                    spacinglist) - spacinglist[0] / 2 - spacinglist[-1] / 2
        # Drop this check to solve issue as discussed here: https://github.com/FreeCAD/FreeCAD/pull/2550
        # if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
        #        return
        # all tests ok!
        if hasattr(obj, "Length"):
            length = getLengthOfRebar(obj)
            if length:
                obj.Length = length
        pl = obj.Placement
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
            basewire = wire.copy()
        except Part.OCCError:
            print("Arch: error sweeping rebar profile along the base sketch")
            return
        # building final shape
        shapes = []
        placementlist = []
        self.wires = []
        rot = FreeCAD.Rotation()
        if obj.Amount == 1:
            if hasattr(obj, "RebarShape"):
                barplacement = CalculatePlacement(
                    obj.Amount, 1, obj.Diameter.Value, size, axis, rot,
                    obj.OffsetStart.Value, obj.OffsetEnd.Value, obj.RebarShape)
            else:
                barplacement = CalculatePlacement(obj.Amount, 1,
                                                  obj.Diameter.Value, size,
                                                  axis, rot,
                                                  obj.OffsetStart.Value,
                                                  obj.OffsetEnd.Value)
            placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        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)
            for i in range(obj.Amount):
                if hasattr(obj, "RebarShape"):
                    barplacement = CalculatePlacement(obj.Amount, i + 1,
                                                      obj.Diameter.Value, size,
                                                      axis, rot,
                                                      obj.OffsetStart.Value,
                                                      obj.OffsetEnd.Value,
                                                      obj.RebarShape)
                else:
                    barplacement = CalculatePlacement(obj.Amount, i + 1,
                                                      obj.Diameter.Value, size,
                                                      axis, rot,
                                                      obj.OffsetStart.Value,
                                                      obj.OffsetEnd.Value)
                placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        # Calculate placement of bars from custom spacing.
        if spacinglist:
            placementlist[:] = []
            if hasattr(obj, "RebarShape") and obj.RebarShape == "Stirrup":
                reqInfluenceArea = size - (obj.OffsetStart.Value +
                                           obj.OffsetEnd.Value +
                                           obj.Diameter.Value)
            else:
                reqInfluenceArea = size - (obj.OffsetStart.Value +
                                           obj.OffsetEnd.Value)
            # Avoid unnecessary checks to pass like. For eg.: when we have values
            # like influenceArea is 100.00001 and reqInflueneArea is 100
            if round(influenceArea) > round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning(
                    "Influence area of rebars is greater than " +
                    str(reqInfluenceArea) + ".\n")
            elif round(influenceArea) < round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning(
                    "Last span is greater that end offset.\n")
            for i in range(len(spacinglist)):
                if i == 0:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
                else:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, i + 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
            obj.Amount = len(spacinglist)
            obj.Spacing = 0
        obj.PlacementList = placementlist
        for i in range(len(obj.PlacementList)):
            if i == 0:
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                basewire.Placement = obj.PlacementList[i]
                self.wires.append(basewire)
            else:
                bar = bar.copy()
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                w = basewire.copy()
                w.Placement = obj.PlacementList[i]
                self.wires.append(w)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
        obj.TotalLength = obj.Length * len(obj.PlacementList)
Ejemplo n.º 35
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
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.Host
        fathershape = None
        if not father:
            # support for old-style rebars
            if obj.InList:
                if hasattr(obj.InList[0], "Armatures"):
                    if obj in obj.InList[0].Armatures:
                        father = obj.InList[0]
        if father:
            if father.isDerivedFrom("Part::Feature"):
                fathershape = father.Shape

        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print(obj.Rounding)
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
        if fathershape:
            size = (ArchCommands.projectToVector(fathershape.copy(),
                                                 axis)).Length
        else:
            size = 1
        if hasattr(obj, "Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
                if fathershape:
                    size = (ArchCommands.projectToVector(
                        fathershape.copy(), axis)).Length
                else:
                    size = 1
        if hasattr(obj, "Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        #print(axis)
        #print(size)
        spacinglist = None
        if hasattr(obj, "CustomSpacing"):
            if obj.CustomSpacing:
                spacinglist = strprocessOfCustomSpacing(obj.CustomSpacing)
                influenceArea = sum(
                    spacinglist) - spacinglist[0] / 2 - spacinglist[-1] / 2
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return
        # all tests ok!
        if hasattr(obj, "Length"):
            length = getLengthOfRebar(obj)
            if length:
                obj.Length = length
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
            basewire = wire.copy()
        except Part.OCCError:
            print("Arch: error sweeping rebar profile along the base sketch")
            return
        # building final shape
        shapes = []
        placementlist = []
        self.wires = []
        if father:
            rot = father.Placement.Rotation
        else:
            rot = FreeCAD.Rotation()
        if obj.Amount == 1:
            barplacement = CalculatePlacement(obj.Amount, 1, size, axis, rot,
                                              obj.OffsetStart.Value,
                                              obj.OffsetEnd.Value)
            placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            interval = interval / (obj.Amount - 1)
            for i in range(obj.Amount):
                barplacement = CalculatePlacement(obj.Amount, i + 1, size,
                                                  axis, rot,
                                                  obj.OffsetStart.Value,
                                                  obj.OffsetEnd.Value)
                placementlist.append(barplacement)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        # Calculate placement of bars from custom spacing.
        if spacinglist:
            placementlist[:] = []
            reqInfluenceArea = size - (obj.OffsetStart.Value +
                                       obj.OffsetEnd.Value)
            # Avoid unnecessary checks to pass like. For eg.: when we have values
            # like influenceArea is 100.00001 and reqInflueneArea is 100
            if round(influenceArea) > round(reqInfluenceArea):
                return FreeCAD.Console.PrintError(
                    "Influence area of rebars is greater than " +
                    str(reqInfluenceArea) + ".\n")
            elif round(influenceArea) < round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning(
                    "Last span is greater that end offset.\n")
            for i in range(len(spacinglist)):
                if i == 0:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
                else:
                    barplacement = CustomSpacingPlacement(
                        spacinglist, i + 1, axis, father.Placement.Rotation,
                        obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
            obj.Amount = len(spacinglist)
            obj.Spacing = 0
        obj.PlacementList = placementlist
        for i in range(len(obj.PlacementList)):
            if i == 0:
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                basewire.Placement = obj.PlacementList[i]
                self.wires.append(basewire)
            else:
                bar = bar.copy()
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                w = basewire.copy()
                w.Placement = obj.PlacementList[i]
                self.wires.append(w)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
        obj.TotalLength = obj.Length * len(obj.PlacementList)
Ejemplo n.º 36
0
    def updateData(self, obj, prop):
        """called when the base object is changed"""
        import DraftGui
        if prop in ["Start", "End", "Dimline", "Direction"]:

            if obj.Start == obj.End:
                return

            if not hasattr(self, "node"):
                return

            import Part, DraftGeomUtils
            from pivy import coin

            # calculate the 4 points
            self.p1 = obj.Start
            self.p4 = obj.End
            base = None
            if hasattr(obj, "Direction"):
                if not DraftVecUtils.isNull(obj.Direction):
                    v2 = self.p1.sub(obj.Dimline)
                    v3 = self.p4.sub(obj.Dimline)
                    v2 = DraftVecUtils.project(v2, obj.Direction)
                    v3 = DraftVecUtils.project(v3, obj.Direction)
                    self.p2 = obj.Dimline.add(v2)
                    self.p3 = obj.Dimline.add(v3)
                    if DraftVecUtils.equals(self.p2, self.p3):
                        base = None
                        proj = None
                    else:
                        base = Part.LineSegment(self.p2, self.p3).toShape()
                        proj = DraftGeomUtils.findDistance(self.p1, base)
                        if proj:
                            proj = proj.negative()
            if not base:
                if DraftVecUtils.equals(self.p1, self.p4):
                    base = None
                    proj = None
                else:
                    base = Part.LineSegment(self.p1, self.p4).toShape()
                    proj = DraftGeomUtils.findDistance(obj.Dimline, base)
                if proj:
                    self.p2 = self.p1.add(proj.negative())
                    self.p3 = self.p4.add(proj.negative())
                else:
                    self.p2 = self.p1
                    self.p3 = self.p4
            if proj:
                if hasattr(obj.ViewObject, "ExtLines") and hasattr(
                        obj.ViewObject, "ScaleMultiplier"):
                    dmax = obj.ViewObject.ExtLines.Value * obj.ViewObject.ScaleMultiplier
                    if dmax and (proj.Length > dmax):
                        if (dmax > 0):
                            self.p1 = self.p2.add(
                                DraftVecUtils.scaleTo(proj, dmax))
                            self.p4 = self.p3.add(
                                DraftVecUtils.scaleTo(proj, dmax))
                        else:
                            rest = proj.Length + dmax
                            self.p1 = self.p2.add(
                                DraftVecUtils.scaleTo(proj, rest))
                            self.p4 = self.p3.add(
                                DraftVecUtils.scaleTo(proj, rest))
            else:
                proj = (self.p3.sub(self.p2)).cross(App.Vector(0, 0, 1))

            # calculate the arrows positions
            self.trans1.translation.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.coord1.point.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.trans2.translation.setValue((self.p3.x, self.p3.y, self.p3.z))
            self.coord2.point.setValue((self.p3.x, self.p3.y, self.p3.z))

            # calculate dimension and extension lines overshoots positions
            self.transDimOvershoot1.translation.setValue(
                (self.p2.x, self.p2.y, self.p2.z))
            self.transDimOvershoot2.translation.setValue(
                (self.p3.x, self.p3.y, self.p3.z))
            self.transExtOvershoot1.translation.setValue(
                (self.p2.x, self.p2.y, self.p2.z))
            self.transExtOvershoot2.translation.setValue(
                (self.p3.x, self.p3.y, self.p3.z))

            # calculate the text position and orientation
            if hasattr(obj, "Normal"):
                if DraftVecUtils.isNull(obj.Normal):
                    if proj:
                        norm = (self.p3.sub(self.p2).cross(proj)).negative()
                    else:
                        norm = App.Vector(0, 0, 1)
                else:
                    norm = App.Vector(obj.Normal)
            else:
                if proj:
                    norm = (self.p3.sub(self.p2).cross(proj)).negative()
                else:
                    norm = App.Vector(0, 0, 1)
            if not DraftVecUtils.isNull(norm):
                norm.normalize()
            u = self.p3.sub(self.p2)
            u.normalize()
            v1 = norm.cross(u)
            rot1 = App.Placement(DraftVecUtils.getPlaneRotation(
                u, v1, norm)).Rotation.Q
            self.transDimOvershoot1.rotation.setValue(
                (rot1[0], rot1[1], rot1[2], rot1[3]))
            self.transDimOvershoot2.rotation.setValue(
                (rot1[0], rot1[1], rot1[2], rot1[3]))
            if hasattr(obj.ViewObject, "FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u = u.negative()
            v2 = norm.cross(u)
            rot2 = App.Placement(DraftVecUtils.getPlaneRotation(
                u, v2, norm)).Rotation.Q
            self.trans1.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3]))
            self.trans2.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3]))
            if self.p1 != self.p2:
                u3 = self.p1.sub(self.p2)
                u3.normalize()
                v3 = norm.cross(u3)
                rot3 = App.Placement(
                    DraftVecUtils.getPlaneRotation(u3, v3, norm)).Rotation.Q
                self.transExtOvershoot1.rotation.setValue(
                    (rot3[0], rot3[1], rot3[2], rot3[3]))
                self.transExtOvershoot2.rotation.setValue(
                    (rot3[0], rot3[1], rot3[2], rot3[3]))
            if hasattr(obj.ViewObject, "TextSpacing") and hasattr(
                    obj.ViewObject, "ScaleMultiplier"):
                ts = obj.ViewObject.TextSpacing.Value * obj.ViewObject.ScaleMultiplier
                offset = DraftVecUtils.scaleTo(v1, ts)
            else:
                offset = DraftVecUtils.scaleTo(v1, 0.05)
            rott = rot1
            if hasattr(obj.ViewObject, "FlipText"):
                if obj.ViewObject.FlipText:
                    rott = App.Rotation(*rott).multiply(App.Rotation(
                        norm, 180)).Q
                    offset = offset.negative()
            # setting text
            try:
                m = obj.ViewObject.DisplayMode
            except:  # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
                m = ["2D", "3D"][utils.get_param("dimstyle", 0)]
            if m == "3D":
                offset = offset.negative()
            self.tbase = (self.p2.add(
                (self.p3.sub(self.p2).multiply(0.5)))).add(offset)
            if hasattr(obj.ViewObject, "TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition
            self.textpos.translation.setValue(
                [self.tbase.x, self.tbase.y, self.tbase.z])
            self.textpos.rotation = coin.SbRotation(rott[0], rott[1], rott[2],
                                                    rott[3])
            su = True
            if hasattr(obj.ViewObject, "ShowUnit"):
                su = obj.ViewObject.ShowUnit
            # set text value
            l = self.p3.sub(self.p2).Length
            unit = None
            if hasattr(obj.ViewObject, "UnitOverride"):
                unit = obj.ViewObject.UnitOverride
            # special representation if "Building US" scheme
            if App.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt(
                    "UserSchema", 0) == 5:
                s = App.Units.Quantity(l, App.Units.Length).UserString
                self.string = s.replace("' ", "'- ")
                self.string = s.replace("+", " ")
            elif hasattr(obj.ViewObject, "Decimals"):
                self.string = DraftGui.displayExternal(l,
                                                       obj.ViewObject.Decimals,
                                                       'Length', su, unit)
            else:
                self.string = DraftGui.displayExternal(l, None, 'Length', su,
                                                       unit)
            if hasattr(obj.ViewObject, "Override"):
                if obj.ViewObject.Override:
                    self.string = obj.ViewObject.Override.replace("$dim",\
                            self.string)
            self.text.string = self.text3d.string = utils.string_encode_coin(
                self.string)

            # set the lines
            if m == "3D":
                # calculate the spacing of the text
                textsize = (len(self.string) *
                            obj.ViewObject.FontSize.Value) / 4.0
                spacing = ((self.p3.sub(self.p2)).Length / 2.0) - textsize
                self.p2a = self.p2.add(
                    DraftVecUtils.scaleTo(self.p3.sub(self.p2), spacing))
                self.p2b = self.p3.add(
                    DraftVecUtils.scaleTo(self.p2.sub(self.p3), spacing))
                self.coords.point.setValues(
                    [[self.p1.x, self.p1.y, self.p1.z],
                     [self.p2.x, self.p2.y, self.p2.z],
                     [self.p2a.x, self.p2a.y, self.p2a.z],
                     [self.p2b.x, self.p2b.y, self.p2b.z],
                     [self.p3.x, self.p3.y, self.p3.z],
                     [self.p4.x, self.p4.y, self.p4.z]])
                #self.line.numVertices.setValues([3,3])
                self.line.coordIndex.setValues(0, 7, (0, 1, 2, -1, 3, 4, 5))
            else:
                self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z],
                                             [self.p2.x, self.p2.y, self.p2.z],
                                             [self.p3.x, self.p3.y, self.p3.z],
                                             [self.p4.x, self.p4.y,
                                              self.p4.z]])
                #self.line.numVertices.setValue(4)
                self.line.coordIndex.setValues(0, 4, (0, 1, 2, 3))
Ejemplo n.º 37
0
def offsetWire(wire, dvec, bind=False, occ=False,
               widthList=None, offsetMode=None, alignList=[],
               normal=None, basewireOffset=0):
    """Offset the wire along the given vector.

    Parameters
    ----------
    wire as a list of edges (use the list directly),
    or previously as a wire or a face (Draft Wire with MakeFace True
    or False supported).

    The vector will be applied at the first vertex of the wire. If bind
    is True (and the shape is open), the original wire and the offsetted one
    are bound by 2 edges, forming a face.

    If widthList is provided (values only, not lengths - i.e. no unit),
    each value will be used to offset each corresponding edge in the wire.

    The 1st value overrides 'dvec' for 1st segment of wire;
    if a value is zero, value of 'widthList[0]' will follow;
    if widthList[0]' == 0, but dvec still provided, dvec will be followed

    offsetMode="BasewireMode" or None

    If alignList is provided,
    each value will be used to offset each corresponding edge
    in the wire with corresponding index.

    'basewireOffset' corresponds to 'offset' in ArchWall which offset
    the basewire before creating the wall outline

    OffsetWire() is now aware of width and align per edge
    Primarily for use with ArchWall based on Sketch object

    To Do
    -----
    `dvec` vector to offset is now derived (and can be ignored)
    in this function if widthList and alignList are provided
    - 'dvec' to be obsolete in future?
    """
    if isinstance(wire, Part.Wire) or isinstance(wire, Part.Face):
        # Seems has repeatedly sortEdges, remark out here
        # edges = Part.__sortEdges__(wire.Edges)
        edges = wire.Edges
    elif isinstance(wire, list):
        if isinstance(wire[0], Part.Edge):
            edges = wire.copy()
            # How to avoid __sortEdges__ again?
            # Make getNormal directly tackle edges?
            wire = Part.Wire(Part.__sortEdges__(edges))
    else:
        print("Either Part.Wire or Part.Edges should be provided, "
              "returning None")
        return None

    # For sketch with a number of wires, getNormal() may result
    # in different direction for each wire.
    # The 'normal' parameter, if provided e.g. by ArchWall,
    # allows normal over different wires e.g. in a Sketch be consistent
    # (over different calls of this function)
    if normal:
        norm = normal
    else:
        norm = getNormal(wire)  # norm = Vector(0, 0, 1)

    closed = isReallyClosed(wire)
    nedges = []
    if occ:
        length = abs(dvec.Length)
        if not length:
            return None

        if wire.Wires:
            wire = wire.Wires[0]
        else:
            wire = Part.Wire(edges)

        try:
            off = wire.makeOffset(length)
        except Part.OCCError:
            return None
        else:
            return off

    # vec of first edge depends on its geometry
    e = edges[0]

    # Make a copy of alignList - to avoid changes in this function
    # become starting input of next call of this function?
    # https://www.dataquest.io/blog/tutorial-functions-modify-lists-dictionaries-python/
    # alignListC = alignList.copy()  # Only Python 3
    alignListC = list(alignList)  # Python 2 and 3

    # Check the direction / offset of starting edge
    firstDir = None
    try:
        if alignListC[0] == 'Left':
            firstDir = 1
            firstAlign = 'Left'
        elif alignListC[0] == 'Right':
            firstDir = -1
            firstAlign = 'Right'
        elif alignListC[0] == 'Center':
            firstDir = 1
            firstAlign = 'Center'
    except IndexError:
        # Should no longer happen for ArchWall
        # as aligns are 'filled in' by ArchWall
        pass

    # If not provided by alignListC checked above, check the direction
    # of offset in dvec (not 'align').

    # TODO Should check if dvec is provided or not
    # ('legacy/backward-compatible' mode)
    if not firstDir:
        # need to test against Part.Circle, not Part.ArcOfCircle
        if isinstance(e.Curve, Part.Circle):
            v0 = e.Vertexes[0].Point.sub(e.Curve.Center)
        else:
            v0 = vec(e).cross(norm)
        # check against dvec provided for the offset direction
        # would not know if dvec is vector of width (Left/Right Align)
        # or width/2 (Center Align)
        dvec0 = DraftVecUtils.scaleTo(v0, dvec.Length)
        if DraftVecUtils.equals(dvec0, dvec):
            # "Left Offset" (Left Align or 'left offset' in Centre Align)
            firstDir = 1
            firstAlign = 'Left'
            alignListC.append('Left')
        elif DraftVecUtils.equals(dvec0, dvec.negative()):
            # "Right Offset" (Right Align or 'right offset' in Centre Align)
            firstDir = -1
            firstAlign = 'Right'
            alignListC.append('Right')
        else:
            print(" something wrong with firstDir ")
            firstAlign = 'Left'
            alignListC.append('Left')

    for i in range(len(edges)):
        # make a copy so it do not reverse the self.baseWires edges
        # pointed to by _Wall.getExtrusionData()?
        curredge = edges[i].copy()

        # record first edge's Orientation, Dir, Align and set Delta
        if i == 0:
            # TODO Could be edge.Orientation in fact
            # "Forward" or "Reversed"
            firstOrientation = curredge.Vertexes[0].Orientation
            curOrientation = firstOrientation
            curDir = firstDir
            curAlign = firstAlign
            delta = dvec

        # record current edge's Orientation, and set Delta
        if i != 0:  # else:
            # TODO Should also calculate 1st edge direction above
            if isinstance(curredge.Curve, Part.Circle):
                delta = curredge.Vertexes[0].Point.sub(curredge.Curve.Center)
            else:
                delta = vec(curredge).cross(norm)
            # TODO Could be edge.Orientation in fact
            curOrientation = curredge.Vertexes[0].Orientation

        # Consider individual edge width
        if widthList:  # ArchWall should now always provide widthList
            try:
                if widthList[i] > 0:
                    delta = DraftVecUtils.scaleTo(delta, widthList[i])
                elif dvec:
                    delta = DraftVecUtils.scaleTo(delta, dvec.Length)
                else:
                    # just hardcoded default value as ArchWall would provide
                    # if dvec is not provided either
                    delta = DraftVecUtils.scaleTo(delta, 200)
            except Part.OCCError:
                if dvec:
                    delta = DraftVecUtils.scaleTo(delta, dvec.Length)
                else:
                    # just hardcoded default value as ArchWall would provide
                    # if dvec is not provided either
                    delta = DraftVecUtils.scaleTo(delta, 200)
        else:
            delta = DraftVecUtils.scaleTo(delta, dvec.Length)

        # Consider individual edge Align direction
        # - ArchWall should now always provide alignList
        if i == 0:
            if alignListC[0] == 'Center':
                delta = DraftVecUtils.scaleTo(delta, delta.Length/2)
            # No need to do anything for 'Left' and 'Right' as original dvec
            # have set both the direction and amount of offset correct
            # elif alignListC[i] == 'Left':  #elif alignListC[i] == 'Right':
        if i != 0:
            try:
                if alignListC[i] == 'Left':
                    curDir = 1
                    curAlign = 'Left'
                elif alignListC[i] == 'Right':
                    curDir = -1
                    curAlign = 'Right'
                    delta = delta.negative()
                elif alignListC[i] == 'Center':
                    curDir = 1
                    curAlign = 'Center'
                    delta = DraftVecUtils.scaleTo(delta, delta.Length/2)
            except IndexError:
                curDir = firstDir
                curAlign = firstAlign
                if firstAlign == 'Right':
                    delta = delta.negative()
                elif firstAlign == 'Center':
                    delta = DraftVecUtils.scaleTo(delta, delta.Length/2)

        # Consider whether generating the 'offset wire' or the 'base wire'
        if offsetMode is None:
            # Consider if curOrientation and/or curDir match their
            # firstOrientation/firstDir - to determine whether
            # and how to offset the current edge

            # This is a xor
            if (curOrientation == firstOrientation) != (curDir == firstDir):
                if curAlign in ['Left', 'Right']:
                    # ArchWall has an Offset properties for user to offset
                    # the basewire before creating the base profile of wall
                    # (not applicable to 'Center' align)
                    if basewireOffset:
                        delta = DraftVecUtils.scaleTo(delta, basewireOffset)
                        nedge = offset(curredge,delta,trim=True)
                    else:
                        nedge = curredge
                elif curAlign == 'Center':
                    delta = delta.negative()
                    nedge = offset(curredge, delta, trim=True)
            else:
                # if curAlign in ['Left', 'Right']:
                # elif curAlign == 'Center': # Both conditions same result.
                # ArchWall has an Offset properties for user to offset
                # the basewire before creating the base profile of wall
                # (not applicable to 'Center' align)
                if basewireOffset:
                    if curAlign in ['Left', 'Right']:
                        delta = DraftVecUtils.scaleTo(delta,
                                                      delta.Length + basewireOffset)
                    #else: # elif curAlign == 'Center': #pass # no need to add basewireOffset
                nedge = offset(curredge, delta, trim=True)

            # TODO arc always in counter-clockwise directinon
            # ... ( not necessarily 'reversed')
            if curOrientation == "Reversed":
                # need to test against Part.Circle, not Part.ArcOfCircle
                if not isinstance(curredge.Curve, Part.Circle):
                    # if not arc/circle, assume straight line, reverse it
                    nedge = Part.Edge(nedge.Vertexes[1], nedge.Vertexes[0])
                else:
                    # if arc/circle
                    # Part.ArcOfCircle(edge.Curve,
                    #                  edge.FirstParameter, edge.LastParameter,
                    #                  edge.Curve.Axis.z > 0)
                    midParameter = nedge.FirstParameter + (nedge.LastParameter - nedge.FirstParameter)/2
                    midOfArc = nedge.valueAt(midParameter)
                    nedge = Part.ArcOfCircle(nedge.Vertexes[1].Point,
                                             midOfArc,
                                             nedge.Vertexes[0].Point).toShape()
                    # TODO any better solution than to calculate midpoint
                    # of arc to reverse?

        elif offsetMode in ["BasewireMode"]:
            if (not (curOrientation == firstOrientation)
                    != (curDir == firstDir)):
                if curAlign in ['Left', 'Right']:
                    # ArchWall has an Offset properties for user to offset
                    # the basewire before creating the base profile of wall
                    # (not applicable to 'Center' align)
                    if basewireOffset:
                        delta = DraftVecUtils.scaleTo(delta, basewireOffset)
                        nedge = offset(curredge, delta, trim=True)
                    else:
                        nedge = curredge
                elif curAlign == 'Center':
                    delta = delta.negative()
                    nedge = offset(curredge, delta, trim=True)
            else:
                if curAlign in ['Left', 'Right']:
                    # ArchWall has an Offset properties for user to offset
                    # the basewire before creating the base profile of wall
                    # (not applicable to 'Center' align)
                    if basewireOffset:
                        delta = DraftVecUtils.scaleTo(delta,
                                                      delta.Length + basewireOffset)
                    nedge = offset(curredge, delta, trim=True)

                elif curAlign == 'Center':
                    nedge = offset(curredge, delta, trim=True)
            if curOrientation == "Reversed":
                # need to test against Part.Circle, not Part.ArcOfCircle
                if not isinstance(curredge.Curve, Part.Circle):
                    # if not arc/circle, assume straight line, reverse it
                    nedge = Part.Edge(nedge.Vertexes[1], nedge.Vertexes[0])
                else:
                    # if arc/circle
                    # Part.ArcOfCircle(edge.Curve,
                    #                  edge.FirstParameter,
                    #                  edge.LastParameter,
                    #                  edge.Curve.Axis.z > 0)
                    midParameter = nedge.FirstParameter + (nedge.LastParameter - nedge.FirstParameter)/2
                    midOfArc = nedge.valueAt(midParameter)
                    nedge = Part.ArcOfCircle(nedge.Vertexes[1].Point,
                                             midOfArc,
                                             nedge.Vertexes[0].Point).toShape()
                    # TODO any better solution than to calculate midpoint
                    # of arc to reverse?
        else:
            print(" something wrong ")
            return None
        if not nedge:
            return None

        nedges.append(nedge)

    if len(edges) > 1:
        nedges = connect(nedges, closed)
    else:
        nedges = Part.Wire(nedges[0])

    if bind and not closed:
        e1 = Part.LineSegment(edges[0].Vertexes[0].Point,
                              nedges[0].Vertexes[0].Point).toShape()
        e2 = Part.LineSegment(edges[-1].Vertexes[-1].Point,
                              nedges[-1].Vertexes[-1].Point).toShape()
        alledges = edges.extend(nedges)
        alledges = alledges.extend([e1, e2])
        w = Part.Wire(alledges)
        return w
    else:
        return nedges
Ejemplo n.º 38
0
    def getExtrusionData(self,obj):

        """returns (shape,extrusion vector,placement) or None"""
        import Part,DraftGeomUtils
        data = ArchComponent.Component.getExtrusionData(self,obj)
        if data:
            if not isinstance(data[0],list):
                # multifuses not considered here
                return data
        length  = obj.Length.Value
        width = obj.Width.Value
        height = obj.Height.Value
        if not height:
            for p in obj.InList:
                if Draft.getType(p) in ["Floor","BuildingPart"]:
                    if p.Height.Value:
                        height = p.Height.Value
        if not height:
            return None
        if obj.Normal == Vector(0,0,0):
            normal = Vector(0,0,1)
        else:
            normal = Vector(obj.Normal)
        base = None
        placement = None
        self.basewires = None
        # build wall layers
        layers = []
        if hasattr(obj,"Material"):
            if obj.Material:
                if hasattr(obj.Material,"Materials"):
                    varwidth = 0
                    restwidth = width - sum(obj.Material.Thicknesses)
                    if restwidth > 0:
                        varwidth = [t for t in obj.Material.Thicknesses if t == 0]
                        if varwidth:
                            varwidth = restwidth/len(varwidth)
                    for t in obj.Material.Thicknesses:
                        if t:
                            layers.append(t)
                        elif varwidth:
                            layers.append(varwidth)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        return None
                    elif obj.Face > 0:
                        if len(obj.Base.Shape.Faces) >= obj.Face:
                            face = obj.Base.Shape.Faces[obj.Face-1]
                            # this wall is based on a specific face of its base object
                            if obj.Normal != Vector(0,0,0):
                                normal = face.normalAt(0,0)
                            if normal.getAngle(Vector(0,0,1)) > math.pi/4:
                                normal.multiply(width)
                                base = face.extrude(normal)
                                if obj.Align == "Center":
                                    base.translate(normal.negative().multiply(0.5))
                                elif obj.Align == "Right":
                                    base.translate(normal.negative())
                            else:
                                normal.multiply(height)
                                base = face.extrude(normal)
                            base,placement = self.rebase(base)
                            return (base,normal,placement)
                    elif obj.Base.Shape.Faces:
                        if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                            return None
                        else:
                            base,placement = self.rebase(obj.Base.Shape)
                    elif len(obj.Base.Shape.Edges) == 1:
                        self.basewires = [Part.Wire(obj.Base.Shape.Edges)]
                    else:
                        # self.basewires = obj.Base.Shape.Wires
                        self.basewires = []
                        for cluster in Part.getSortedClusters(obj.Base.Shape.Edges):
                            for c in Part.sortEdges(cluster):
                                self.basewires.append(Part.Wire(c))

                    if self.basewires and width:
                        if (len(self.basewires) == 1) and layers:
                            self.basewires = [self.basewires[0] for l in layers]
                        layeroffset = 0
                        baseface = None
                        for i,wire in enumerate(self.basewires):
                            e = wire.Edges[0]
                            if isinstance(e.Curve,Part.Circle):
                                dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                            else:
                                dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                            if not DraftVecUtils.isNull(dvec):
                                dvec.normalize()
                            sh = None
                            if obj.Align == "Left":
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Right":
                                dvec = dvec.negative()
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Center":
                                if layers:
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w1 = DraftGeomUtils.offsetWire(wire,d1)
                                    layeroffset += layers[i]
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w2 = DraftGeomUtils.offsetWire(wire,d1)
                                else:
                                    dvec.multiply(width/2)
                                    w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                    dvec = dvec.negative()
                                    w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                sh = DraftGeomUtils.bind(w1,w2)
                            if sh:
                                sh.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(sh)
                                if baseface:
                                    if layers:
                                        baseface.append(f)
                                    else:
                                        baseface = baseface.fuse(f)
                                        # baseface = baseface.removeSplitter()
                                        s = DraftGeomUtils.removeSplitter(baseface)
                                        if s:
                                            baseface = s
                                else:
                                    if layers:
                                        baseface = [f]
                                    else:
                                        baseface = f
                        if baseface:
                            base,placement = self.rebase(baseface)
        else:
            if layers:
                totalwidth = sum(layers)
                offset = 0
                base = []
                for l in layers:
                    l2 = length/2 or 0.5
                    w1 = -totalwidth/2 + offset
                    w2 = w1 + l
                    v1 = Vector(-l2,w1,0)
                    v2 = Vector(l2,w1,0)
                    v3 = Vector(l2,w2,0)
                    v4 = Vector(-l2,w2,0)
                    base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])))
                    offset += l
            else:
                l2 = length/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
                base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            placement = FreeCAD.Placement()
        if base and placement:
            extrusion = normal.multiply(height)
            if placement.Rotation.Angle > 0:
                extrusion = placement.inverse().Rotation.multVec(extrusion)
            return (base,extrusion,placement)
        return None
Ejemplo n.º 39
0
    def execute(self, obj):
        "creates the panel shape"

        if self.clone(obj):
            return

        import Part, DraftGeomUtils

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

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

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

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

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

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

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

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(
                            translate("Arch", "Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Ejemplo n.º 40
0
 def getProfiles(self,obj,noplacement=False):
     "Returns the base profile(s) of this component, if applicable"
     wires = []
     n,l,w,h = self.getDefaultValues(obj)
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 base = obj.Base.Shape.copy()
                 if noplacement:
                     base.Placement = FreeCAD.Placement()
                 if not base.Solids:
                     if base.Faces: 
                         return [base]
                     basewires = []
                     if not base.Wires:
                         if len(base.Edges) == 1:
                             import Part
                             basewires = [Part.Wire(base.Edges)]
                     else:
                         basewires = base.Wires
                     if basewires:
                         import DraftGeomUtils,DraftVecUtils,Part
                         for wire in basewires:
                             e = wire.Edges[0]
                             if isinstance(e.Curve,Part.Circle):
                                 dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                             else:
                                 dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(n)
                             if not DraftVecUtils.isNull(dvec):
                                 dvec.normalize()
                             sh = None
                             if hasattr(obj,"Align"):
                                 if obj.Align == "Left":
                                     dvec.multiply(w)
                                     if hasattr(obj,"Offset"):
                                         if obj.Offset.Value:
                                             dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                             wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                     w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                     w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
                                     sh = DraftGeomUtils.bind(w1,w2)
                                 elif obj.Align == "Right":
                                     dvec.multiply(w)
                                     dvec = dvec.negative()
                                     if hasattr(obj,"Offset"):
                                         if obj.Offset.Value:
                                             dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                             wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                     w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                     w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
                                     sh = DraftGeomUtils.bind(w1,w2)
                                 elif obj.Align == "Center":
                                     dvec.multiply(w/2)
                                     w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                     dvec = dvec.negative()
                                     w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                     sh = DraftGeomUtils.bind(w1,w2)
                                 if sh:
                                     wires.append(sh)
                             else:
                                 wires.append(wire)
     else:
         if (Draft.getType(obj) == "Structure") and (l > h):
             if noplacement:
                 h2 = h/2 or 0.5
                 w2 = w/2 or 0.5
                 v1 = Vector(-h2,-w2,0)
                 v2 = Vector(h2,-w2,0)
                 v3 = Vector(h2,w2,0)
                 v4 = Vector(-h2,w2,0)
             else:
                 h2 = h/2 or 0.5
                 w2 = w/2 or 0.5
                 v1 = Vector(0,-w2,-h2)
                 v2 = Vector(0,-w2,h2)
                 v3 = Vector(0,w2,h2)
                 v4 = Vector(0,w2,-h2)
         else:
             l2 = l/2 or 0.5
             w2 = w/2 or 0.5
             v1 = Vector(-l2,-w2,0)
             v2 = Vector(l2,-w2,0)
             v3 = Vector(l2,w2,0)
             v4 = Vector(-l2,w2,0)
         import Part
         base = Part.makePolygon([v1,v2,v3,v4,v1])
         return [base]
     return wires
Ejemplo n.º 41
0
def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None,linestyle=None,color=None,linespacing=None,techdraw=False,rotation=0):
    '''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle],[color],[linespacing]):
    returns a string containing a SVG representation of the given object,
    with the given linewidth and fontsize (used if the given object contains
    any text). You can also supply an arbitrary projection vector. the
    scale parameter allows to scale linewidths down, so they are resolution-independant.'''

    # if this is a group, gather all the svg views of its children
    if hasattr(obj,"isDerivedFrom"):
        if obj.isDerivedFrom("App::DocumentObjectGroup"):
            svg = ""
            for child in obj.Group:
                svg += getSVG(child,scale,linewidth,fontsize,fillstyle,direction,linestyle,color,linespacing,techdraw)
            return svg

    pathdata = []
    svg = ""
    linewidth = float(linewidth)/scale
    fontsize = (float(fontsize)/scale)/2
    if linespacing:
        linespacing = float(linespacing)/scale
    else:
        linespacing = 0.5
    #print obj.Label," line spacing ",linespacing,"scale ",scale
    pointratio = .75 # the number of times the dots are smaller than the arrow size
    plane = None
    if direction:
        if isinstance(direction,FreeCAD.Vector):
            if direction != Vector(0,0,0):
                plane = WorkingPlane.plane()
                plane.alignToPointAndAxis_SVG(Vector(0,0,0),direction.negative().negative(),0)
        elif isinstance(direction,WorkingPlane.plane):
            plane = direction
    stroke = "#000000"
    if color:
        if "#" in color:
            stroke = color
        else:
            stroke = getrgb(color)
    elif gui:
        if hasattr(obj,"ViewObject"):
            if hasattr(obj.ViewObject,"LineColor"):
                stroke = getrgb(obj.ViewObject.LineColor)


    def getPath(edges=[],wires=[],pathname=None):
        import Part,DraftGeomUtils
        svg = "<path "
        if pathname is None:
            svg += 'id="%s" ' % obj.Name
        elif pathname != "":
            svg += 'id="%s" ' % pathname
        svg += ' d="'
        if not wires:
            egroups = Part.sortEdges(edges)
        else:
            egroups = []
            for w in wires:
                w1=w.copy()
                w1.fixWire()
                egroups.append(Part.__sortEdges__(w1.Edges))
        for egroupindex, edges in enumerate(egroups):
            edata = ""
            vs=() #skipped for the first edge
            for edgeindex,e in enumerate(edges):
                previousvs = vs
                # vertexes of an edge (reversed if needed)
                vs = e.Vertexes
                if previousvs:
                    if (vs[0].Point-previousvs[-1].Point).Length > 1e-6:
                        vs.reverse()
                if edgeindex == 0:
                    v = getProj(vs[0].Point, plane)
                    edata += 'M '+ str(v.x) +' '+ str(v.y) + ' '
                else:
                    if (vs[0].Point-previousvs[-1].Point).Length > 1e-6:
                        raise ValueError('edges not ordered')
                iscircle = DraftGeomUtils.geomType(e) == "Circle"
                isellipse = DraftGeomUtils.geomType(e) == "Ellipse"
                if iscircle or isellipse:
                    import math
                    if hasattr(FreeCAD,"DraftWorkingPlane"):
                        drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
                    else:
                        drawing_plane_normal = FreeCAD.Vector(0,0,1)
                    if plane: drawing_plane_normal = plane.axis
                    c = e.Curve
                    if round(c.Axis.getAngle(drawing_plane_normal),2) in [0,3.14]:
                        occversion = Part.OCC_VERSION.split(".")
                        done = False
                        if (int(occversion[0]) >= 7) and (int(occversion[1]) >= 1):
                            # if using occ >= 7.1, use HLR algorithm
                            import Drawing
                            snip = Drawing.projectToSVG(e,drawing_plane_normal)
                            if snip:
                                try:
                                    a = "A " + snip.split("path d=\"")[1].split("\"")[0].split("A")[1]
                                except:
                                    pass
                                else:
                                    edata += a
                                    done = True
                        if not done:
                            if len(e.Vertexes) == 1 and iscircle: #complete curve
                                svg = getCircle(e)
                                return svg
                            elif len(e.Vertexes) == 1 and isellipse:
                                #svg = getEllipse(e)
                                #return svg
                                endpoints = (getProj(c.value((c.LastParameter-\
                                        c.FirstParameter)/2.0), plane), \
                                        getProj(vs[-1].Point, plane))
                            else:
                                endpoints = (getProj(vs[-1].Point), plane)
                            # arc
                            if iscircle:
                                rx = ry = c.Radius
                                rot = 0
                            else: #ellipse
                                rx = c.MajorRadius
                                ry = c.MinorRadius
                                rot = math.degrees(c.AngleXU * (c.Axis * \
                                    FreeCAD.Vector(0,0,1)))
                                if rot > 90:
                                    rot -=180
                                if rot < -90:
                                    rot += 180
                                #be careful with the sweep flag
                            flag_large_arc = (((e.ParameterRange[1] - \
                                    e.ParameterRange[0]) / math.pi) % 2) > 1
                            #flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
                            #         == (e.LastParameter > e.FirstParameter)
                            #        == (e.Orientation == "Forward")
                            # other method: check the direction of the angle between tangents
                            t1 = e.tangentAt(e.FirstParameter)
                            t2 = e.tangentAt(e.FirstParameter + (e.LastParameter-e.FirstParameter)/10)
                            flag_sweep = (DraftVecUtils.angle(t1,t2,drawing_plane_normal) < 0)
                            for v in endpoints:
                                edata += 'A %s %s %s %s %s %s %s ' % \
                                        (str(rx),str(ry),str(rot),\
                                        str(int(flag_large_arc)),\
                                        str(int(flag_sweep)),str(v.x),str(v.y))
                    else:
                        edata += getDiscretized(e, plane)
                elif DraftGeomUtils.geomType(e) == "Line":
                    v = getProj(vs[-1].Point, plane)
                    edata += 'L '+ str(v.x) +' '+ str(v.y) + ' '
                else:
                    bspline=e.Curve.toBSpline(e.FirstParameter,e.LastParameter)
                    if bspline.Degree > 3 or bspline.isRational():
                        try:
                            bspline=bspline.approximateBSpline(0.05,50, 3,'C0')
                        except RuntimeError:
                            print("Debug: unable to approximate bspline")
                    if bspline.Degree <= 3 and not bspline.isRational():
                        for bezierseg in bspline.toBezier():
                            if bezierseg.Degree>3: #should not happen
                                raise AssertionError
                            elif bezierseg.Degree==1:
                                edata +='L '
                            elif bezierseg.Degree==2:
                                edata +='Q '
                            elif bezierseg.Degree==3:
                                edata +='C '
                            for pole in bezierseg.getPoles()[1:]:
                                v = getProj(pole, plane)
                                edata += str(v.x) +' '+ str(v.y) + ' '
                    else:
                        print("Debug: one edge (hash ",e.hashCode(),\
                                ") has been discretized with parameter 0.1")
                        for linepoint in bspline.discretize(0.1)[1:]:
                            v = getProj(linepoint, plane)
                            edata += 'L '+ str(v.x) +' '+ str(v.y) + ' '
            if fill != 'none':
                edata += 'Z '
            if edata in pathdata:
                # do not draw a path on another identical path
                return ""
            else:
                svg += edata
                pathdata.append(edata)
        svg += '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:'+ str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill
        try:
            svg += ';fill-opacity:' + str(fill_opacity)
        except NameError:
            pass
        svg += ';fill-rule: evenodd "'
        svg += '/>\n'
        return svg

    def getCircle(edge):
        cen = getProj(edge.Curve.Center, plane)
        rad = edge.Curve.Radius
        if hasattr(FreeCAD,"DraftWorkingPlane"):
            drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
        else:
            drawing_plane_normal = FreeCAD.Vector(0,0,1)
        if plane: drawing_plane_normal = plane.axis
        if round(edge.Curve.Axis.getAngle(drawing_plane_normal),2) == 0:
            # perpendicular projection: circle
            svg = '<circle cx="' + str(cen.x)
            svg += '" cy="' + str(cen.y)
            svg += '" r="' + str(rad)+'" '
        else:
            # any other projection: ellipse
            svg = '<path d="'
            svg += getDiscretized(edge, plane)
            svg += '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:'+ str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill + '"'
        svg += '/>\n'
        return svg

    def getEllipse(edge):
        cen = getProj(edge.Curve.Center, plane)
        mir = edge.Curve.MinorRadius
        mar = edge.Curve.MajorRadius
        svg = '<ellipse cx="' + str(cen.x)
        svg += '" cy="' + str(cen.y)
        svg += '" rx="' + str(mar)
        svg += '" ry="' + str(mir)+'" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:'+ str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill + '"'
        svg += '/>\n'
        return svg

    def getArrow(arrowtype,point,arrowsize,color,linewidth,angle=0):
        svg = ""
        if gui:
            if not obj.ViewObject:
                return svg
            if obj.ViewObject.ArrowType == "Circle":
                svg += '<circle cx="'+str(point.x)+'" cy="'+str(point.y)
                svg += '" r="'+str(arrowsize)+'" '
                svg += 'fill="none" stroke="'+ color + '" '
                svg += 'style="stroke-width:'+ str(linewidth) + ';stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'freecad:skip="1"'
                svg += '/>\n'
            elif obj.ViewObject.ArrowType == "Dot":
                svg += '<circle cx="'+str(point.x)+'" cy="'+str(point.y)
                svg += '" r="'+str(arrowsize)+'" '
                svg += 'fill="'+ color +'" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'freecad:skip="1"'
                svg += '/>\n'
            elif obj.ViewObject.ArrowType == "Arrow":
                svg += '<path transform="rotate('+str(math.degrees(angle))
                svg += ','+ str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'scale('+str(arrowsize)+','+str(arrowsize)+')" freecad:skip="1" '
                svg += 'fill="'+ color +'" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'd="M 0 0 L 4 1 L 4 -1 Z"/>\n'
            elif obj.ViewObject.ArrowType == "Tick":
                svg += '<path transform="rotate('+str(math.degrees(angle))
                svg += ','+ str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'scale('+str(arrowsize)+','+str(arrowsize)+')" freecad:skip="1" '
                svg += 'fill="'+ color +'" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'd="M -1 -2 L 0 2 L 1 2 L 0 -2 Z"/>\n'
            elif obj.ViewObject.ArrowType == "Tick-2":
                svg += '<line transform="rotate('+str(math.degrees(angle)+45)
                svg += ','+ str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += '" freecad:skip="1" '
                svg += 'fill="none" stroke="'+ color +'" '
                svg += 'style="stroke-dasharray:none;stroke-linecap:square;'
                svg += 'stroke-width:'+ str(linewidth) +'" '
                svg += 'x1="-'+ str(arrowsize*2) +'" y1="0" '
                svg += 'x2="' + str(arrowsize*2) +'" y2="0" />\n'
            else:
                print("getSVG: arrow type not implemented")
        return svg

    def getOvershoot(point,shootsize,color,linewidth,angle=0):
        svg = '<line transform="rotate('+str(math.degrees(angle))
        svg += ','+ str(point.x) + ',' + str(point.y) + ') '
        svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
        svg += '" freecad:skip="1" '
        svg += 'fill="none" stroke="'+ color +'" '
        svg += 'style="stroke-dasharray:none;stroke-linecap:square;'
        svg += 'stroke-width:'+ str(linewidth) +'" '
        svg += 'x1="0" y1="0" '
        svg += 'x2="'+ str(shootsize*-1) +'" y2="0" />\n'
        return svg

    def getText(color,fontsize,fontname,angle,base,text,linespacing=0.5,align="center",flip=True):
        if isinstance(angle,FreeCAD.Rotation):
            if not plane:
                angle = angle.Angle
            else:
                if plane.axis.getAngle(angle.Axis) < 0.001:
                    angle = angle.Angle
                elif abs(plane.axis.getAngle(angle.Axis)-math.pi) < 0.001:
                    return "" # text is perpendicular to view, so it shouldn't appear
                else:
                    angle = 0 #TODO maybe there is something better to do here?
        if not isinstance(text,list):
            text = text.split("\n")
        if align.lower() == "center":
            anchor = "middle"
        elif align.lower() == "left":
            anchor = "start"
        else:
            anchor = "end"
        if techdraw:
            svg = ""
            for i in range(len(text)):
                t = text[i]
                if sys.version_info.major < 3 and (not isinstance(t,unicode)):
                    t = t.decode("utf8")
                # possible workaround if UTF8 is unsupported
                #    import unicodedata
                #    t = u"".join([c for c in unicodedata.normalize("NFKD",t) if not unicodedata.combining(c)]).encode("utf8")
                svg += '<text fill="' + color +'" font-size="' + str(fontsize) + '" '
                svg += 'style="text-anchor:'+anchor+';text-align:'+align.lower()+';'
                svg += 'font-family:'+ fontname +'" '
                svg += 'transform="rotate('+str(math.degrees(angle))
                svg += ','+ str(base.x) + ',' + str(base.y-linespacing*i) + ') '
                svg += 'translate(' + str(base.x) + ',' + str(base.y-linespacing*i) + ') '
                svg += 'scale(1,-1)" '
                #svg += '" freecad:skip="1"'
                svg += '>\n' + t + '</text>\n'
        else:
            svg = '<text fill="'
            svg += color +'" font-size="'
            svg += str(fontsize) + '" '
            svg += 'style="text-anchor:'+anchor+';text-align:'+align.lower()+';'
            svg += 'font-family:'+ fontname +'" '
            svg += 'transform="rotate('+str(math.degrees(angle))
            svg += ','+ str(base.x) + ',' + str(base.y) + ') '
            if flip:
                svg += 'translate(' + str(base.x) + ',' + str(base.y) + ')'
            else:
                svg += 'translate(' + str(base.x) + ',' + str(-base.y) + ')'
            #svg += 'scale('+str(tmod/2000)+',-'+str(tmod/2000)+') '
            if flip:
                svg += ' scale(1,-1) '
            else:
                svg += ' scale(1,1) '
            svg += '" freecad:skip="1"'
            svg += '>\n'
            if len(text) == 1:
                try:
                    svg += text[0]
                except:
                    svg += text[0].decode("utf8")
            else:
                for i in range(len(text)):
                    if i == 0:
                        svg += '<tspan>'
                    else:
                        svg += '<tspan x="0" dy="'+str(linespacing)+'">'
                    try:
                        svg += text[i]
                    except:
                        svg += text[i].decode("utf8")
                    svg += '</tspan>\n'
            svg += '</text>\n'
        return svg


    if not obj:
        pass

    elif isinstance(obj,Part.Shape):
        if "#" in fillstyle:
            fill = fillstyle
        elif fillstyle == "shape color":
            fill = "#888888"
        else:
            fill = 'url(#'+fillstyle+')'
        lstyle = getLineStyle(linestyle, scale)
        svg += getPath(obj.Edges,pathname="")


    elif getType(obj) == "Dimension":
        if gui:
            if not obj.ViewObject:
                print ("export of dimensions to SVG is only available in GUI mode")
            elif obj.ViewObject.Proxy:
                if hasattr(obj.ViewObject.Proxy,"p1"):
                    prx = obj.ViewObject.Proxy
                    ts = (len(prx.string)*obj.ViewObject.FontSize.Value)/4.0
                    rm = ((prx.p3.sub(prx.p2)).Length/2.0)-ts
                    p2a = getProj(prx.p2.add(DraftVecUtils.scaleTo(prx.p3.sub(prx.p2),rm)), plane)
                    p2b = getProj(prx.p3.add(DraftVecUtils.scaleTo(prx.p2.sub(prx.p3),rm)), plane)
                    p1 = getProj(prx.p1, plane)
                    p2 = getProj(prx.p2, plane)
                    p3 = getProj(prx.p3, plane)
                    p4 = getProj(prx.p4, plane)
                    tbase = getProj(prx.tbase, plane)
                    r = prx.textpos.rotation.getValue().getValue()
                    rv = FreeCAD.Rotation(r[0],r[1],r[2],r[3]).multVec(FreeCAD.Vector(1,0,0))
                    angle = -DraftVecUtils.angle(getProj(rv, plane))
                    #angle = -DraftVecUtils.angle(p3.sub(p2))

                    # drawing lines
                    svg = '<path '
                    if obj.ViewObject.DisplayMode == "2D":
                        tangle = angle
                        if tangle > math.pi/2:
                            tangle = tangle-math.pi
                        #elif (tangle <= -math.pi/2) or (tangle > math.pi/2):
                        #    tangle = tangle+math.pi
                        #tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2/scale,0),tangle))
                        if rotation != 0:
                            #print "dim: tangle:",tangle," rot: ",rotation," text: ",prx.string
                            if abs(tangle+math.radians(rotation)) < 0.0001:
                                tangle += math.pi
                                tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2/scale,0),tangle))
                        svg += 'd="M '+str(p1.x)+' '+str(p1.y)+' '
                        svg += 'L '+str(p2.x)+' '+str(p2.y)+' '
                        svg += 'L '+str(p3.x)+' '+str(p3.y)+' '
                        svg += 'L '+str(p4.x)+' '+str(p4.y)+'" '
                    else:
                        tangle = 0
                        if rotation != 0:
                            tangle = -math.radians(rotation)
                        tbase = tbase.add(Vector(0,-2.0/scale,0))
                        svg += 'd="M '+str(p1.x)+' '+str(p1.y)+' '
                        svg += 'L '+str(p2.x)+' '+str(p2.y)+' '
                        svg += 'L '+str(p2a.x)+' '+str(p2a.y)+' '
                        svg += 'M '+str(p2b.x)+' '+str(p2b.y)+' '
                        svg += 'L '+str(p3.x)+' '+str(p3.y)+' '
                        svg += 'L '+str(p4.x)+' '+str(p4.y)+'" '

                    svg += 'fill="none" stroke="'
                    svg += stroke + '" '
                    svg += 'stroke-width="' + str(linewidth) + ' px" '
                    svg += 'style="stroke-width:'+ str(linewidth)
                    svg += ';stroke-miterlimit:4;stroke-dasharray:none" '
                    svg += 'freecad:basepoint1="'+str(p1.x)+' '+str(p1.y)+'" '
                    svg += 'freecad:basepoint2="'+str(p4.x)+' '+str(p4.y)+'" '
                    svg += 'freecad:dimpoint="'+str(p2.x)+' '+str(p2.y)+'"'
                    svg += '/>\n'

                    # drawing dimension and extension lines overshoots
                    if hasattr(obj.ViewObject,"DimOvershoot") and obj.ViewObject.DimOvershoot.Value:
                        shootsize = obj.ViewObject.DimOvershoot.Value/pointratio
                        svg += getOvershoot(p2,shootsize,stroke,linewidth,angle)
                        svg += getOvershoot(p3,shootsize,stroke,linewidth,angle+math.pi)
                    if hasattr(obj.ViewObject,"ExtOvershoot") and obj.ViewObject.ExtOvershoot.Value:
                        shootsize = obj.ViewObject.ExtOvershoot.Value/pointratio
                        shootangle = -DraftVecUtils.angle(p1.sub(p2))
                        svg += getOvershoot(p2,shootsize,stroke,linewidth,shootangle)
                        svg += getOvershoot(p3,shootsize,stroke,linewidth,shootangle)

                    # drawing arrows
                    if hasattr(obj.ViewObject,"ArrowType"):
                        arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                        if hasattr(obj.ViewObject,"FlipArrows"):
                            if obj.ViewObject.FlipArrows:
                                angle = angle+math.pi
                        svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle)
                        svg += getArrow(obj.ViewObject.ArrowType,p3,arrowsize,stroke,linewidth,angle+math.pi)

                    # drawing text
                    svg += getText(stroke,fontsize,obj.ViewObject.FontName,tangle,tbase,prx.string)

    elif getType(obj) == "AngularDimension":
        if gui:
            if not obj.ViewObject:
                print ("export of dimensions to SVG is only available in GUI mode")
            elif obj.ViewObject.Proxy:
                if hasattr(obj.ViewObject.Proxy,"circle"):
                    prx = obj.ViewObject.Proxy

                    # drawing arc
                    fill= "none"
                    lstyle = getLineStyle(linestyle, scale)
                    if obj.ViewObject.DisplayMode == "2D":
                        svg += getPath([prx.circle])
                    else:
                        if hasattr(prx,"circle1"):
                            svg += getPath([prx.circle1])
                            svg += getPath([prx.circle2])
                        else:
                            svg += getPath([prx.circle])

                    # drawing arrows
                    if hasattr(obj.ViewObject,"ArrowType"):
                        p2 = getProj(prx.p2, plane)
                        p3 = getProj(prx.p3, plane)
                        arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                        arrowlength = 4*obj.ViewObject.ArrowSize.Value
                        u1 = getProj((prx.circle.valueAt(prx.circle.FirstParameter+arrowlength)).sub(prx.circle.valueAt(prx.circle.FirstParameter)), plane)
                        u2 = getProj((prx.circle.valueAt(prx.circle.LastParameter-arrowlength)).sub(prx.circle.valueAt(prx.circle.LastParameter)), plane)
                        angle1 = -DraftVecUtils.angle(u1)
                        angle2 = -DraftVecUtils.angle(u2)
                        if hasattr(obj.ViewObject,"FlipArrows"):
                            if obj.ViewObject.FlipArrows:
                                angle1 = angle1+math.pi
                                angle2 = angle2+math.pi
                        svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle1)
                        svg += getArrow(obj.ViewObject.ArrowType,p3,arrowsize,stroke,linewidth,angle2)

                    # drawing text
                    if obj.ViewObject.DisplayMode == "2D":
                        t = prx.circle.tangentAt(prx.circle.FirstParameter+(prx.circle.LastParameter-prx.circle.FirstParameter)/2.0)
                        t = getProj(t, plane)
                        tangle = DraftVecUtils.angle(t)
                        if (tangle <= -math.pi/2) or (tangle > math.pi/2):
                            tangle = tangle + math.pi
                        tbase = getProj(prx.circle.valueAt(prx.circle.FirstParameter+(prx.circle.LastParameter-prx.circle.FirstParameter)/2.0), plane)
                        tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2.0/scale,0),tangle))
                        #print(tbase)
                    else:
                        tangle = 0
                        tbase = getProj(prx.tbase, plane)
                    svg += getText(stroke,fontsize,obj.ViewObject.FontName,tangle,tbase,prx.string)

    elif getType(obj) == "Label":
        if getattr(obj.ViewObject, "Line", True):  # some Labels may have no Line property
            def format_point(coords, action='L'):
                return "{action}{x},{y}".format(
                    x=coords.x, y=coords.y, action=action
                )

            # Draw multisegment line
            proj_points = list(map(lambda x: getProj(x, plane), obj.Points))
            path_dir_list = [format_point(proj_points[0], action='M')]
            path_dir_list += map(format_point, proj_points[1:])
            path_dir_str = " ".join(path_dir_list)
            svg_path = '<path fill="none" stroke="{stroke}" stroke-width="{linewidth}" d="{directions}"/>'.format(
                stroke=stroke,
                linewidth=linewidth,
                directions=path_dir_str
            )
            svg += svg_path

            # Draw arrow.
            # We are different here from 3D view
            # if Line is set to 'off', no arrow is drawn
            if hasattr(obj.ViewObject, "ArrowType") and len(obj.Points) >= 2:
                last_segment = FreeCAD.Vector(obj.Points[-1] - obj.Points[-2])
                angle = -DraftVecUtils.angle(getProj(last_segment, plane)) + math.pi
                svg += getArrow(
                    arrowtype=obj.ViewObject.ArrowType,
                    point=proj_points[-1],
                    arrowsize=obj.ViewObject.ArrowSize.Value/pointratio,
                    color=stroke,
                    linewidth=linewidth,
                    angle=angle
                )

        # print text
        if gui:
            if not obj.ViewObject:
                print("export of texts to SVG is only available in GUI mode")
            else:
                fontname = obj.ViewObject.TextFont
                position = getProj(obj.Placement.Base, plane)
                rotation = obj.Placement.Rotation
                justification = obj.ViewObject.TextAlignment
                text = obj.Text
                svg += getText(stroke, fontsize, fontname, rotation, position,
                               text, linespacing, justification)

    elif getType(obj) in ["Annotation","DraftText"]:
        "returns an svg representation of a document annotation"
        if gui:
            if not obj.ViewObject:
                print ("export of texts to SVG is only available in GUI mode")
            else:
                n = obj.ViewObject.FontName
                if getType(obj) == "Annotation":
                    p = getProj(obj.Position, plane)
                    r = obj.ViewObject.Rotation.getValueAs("rad")
                    t = obj.LabelText
                else: # DraftText
                    p = getProj(obj.Placement.Base, plane)
                    r = obj.Placement.Rotation
                    t = obj.Text
                j = obj.ViewObject.Justification
                svg += getText(stroke,fontsize,n,r,p,t,linespacing,j)

    elif getType(obj) == "Axis":
        "returns the SVG representation of an Arch Axis system"
        if gui:
            if not obj.ViewObject:
                print ("export of axes to SVG is only available in GUI mode")
            else:
                vobj = obj.ViewObject
                lorig = getLineStyle(linestyle, scale)
                fill = 'none'
                rad = vobj.BubbleSize.Value/2
                n = 0
                for e in obj.Shape.Edges:
                    lstyle = lorig
                    svg += getPath([e])
                    lstyle = "none"
                    pos = ["Start"]
                    if hasattr(vobj,"BubblePosition"):
                        if vobj.BubblePosition == "Both":
                            pos = ["Start","End"]
                        else:
                            pos = [vobj.BubblePosition]
                    for p in pos:
                        if p == "Start":
                            p1 = e.Vertexes[0].Point
                            p2 = e.Vertexes[1].Point
                        else:
                            p1 = e.Vertexes[1].Point
                            p2 = e.Vertexes[0].Point
                        dv = p2.sub(p1)
                        dv.normalize()
                        center = p2.add(dv.scale(rad,rad,rad))
                        svg += getCircle(Part.makeCircle(rad,center))
                        if hasattr(vobj.Proxy,"bubbletexts"):
                            if len (vobj.Proxy.bubbletexts) >= n:
                                svg += '<text fill="' + stroke + '" '
                                svg += 'font-size="' + str(rad) + '" '
                                svg += 'style="text-anchor:middle;'
                                svg += 'text-align:center;'
                                svg += 'font-family: sans;" '
                                svg += 'transform="translate(' + str(center.x+rad/4.0) + ',' + str(center.y-rad/3.0) + ') '
                                svg += 'scale(1,-1)"> '
                                svg += '<tspan>' + obj.ViewObject.Proxy.bubbletexts[n].string.getValues()[0] + '</tspan>\n'
                                svg += '</text>\n'
                                n += 1

    elif getType(obj) == "Pipe":
        fill = stroke
        lstyle = getLineStyle(linestyle, scale)
        if obj.Base and obj.Diameter:
            svg += getPath(obj.Base.Shape.Edges)
        for f in obj.Shape.Faces:
            if len(f.Edges) == 1:
                if isinstance(f.Edges[0].Curve,Part.Circle):
                    svg += getCircle(f.Edges[0])

    elif getType(obj) == "Rebar":
        fill = "none"
        lstyle = getLineStyle(linestyle, scale)
        if obj.Proxy:
            if not hasattr(obj.Proxy,"wires"):
                obj.Proxy.execute(obj)
            if hasattr(obj.Proxy,"wires"):
                svg += getPath(wires=obj.Proxy.wires)

    elif getType(obj) == "PipeConnector":
        pass

    elif getType(obj) == "Space":
        "returns an SVG fragment for the text of a space"
        if gui:
            if not obj.ViewObject:
                print ("export of spaces to SVG is only available in GUI mode")
            else:
                c = getrgb(obj.ViewObject.TextColor)
                n = obj.ViewObject.FontName
                a = 0
                if rotation != 0:
                    a = math.radians(rotation)
                t1 = obj.ViewObject.Proxy.text1.string.getValues()
                t2 = obj.ViewObject.Proxy.text2.string.getValues()
                scale = obj.ViewObject.FirstLine.Value/obj.ViewObject.FontSize.Value
                f1 = fontsize*scale
                p2 = FreeCAD.Vector(obj.ViewObject.Proxy.coords.translation.getValue().getValue())
                lspc = FreeCAD.Vector(obj.ViewObject.Proxy.header.translation.getValue().getValue())
                p1 = p2.add(lspc)
                j = obj.ViewObject.TextAlign
                svg += getText(c,f1,n,a,getProj(p1, plane),t1,linespacing,j,flip=True)
                if t2:
                    ofs = FreeCAD.Vector(0,lspc.Length,0)
                    if a:
                        ofs = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),-rotation).multVec(ofs)
                    svg += getText(c,fontsize,n,a,getProj(p1, plane).add(ofs),t2,linespacing,j,flip=True)

    elif obj.isDerivedFrom('Part::Feature'):
        if obj.Shape.isNull():
            return ''
        # setting fill
        if obj.Shape.Faces:
            if gui:
                try:
                    m = obj.ViewObject.DisplayMode
                except AttributeError:
                    m = None
                if (m != "Wireframe"):
                    if fillstyle == "shape color":
                        fill = getrgb(obj.ViewObject.ShapeColor,testbw=False)
                        fill_opacity = 1 - (obj.ViewObject.Transparency / 100.0)
                    else:
                        fill = 'url(#'+fillstyle+')'
                        svg += getPattern(fillstyle)
                else:
                    fill = "none"
            else:
                fill = "#888888"
        else:
            fill = 'none'
        lstyle = getLineStyle(linestyle, scale)

        if len(obj.Shape.Vertexes) > 1:
            wiredEdges = []
            if obj.Shape.Faces:
                for i,f in enumerate(obj.Shape.Faces):
                    svg += getPath(wires=f.Wires,pathname='%s_f%04d' % \
                            (obj.Name,i))
                    wiredEdges.extend(f.Edges)
            else:
                for i,w in enumerate(obj.Shape.Wires):
                    svg += getPath(w.Edges,pathname='%s_w%04d' % \
                            (obj.Name,i))
                    wiredEdges.extend(w.Edges)
            if len(wiredEdges) != len(obj.Shape.Edges):
                for i,e in enumerate(obj.Shape.Edges):
                    if (DraftGeomUtils.findEdge(e,wiredEdges) == None):
                        svg += getPath([e],pathname='%s_nwe%04d' % \
                                (obj.Name,i))
        else:
            # closed circle or spline
            if obj.Shape.Edges:
                if isinstance(obj.Shape.Edges[0].Curve,Part.Circle):
                    svg = getCircle(obj.Shape.Edges[0])
                else:
                    svg = getPath(obj.Shape.Edges)
        if FreeCAD.GuiUp:
            if hasattr(obj.ViewObject,"EndArrow") and hasattr(obj.ViewObject,"ArrowType") and (len(obj.Shape.Vertexes) > 1):
                if obj.ViewObject.EndArrow:
                    p1 = getProj(obj.Shape.Vertexes[-2].Point, plane)
                    p2 = getProj(obj.Shape.Vertexes[-1].Point, plane)
                    angle = -DraftVecUtils.angle(p2.sub(p1))
                    arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                    svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle)

    # techdraw expects bottom-to-top coordinates
    if techdraw:
        svg = '<g transform ="scale(1,-1)">'+svg+'</g>'
    return svg
Ejemplo n.º 42
0
    def execute(self,obj):
        "creates the panel shape"

        import Part, DraftGeomUtils

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

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if obj.Base:
            p = FreeCAD.Placement(obj.Base.Placement)
            normal = p.Rotation.multVec(Vector(0,0,1))
            normal = normal.multiply(thickness)
            base = obj.Base.Shape.copy()
            if base.Solids:
                pass
            elif base.Faces:
                self.BaseProfile = base
                self.ExtrusionVector = normal
                base = base.extrude(normal)
            elif base.Wires:
                closed = True
                for w in base.Wires:
                    if not w.isClosed():
                        closed = False
                if closed:
                    base = ArchCommands.makeFace(base.Wires)
                    self.BaseProfile = base
                    self.ExtrusionVector = normal
                    base = base.extrude(normal)
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if obj.Base.Mesh.isSolid():
                    if obj.Base.Mesh.countComponents() == 1:
                        sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                        if sh.isClosed() and sh.isValid() and sh.Solids:
                            base = sh
        else:
            normal = Vector(0,0,1).multiply(thickness)
            self.ExtrusionVector = normal
            l2 = length/2 or 0.5
            w2 = width/2 or 0.5
            v1 = Vector(-l2,-w2,0)
            v2 = Vector(l2,-w2,0)
            v3 = Vector(l2,w2,0)
            v4 = Vector(-l2,w2,0)
            base = Part.makePolygon([v1,v2,v3,v4,v1])
            base = Part.Face(base)
            self.BaseProfile = base
            base = base.extrude(self.ExtrusionVector)

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

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

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

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

        if self.clone(obj):
            return

        if len(obj.InList) != 1:
            return
        if Draft.getType(obj.InList[0]) != "Structure":
            return
        if not obj.InList[0].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.InList[0]
        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj, "Rounding"):
            #print obj.Rounding
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire, radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        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)  #.normalize()
                # don't normalize so the vector can also be used to determine the distance
                size = axis.Length
        #print axis
        #print size
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return

        # all tests ok!
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value / 2, bpoint, bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle], True, False, 2)
        except Part.OCCError:
            print "Arch: error sweeping rebar profile along the base sketch"
            return
        # building final shape
        shapes = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis, size / 2)
            bar.translate(offset)
            shapes.append(bar)
            if hasattr(obj, "Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart.Value)
            else:
                baseoffset = None
            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:
                        bar.translate(baseoffset)
                    shapes.append(bar)
                else:
                    bar = bar.copy()
                    bar.translate(vinterval)
                    shapes.append(bar)
            if hasattr(obj, "Spacing"):
                obj.Spacing = interval
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
Ejemplo n.º 44
0
def getSVG(obj,
           scale=1,
           linewidth=0.35,
           fontsize=12,
           fillstyle="shape color",
           direction=None,
           linestyle=None,
           color=None,
           linespacing=None,
           techdraw=False,
           rotation=0,
           fillSpaces=False,
           override=True):
    '''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle],[color],[linespacing]):
    returns a string containing a SVG representation of the given object,
    with the given linewidth and fontsize (used if the given object contains
    any text). You can also supply an arbitrary projection vector. the
    scale parameter allows to scale linewidths down, so they are resolution-independant.'''

    import Part, DraftGeomUtils

    # if this is a group, gather all the svg views of its children
    if hasattr(obj, "isDerivedFrom"):
        if obj.isDerivedFrom("App::DocumentObjectGroup") or getType(
                obj) == "Layer":
            svg = ""
            for child in obj.Group:
                svg += getSVG(child, scale, linewidth, fontsize, fillstyle,
                              direction, linestyle, color, linespacing,
                              techdraw, rotation, fillSpaces, override)
            return svg

    pathdata = []
    svg = ""
    linewidth = float(linewidth) / scale
    if not override:
        if hasattr(obj, "ViewObject"):
            if hasattr(obj.ViewObject, "LineWidth"):
                if hasattr(obj.ViewObject.LineWidth, "Value"):
                    lw = obj.ViewObject.LineWidth.Value
                else:
                    lw = obj.ViewObject.LineWidth
                linewidth = lw * linewidth
    fontsize = (float(fontsize) / scale) / 2
    if linespacing:
        linespacing = float(linespacing) / scale
    else:
        linespacing = 0.5
    #print obj.Label," line spacing ",linespacing,"scale ",scale
    pointratio = .75  # the number of times the dots are smaller than the arrow size
    plane = None
    if direction:
        if isinstance(direction, FreeCAD.Vector):
            if direction != Vector(0, 0, 0):
                plane = WorkingPlane.plane()
                plane.alignToPointAndAxis_SVG(Vector(0, 0, 0),
                                              direction.negative().negative(),
                                              0)
        elif isinstance(direction, WorkingPlane.plane):
            plane = direction
    stroke = "#000000"
    if color and override:
        if "#" in color:
            stroke = color
        else:
            stroke = getrgb(color)
    elif gui:
        if hasattr(obj, "ViewObject"):
            if hasattr(obj.ViewObject, "LineColor"):
                stroke = getrgb(obj.ViewObject.LineColor)
            elif hasattr(obj.ViewObject, "TextColor"):
                stroke = getrgb(obj.ViewObject.TextColor)
    lstyle = "none"
    if override:
        lstyle = getLineStyle(linestyle, scale)
    else:
        if hasattr(obj, "ViewObject"):
            if hasattr(obj.ViewObject, "DrawStyle"):
                lstyle = getLineStyle(obj.ViewObject.DrawStyle, scale)

    def getPath(edges=[], wires=[], pathname=None):

        svg = "<path "
        if pathname is None:
            svg += 'id="%s" ' % obj.Name
        elif pathname != "":
            svg += 'id="%s" ' % pathname
        svg += ' d="'
        if not wires:
            egroups = Part.sortEdges(edges)
        else:
            egroups = []
            first = True
            for w in wires:
                w1 = w.copy()
                if first:
                    first = False
                else:
                    # invert further wires to create holes
                    w1 = DraftGeomUtils.invert(w1)
                w1.fixWire()
                egroups.append(Part.__sortEdges__(w1.Edges))
        for egroupindex, edges in enumerate(egroups):
            edata = ""
            vs = ()  #skipped for the first edge
            for edgeindex, e in enumerate(edges):
                previousvs = vs
                # vertexes of an edge (reversed if needed)
                vs = e.Vertexes
                if previousvs:
                    if (vs[0].Point - previousvs[-1].Point).Length > 1e-6:
                        vs.reverse()
                if edgeindex == 0:
                    v = getProj(vs[0].Point, plane)
                    edata += 'M ' + str(v.x) + ' ' + str(v.y) + ' '
                else:
                    if (vs[0].Point - previousvs[-1].Point).Length > 1e-6:
                        raise ValueError('edges not ordered')
                iscircle = DraftGeomUtils.geomType(e) == "Circle"
                isellipse = DraftGeomUtils.geomType(e) == "Ellipse"
                if iscircle or isellipse:
                    import math
                    if hasattr(FreeCAD, "DraftWorkingPlane"):
                        drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
                    else:
                        drawing_plane_normal = FreeCAD.Vector(0, 0, 1)
                    if plane: drawing_plane_normal = plane.axis
                    c = e.Curve
                    if round(c.Axis.getAngle(drawing_plane_normal),
                             2) in [0, 3.14]:
                        occversion = Part.OCC_VERSION.split(".")
                        done = False
                        if (int(occversion[0]) >= 7) and (int(occversion[1]) >=
                                                          1):
                            # if using occ >= 7.1, use HLR algorithm
                            import Drawing
                            snip = Drawing.projectToSVG(
                                e, drawing_plane_normal)
                            if snip:
                                try:
                                    a = "A " + snip.split("path d=\"")[
                                        1].split("\"")[0].split("A")[1]
                                except:
                                    pass
                                else:
                                    edata += a
                                    done = True
                        if not done:
                            if len(e.Vertexes
                                   ) == 1 and iscircle:  #complete curve
                                svg = getCircle(e)
                                return svg
                            elif len(e.Vertexes) == 1 and isellipse:
                                #svg = getEllipse(e)
                                #return svg
                                endpoints = [
                                    getProj(
                                        c.value((c.LastParameter -
                                                 c.FirstParameter) / 2.0),
                                        plane),
                                    getProj(vs[-1].Point, plane)
                                ]
                            else:
                                endpoints = [getProj(vs[-1].Point, plane)]
                            # arc
                            if iscircle:
                                rx = ry = c.Radius
                                rot = 0
                            else:  #ellipse
                                rx = c.MajorRadius
                                ry = c.MinorRadius
                                rot = math.degrees(c.AngleXU * (c.Axis * \
                                    FreeCAD.Vector(0,0,1)))
                                if rot > 90:
                                    rot -= 180
                                if rot < -90:
                                    rot += 180
                                #be careful with the sweep flag
                            flag_large_arc = (((e.ParameterRange[1] - \
                                    e.ParameterRange[0]) / math.pi) % 2) > 1
                            #flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
                            #         == (e.LastParameter > e.FirstParameter)
                            #        == (e.Orientation == "Forward")
                            # other method: check the direction of the angle between tangents
                            t1 = e.tangentAt(e.FirstParameter)
                            t2 = e.tangentAt(
                                e.FirstParameter +
                                (e.LastParameter - e.FirstParameter) / 10)
                            flag_sweep = (DraftVecUtils.angle(
                                t1, t2, drawing_plane_normal) < 0)
                            for v in endpoints:
                                edata += 'A %s %s %s %s %s %s %s ' % \
                                        (str(rx),str(ry),str(rot),\
                                        str(int(flag_large_arc)),\
                                        str(int(flag_sweep)),str(v.x),str(v.y))
                    else:
                        edata += getDiscretized(e, plane)
                elif DraftGeomUtils.geomType(e) == "Line":
                    v = getProj(vs[-1].Point, plane)
                    edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
                else:
                    bspline = e.Curve.toBSpline(e.FirstParameter,
                                                e.LastParameter)
                    if bspline.Degree > 3 or bspline.isRational():
                        try:
                            bspline = bspline.approximateBSpline(
                                0.05, 50, 3, 'C0')
                        except RuntimeError:
                            print("Debug: unable to approximate bspline")
                    if bspline.Degree <= 3 and not bspline.isRational():
                        for bezierseg in bspline.toBezier():
                            if bezierseg.Degree > 3:  #should not happen
                                raise AssertionError
                            elif bezierseg.Degree == 1:
                                edata += 'L '
                            elif bezierseg.Degree == 2:
                                edata += 'Q '
                            elif bezierseg.Degree == 3:
                                edata += 'C '
                            for pole in bezierseg.getPoles()[1:]:
                                v = getProj(pole, plane)
                                edata += str(v.x) + ' ' + str(v.y) + ' '
                    else:
                        print("Debug: one edge (hash ",e.hashCode(),\
                                ") has been discretized with parameter 0.1")
                        for linepoint in bspline.discretize(0.1)[1:]:
                            v = getProj(linepoint, plane)
                            edata += 'L ' + str(v.x) + ' ' + str(v.y) + ' '
            if fill != 'none':
                edata += 'Z '
            if edata in pathdata:
                # do not draw a path on another identical path
                return ""
            else:
                svg += edata
                pathdata.append(edata)
        svg += '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill
        try:
            svg += ';fill-opacity:' + str(fill_opacity)
        except NameError:
            pass
        svg += ';fill-rule: evenodd "'
        svg += '/>\n'
        return svg

    def getCircle(edge):
        cen = getProj(edge.Curve.Center, plane)
        rad = edge.Curve.Radius
        if hasattr(FreeCAD, "DraftWorkingPlane"):
            drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
        else:
            drawing_plane_normal = FreeCAD.Vector(0, 0, 1)
        if plane: drawing_plane_normal = plane.axis
        if round(edge.Curve.Axis.getAngle(drawing_plane_normal),
                 2) in [0, 3.14]:
            # perpendicular projection: circle
            svg = '<circle cx="' + str(cen.x)
            svg += '" cy="' + str(cen.y)
            svg += '" r="' + str(rad) + '" '
        else:
            # any other projection: ellipse
            svg = '<path d="'
            svg += getDiscretized(edge, plane)
            svg += '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill + '"'
        svg += '/>\n'
        return svg

    def getEllipse(edge):
        cen = getProj(edge.Curve.Center, plane)
        mir = edge.Curve.MinorRadius
        mar = edge.Curve.MajorRadius
        svg = '<ellipse cx="' + str(cen.x)
        svg += '" cy="' + str(cen.y)
        svg += '" rx="' + str(mar)
        svg += '" ry="' + str(mir) + '" '
        svg += 'stroke="' + stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4'
        svg += ';stroke-dasharray:' + lstyle
        svg += ';fill:' + fill + '"'
        svg += '/>\n'
        return svg

    def getArrow(arrowtype, point, arrowsize, color, linewidth, angle=0):
        svg = ""
        if gui:
            if not obj.ViewObject:
                return svg
            if obj.ViewObject.ArrowType == "Circle":
                svg += '<circle cx="' + str(point.x) + '" cy="' + str(point.y)
                svg += '" r="' + str(arrowsize) + '" '
                svg += 'fill="none" stroke="' + color + '" '
                svg += 'style="stroke-width:' + str(
                    linewidth) + ';stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'freecad:skip="1"'
                svg += '/>\n'
            elif obj.ViewObject.ArrowType == "Dot":
                svg += '<circle cx="' + str(point.x) + '" cy="' + str(point.y)
                svg += '" r="' + str(arrowsize) + '" '
                svg += 'fill="' + color + '" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'freecad:skip="1"'
                svg += '/>\n'
            elif obj.ViewObject.ArrowType == "Arrow":
                svg += '<path transform="rotate(' + str(math.degrees(angle))
                svg += ',' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'scale(' + str(arrowsize) + ',' + str(
                    arrowsize) + ')" freecad:skip="1" '
                svg += 'fill="' + color + '" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'd="M 0 0 L 4 1 L 4 -1 Z"/>\n'
            elif obj.ViewObject.ArrowType == "Tick":
                svg += '<path transform="rotate(' + str(math.degrees(angle))
                svg += ',' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'scale(' + str(arrowsize) + ',' + str(
                    arrowsize) + ')" freecad:skip="1" '
                svg += 'fill="' + color + '" stroke="none" '
                svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
                svg += 'd="M -1 -2 L 0 2 L 1 2 L 0 -2 Z"/>\n'
            elif obj.ViewObject.ArrowType == "Tick-2":
                svg += '<line transform="rotate(' + str(
                    math.degrees(angle) + 45)
                svg += ',' + str(point.x) + ',' + str(point.y) + ') '
                svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
                svg += '" freecad:skip="1" '
                svg += 'fill="none" stroke="' + color + '" '
                svg += 'style="stroke-dasharray:none;stroke-linecap:square;'
                svg += 'stroke-width:' + str(linewidth) + '" '
                svg += 'x1="-' + str(arrowsize * 2) + '" y1="0" '
                svg += 'x2="' + str(arrowsize * 2) + '" y2="0" />\n'
            else:
                print("getSVG: arrow type not implemented")
        return svg

    def getOvershoot(point, shootsize, color, linewidth, angle=0):
        svg = '<line transform="rotate(' + str(math.degrees(angle))
        svg += ',' + str(point.x) + ',' + str(point.y) + ') '
        svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
        svg += '" freecad:skip="1" '
        svg += 'fill="none" stroke="' + color + '" '
        svg += 'style="stroke-dasharray:none;stroke-linecap:square;'
        svg += 'stroke-width:' + str(linewidth) + '" '
        svg += 'x1="0" y1="0" '
        svg += 'x2="' + str(shootsize * -1) + '" y2="0" />\n'
        return svg

    def getText(tcolor,
                fontsize,
                fontname,
                angle,
                base,
                text,
                linespacing=0.5,
                align="center",
                flip=True):
        if isinstance(angle, FreeCAD.Rotation):
            if not plane:
                angle = angle.Angle
            else:
                if plane.axis.getAngle(angle.Axis) < 0.001:
                    angle = angle.Angle
                elif abs(plane.axis.getAngle(angle.Axis) - math.pi) < 0.001:
                    if abs(angle.Angle) > 0.1:
                        angle = -angle.Angle
                    else:
                        angle = angle.Angle
                elif abs(plane.axis.getAngle(angle.Axis) -
                         math.pi / 2) < 0.001:
                    return ""  # text is perpendicular to view, so it shouldn't appear
                else:
                    angle = 0  #TODO maybe there is something better to do here?
        if not isinstance(text, list):
            text = text.split("\n")
        if align.lower() == "center":
            anchor = "middle"
        elif align.lower() == "left":
            anchor = "start"
        else:
            anchor = "end"
        if techdraw:
            svg = ""
            for i in range(len(text)):
                t = text[i].replace("&", "&amp;").replace("<", "&lt;").replace(
                    ">", "&gt;")
                if six.PY2 and not isinstance(t, six.text_type):
                    t = t.decode("utf8")
                # possible workaround if UTF8 is unsupported
                #    import unicodedata
                #    t = u"".join([c for c in unicodedata.normalize("NFKD",t) if not unicodedata.combining(c)]).encode("utf8")
                svg += '<text stroke-width="0" stroke="' + tcolor + '" fill="' + tcolor + '" font-size="' + str(
                    fontsize) + '" '
                svg += 'style="text-anchor:' + anchor + ';text-align:' + align.lower(
                ) + ';'
                svg += 'font-family:' + fontname + '" '
                svg += 'transform="rotate(' + str(math.degrees(angle))
                svg += ',' + str(
                    base.x) + ',' + str(base.y - linespacing * i) + ') '
                svg += 'translate(' + str(
                    base.x) + ',' + str(base.y - linespacing * i) + ') '
                svg += 'scale(1,-1)" '
                #svg += '" freecad:skip="1"'
                svg += '>\n' + t + '</text>\n'
        else:
            svg = '<text stroke-width="0" stroke="' + tcolor + '" fill="'
            svg += tcolor + '" font-size="'
            svg += str(fontsize) + '" '
            svg += 'style="text-anchor:' + anchor + ';text-align:' + align.lower(
            ) + ';'
            svg += 'font-family:' + fontname + '" '
            svg += 'transform="rotate(' + str(math.degrees(angle))
            svg += ',' + str(base.x) + ',' + str(base.y) + ') '
            if flip:
                svg += 'translate(' + str(base.x) + ',' + str(base.y) + ')'
            else:
                svg += 'translate(' + str(base.x) + ',' + str(-base.y) + ')'
            #svg += 'scale('+str(tmod/2000)+',-'+str(tmod/2000)+') '
            if flip:
                svg += ' scale(1,-1) '
            else:
                svg += ' scale(1,1) '
            svg += '" freecad:skip="1"'
            svg += '>\n'
            if len(text) == 1:
                try:
                    svg += text[0].replace("&", "&amp;").replace(
                        "<", "&lt;").replace(">", "&gt;")
                except:
                    svg += text[0].decode("utf8").replace(
                        "&", "&amp;").replace("<",
                                              "&lt;").replace(">", "&gt;")
            else:
                for i in range(len(text)):
                    if i == 0:
                        svg += '<tspan>'
                    else:
                        svg += '<tspan x="0" dy="' + str(linespacing) + '">'
                    try:
                        svg += text[i].replace("&", "&amp;").replace(
                            "<", "&lt;").replace(">", "&gt;")
                    except:
                        svg += text[i].decode("utf8").replace(
                            "&", "&amp;").replace("<",
                                                  "&lt;").replace(">", "&gt;")
                    svg += '</tspan>\n'
            svg += '</text>\n'
        return svg

    if not obj:
        pass

    elif isinstance(obj, Part.Shape):
        if "#" in fillstyle:
            fill = fillstyle
        elif fillstyle == "shape color":
            fill = "#888888"
        else:
            fill = 'url(#' + fillstyle + ')'
        svg += getPath(obj.Edges, pathname="")

    elif getType(obj) in ["Dimension", "LinearDimension"]:
        if gui:
            if not obj.ViewObject:
                print(
                    "export of dimensions to SVG is only available in GUI mode"
                )
            elif obj.ViewObject.Proxy:
                if hasattr(obj.ViewObject.Proxy, "p1"):
                    prx = obj.ViewObject.Proxy
                    ts = (len(prx.string) *
                          obj.ViewObject.FontSize.Value) / 4.0
                    rm = ((prx.p3.sub(prx.p2)).Length / 2.0) - ts
                    p2a = getProj(
                        prx.p2.add(
                            DraftVecUtils.scaleTo(prx.p3.sub(prx.p2), rm)),
                        plane)
                    p2b = getProj(
                        prx.p3.add(
                            DraftVecUtils.scaleTo(prx.p2.sub(prx.p3), rm)),
                        plane)
                    p1 = getProj(prx.p1, plane)
                    p2 = getProj(prx.p2, plane)
                    p3 = getProj(prx.p3, plane)
                    p4 = getProj(prx.p4, plane)
                    tbase = getProj(prx.tbase, plane)
                    r = prx.textpos.rotation.getValue().getValue()
                    rv = FreeCAD.Rotation(r[0], r[1], r[2], r[3]).multVec(
                        FreeCAD.Vector(1, 0, 0))
                    angle = -DraftVecUtils.angle(getProj(rv, plane))
                    #angle = -DraftVecUtils.angle(p3.sub(p2))

                    svg = ''
                    nolines = False
                    if hasattr(obj.ViewObject, "ShowLine"):
                        if not obj.ViewObject.ShowLine:
                            nolines = True

                    # drawing lines
                    if not nolines:
                        svg += '<path '
                    if obj.ViewObject.DisplayMode == "2D":
                        tangle = angle
                        if tangle > math.pi / 2:
                            tangle = tangle - math.pi
                        #elif (tangle <= -math.pi/2) or (tangle > math.pi/2):
                        #    tangle = tangle+math.pi
                        #tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2/scale,0),tangle))
                        if rotation != 0:
                            #print "dim: tangle:",tangle," rot: ",rotation," text: ",prx.string
                            if abs(tangle + math.radians(rotation)) < 0.0001:
                                tangle += math.pi
                                tbase = tbase.add(
                                    DraftVecUtils.rotate(
                                        Vector(0, 2 / scale, 0), tangle))
                        if not nolines:
                            svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' '
                            svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' '
                            svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' '
                            svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" '
                    else:
                        tangle = 0
                        if rotation != 0:
                            tangle = -math.radians(rotation)
                        tbase = tbase.add(Vector(0, -2.0 / scale, 0))
                        if not nolines:
                            svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' '
                            svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' '
                            svg += 'L ' + str(p2a.x) + ' ' + str(p2a.y) + ' '
                            svg += 'M ' + str(p2b.x) + ' ' + str(p2b.y) + ' '
                            svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' '
                            svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" '

                    if not nolines:
                        svg += 'fill="none" stroke="'
                        svg += stroke + '" '
                        svg += 'stroke-width="' + str(linewidth) + ' px" '
                        svg += 'style="stroke-width:' + str(linewidth)
                        svg += ';stroke-miterlimit:4;stroke-dasharray:none" '
                        svg += 'freecad:basepoint1="' + str(p1.x) + ' ' + str(
                            p1.y) + '" '
                        svg += 'freecad:basepoint2="' + str(p4.x) + ' ' + str(
                            p4.y) + '" '
                        svg += 'freecad:dimpoint="' + str(p2.x) + ' ' + str(
                            p2.y) + '"'
                        svg += '/>\n'

                        # drawing dimension and extension lines overshoots
                        if hasattr(obj.ViewObject, "DimOvershoot"
                                   ) and obj.ViewObject.DimOvershoot.Value:
                            shootsize = obj.ViewObject.DimOvershoot.Value / pointratio
                            svg += getOvershoot(p2, shootsize, stroke,
                                                linewidth, angle)
                            svg += getOvershoot(p3, shootsize, stroke,
                                                linewidth, angle + math.pi)
                        if hasattr(obj.ViewObject, "ExtOvershoot"
                                   ) and obj.ViewObject.ExtOvershoot.Value:
                            shootsize = obj.ViewObject.ExtOvershoot.Value / pointratio
                            shootangle = -DraftVecUtils.angle(p1.sub(p2))
                            svg += getOvershoot(p2, shootsize, stroke,
                                                linewidth, shootangle)
                            svg += getOvershoot(p3, shootsize, stroke,
                                                linewidth, shootangle)

                        # drawing arrows
                        if hasattr(obj.ViewObject, "ArrowType"):
                            arrowsize = obj.ViewObject.ArrowSize.Value / pointratio
                            if hasattr(obj.ViewObject, "FlipArrows"):
                                if obj.ViewObject.FlipArrows:
                                    angle = angle + math.pi
                            svg += getArrow(obj.ViewObject.ArrowType, p2,
                                            arrowsize, stroke, linewidth,
                                            angle)
                            svg += getArrow(obj.ViewObject.ArrowType, p3,
                                            arrowsize, stroke, linewidth,
                                            angle + math.pi)

                    # drawing text
                    svg += getText(stroke, fontsize, obj.ViewObject.FontName,
                                   tangle, tbase, prx.string)

    elif getType(obj) == "AngularDimension":
        if gui:
            if not obj.ViewObject:
                print(
                    "export of dimensions to SVG is only available in GUI mode"
                )
            elif obj.ViewObject.Proxy:
                if hasattr(obj.ViewObject.Proxy, "circle"):
                    prx = obj.ViewObject.Proxy

                    # drawing arc
                    fill = "none"
                    if obj.ViewObject.DisplayMode == "2D":
                        svg += getPath([prx.circle])
                    else:
                        if hasattr(prx, "circle1"):
                            svg += getPath([prx.circle1])
                            svg += getPath([prx.circle2])
                        else:
                            svg += getPath([prx.circle])

                    # drawing arrows
                    if hasattr(obj.ViewObject, "ArrowType"):
                        p2 = getProj(prx.p2, plane)
                        p3 = getProj(prx.p3, plane)
                        arrowsize = obj.ViewObject.ArrowSize.Value / pointratio
                        arrowlength = 4 * obj.ViewObject.ArrowSize.Value
                        u1 = getProj(
                            (prx.circle.valueAt(prx.circle.FirstParameter +
                                                arrowlength)
                             ).sub(
                                 prx.circle.valueAt(
                                     prx.circle.FirstParameter)), plane)
                        u2 = getProj(
                            (prx.circle.valueAt(prx.circle.LastParameter -
                                                arrowlength)
                             ).sub(prx.circle.valueAt(
                                 prx.circle.LastParameter)), plane)
                        angle1 = -DraftVecUtils.angle(u1)
                        angle2 = -DraftVecUtils.angle(u2)
                        if hasattr(obj.ViewObject, "FlipArrows"):
                            if obj.ViewObject.FlipArrows:
                                angle1 = angle1 + math.pi
                                angle2 = angle2 + math.pi
                        svg += getArrow(obj.ViewObject.ArrowType, p2,
                                        arrowsize, stroke, linewidth, angle1)
                        svg += getArrow(obj.ViewObject.ArrowType, p3,
                                        arrowsize, stroke, linewidth, angle2)

                    # drawing text
                    if obj.ViewObject.DisplayMode == "2D":
                        t = prx.circle.tangentAt(prx.circle.FirstParameter +
                                                 (prx.circle.LastParameter -
                                                  prx.circle.FirstParameter) /
                                                 2.0)
                        t = getProj(t, plane)
                        tangle = DraftVecUtils.angle(t)
                        if (tangle <= -math.pi / 2) or (tangle > math.pi / 2):
                            tangle = tangle + math.pi
                        tbase = getProj(
                            prx.circle.valueAt(prx.circle.FirstParameter +
                                               (prx.circle.LastParameter -
                                                prx.circle.FirstParameter) /
                                               2.0), plane)
                        tbase = tbase.add(
                            DraftVecUtils.rotate(Vector(0, 2.0 / scale, 0),
                                                 tangle))
                        #print(tbase)
                    else:
                        tangle = 0
                        tbase = getProj(prx.tbase, plane)
                    svg += getText(stroke, fontsize, obj.ViewObject.FontName,
                                   tangle, tbase, prx.string)

    elif getType(obj) == "Label":
        if getattr(obj.ViewObject, "Line",
                   True):  # some Labels may have no Line property

            def format_point(coords, action='L'):
                return "{action}{x},{y}".format(x=coords.x,
                                                y=coords.y,
                                                action=action)

            # Draw multisegment line
            proj_points = list(map(lambda x: getProj(x, plane), obj.Points))
            path_dir_list = [format_point(proj_points[0], action='M')]
            path_dir_list += map(format_point, proj_points[1:])
            path_dir_str = " ".join(path_dir_list)
            svg_path = '<path fill="none" stroke="{stroke}" stroke-width="{linewidth}" d="{directions}"/>'.format(
                stroke=stroke, linewidth=linewidth, directions=path_dir_str)
            svg += svg_path

            # Draw arrow.
            # We are different here from 3D view
            # if Line is set to 'off', no arrow is drawn
            if hasattr(obj.ViewObject, "ArrowType") and len(obj.Points) >= 2:
                last_segment = FreeCAD.Vector(obj.Points[-1] - obj.Points[-2])
                angle = -DraftVecUtils.angle(getProj(last_segment,
                                                     plane)) + math.pi
                svg += getArrow(arrowtype=obj.ViewObject.ArrowType,
                                point=proj_points[-1],
                                arrowsize=obj.ViewObject.ArrowSize.Value /
                                pointratio,
                                color=stroke,
                                linewidth=linewidth,
                                angle=angle)

        # print text
        if gui:
            if not obj.ViewObject:
                print("export of texts to SVG is only available in GUI mode")
            else:
                fontname = obj.ViewObject.TextFont
                position = getProj(obj.Placement.Base, plane)
                rotation = obj.Placement.Rotation
                justification = obj.ViewObject.TextAlignment
                text = obj.Text
                svg += getText(stroke, fontsize, fontname, rotation, position,
                               text, linespacing, justification)

    elif getType(obj) in ["Annotation", "DraftText"]:
        "returns an svg representation of a document annotation"
        if gui:
            if not obj.ViewObject:
                print("export of texts to SVG is only available in GUI mode")
            else:
                n = obj.ViewObject.FontName
                if getType(obj) == "Annotation":
                    p = getProj(obj.Position, plane)
                    r = obj.ViewObject.Rotation.getValueAs("rad")
                    t = obj.LabelText
                else:  # DraftText
                    p = getProj(obj.Placement.Base, plane)
                    r = obj.Placement.Rotation
                    t = obj.Text
                j = obj.ViewObject.Justification
                svg += getText(stroke, fontsize, n, r, p, t, linespacing, j)

    elif getType(obj) == "Axis":
        "returns the SVG representation of an Arch Axis system"
        if gui:
            if not obj.ViewObject:
                print("export of axes to SVG is only available in GUI mode")
            else:
                vobj = obj.ViewObject
                lorig = lstyle
                fill = 'none'
                rad = vobj.BubbleSize.Value / 2
                n = 0
                for e in obj.Shape.Edges:
                    lstyle = lorig
                    svg += getPath([e])
                    lstyle = "none"
                    pos = ["Start"]
                    if hasattr(vobj, "BubblePosition"):
                        if vobj.BubblePosition == "Both":
                            pos = ["Start", "End"]
                        else:
                            pos = [vobj.BubblePosition]
                    for p in pos:
                        if p == "Start":
                            p1 = e.Vertexes[0].Point
                            p2 = e.Vertexes[1].Point
                        else:
                            p1 = e.Vertexes[1].Point
                            p2 = e.Vertexes[0].Point
                        dv = p2.sub(p1)
                        dv.normalize()
                        center = p2.add(dv.scale(rad, rad, rad))
                        svg += getCircle(Part.makeCircle(rad, center))
                        if hasattr(vobj.Proxy, "bubbletexts"):
                            if len(vobj.Proxy.bubbletexts) >= n:
                                svg += '<text fill="' + stroke + '" '
                                svg += 'font-size="' + str(rad) + '" '
                                svg += 'style="text-anchor:middle;'
                                svg += 'text-align:center;'
                                svg += 'font-family: sans;" '
                                svg += 'transform="translate(' + str(
                                    center.x +
                                    rad / 4.0) + ',' + str(center.y -
                                                           rad / 3.0) + ') '
                                svg += 'scale(1,-1)"> '
                                svg += '<tspan>' + obj.ViewObject.Proxy.bubbletexts[
                                    n].string.getValues()[0] + '</tspan>\n'
                                svg += '</text>\n'
                                n += 1
                lstyle = lorig

    elif getType(obj) == "Pipe":
        fill = stroke
        if obj.Base and obj.Diameter:
            svg += getPath(obj.Base.Shape.Edges)
        for f in obj.Shape.Faces:
            if len(f.Edges) == 1:
                if isinstance(f.Edges[0].Curve, Part.Circle):
                    svg += getCircle(f.Edges[0])

    elif getType(obj) == "Rebar":
        fill = "none"
        if obj.Proxy:
            if not hasattr(obj.Proxy, "wires"):
                obj.Proxy.execute(obj)
            if hasattr(obj.Proxy, "wires"):
                svg += getPath(wires=obj.Proxy.wires)

    elif getType(obj) == "PipeConnector":
        pass

    elif getType(obj) == "Space":
        "returns an SVG fragment for the text of a space"
        if gui:
            if not obj.ViewObject:
                print("export of spaces to SVG is only available in GUI mode")
            else:
                if fillSpaces:
                    if hasattr(obj, "Proxy"):
                        if not hasattr(obj.Proxy, "face"):
                            obj.Proxy.getArea(obj, notouch=True)
                        if hasattr(obj.Proxy, "face"):
                            # setting fill
                            if gui:
                                fill = getrgb(obj.ViewObject.ShapeColor,
                                              testbw=False)
                                fill_opacity = 1 - (
                                    obj.ViewObject.Transparency / 100.0)
                            else:
                                fill = "#888888"
                            svg += getPath(wires=[obj.Proxy.face.OuterWire])
                c = getrgb(obj.ViewObject.TextColor)
                n = obj.ViewObject.FontName
                a = 0
                if rotation != 0:
                    a = math.radians(rotation)
                t1 = obj.ViewObject.Proxy.text1.string.getValues()
                t2 = obj.ViewObject.Proxy.text2.string.getValues()
                scale = obj.ViewObject.FirstLine.Value / obj.ViewObject.FontSize.Value
                f1 = fontsize * scale
                p2 = obj.Placement.multVec(
                    FreeCAD.Vector(obj.ViewObject.Proxy.coords.translation.
                                   getValue().getValue()))
                lspc = FreeCAD.Vector(obj.ViewObject.Proxy.header.translation.
                                      getValue().getValue())
                p1 = p2.add(lspc)
                j = obj.ViewObject.TextAlign
                t3 = getText(c,
                             f1,
                             n,
                             a,
                             getProj(p1, plane),
                             t1,
                             linespacing,
                             j,
                             flip=True)
                svg += t3
                if t2:
                    ofs = FreeCAD.Vector(0, -lspc.Length, 0)
                    if a:
                        ofs = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1),
                                               -rotation).multVec(ofs)
                    t4 = getText(c,
                                 fontsize,
                                 n,
                                 a,
                                 getProj(p1, plane).add(ofs),
                                 t2,
                                 linespacing,
                                 j,
                                 flip=True)
                    svg += t4

    elif obj.isDerivedFrom('Part::Feature'):
        if obj.Shape.isNull():
            return ''
        # setting fill
        if obj.Shape.Faces:
            if gui:
                try:
                    m = obj.ViewObject.DisplayMode
                except AttributeError:
                    m = None
                if (m != "Wireframe"):
                    if fillstyle == "shape color":
                        fill = getrgb(obj.ViewObject.ShapeColor, testbw=False)
                        fill_opacity = 1 - (obj.ViewObject.Transparency /
                                            100.0)
                    else:
                        fill = 'url(#' + fillstyle + ')'
                        svg += getPattern(fillstyle)
                else:
                    fill = "none"
            else:
                fill = "#888888"
        else:
            fill = 'none'

        if len(obj.Shape.Vertexes) > 1:
            wiredEdges = []
            if obj.Shape.Faces:
                for i, f in enumerate(obj.Shape.Faces):
                    # place outer wire first
                    wires = [f.OuterWire]
                    wires.extend([
                        w for w in f.Wires
                        if w.hashCode() != f.OuterWire.hashCode()
                    ])
                    svg += getPath(wires=f.Wires,pathname='%s_f%04d' % \
                            (obj.Name,i))
                    wiredEdges.extend(f.Edges)
            else:
                for i, w in enumerate(obj.Shape.Wires):
                    svg += getPath(w.Edges,pathname='%s_w%04d' % \
                            (obj.Name,i))
                    wiredEdges.extend(w.Edges)
            if len(wiredEdges) != len(obj.Shape.Edges):
                for i, e in enumerate(obj.Shape.Edges):
                    if (DraftGeomUtils.findEdge(e, wiredEdges) is None):
                        svg += getPath([e],pathname='%s_nwe%04d' % \
                                (obj.Name,i))
        else:
            # closed circle or spline
            if obj.Shape.Edges:
                if isinstance(obj.Shape.Edges[0].Curve, Part.Circle):
                    svg = getCircle(obj.Shape.Edges[0])
                else:
                    svg = getPath(obj.Shape.Edges)
        if FreeCAD.GuiUp:
            if hasattr(obj.ViewObject, "EndArrow") and hasattr(
                    obj.ViewObject,
                    "ArrowType") and (len(obj.Shape.Vertexes) > 1):
                if obj.ViewObject.EndArrow:
                    p1 = getProj(obj.Shape.Vertexes[-1].Point, plane)
                    p2 = getProj(obj.Shape.Vertexes[-2].Point, plane)
                    angle = -DraftVecUtils.angle(p2.sub(p1))
                    arrowsize = obj.ViewObject.ArrowSize.Value / pointratio
                    svg += getArrow(obj.ViewObject.ArrowType, p1, arrowsize,
                                    stroke, linewidth, angle)

    # techdraw expects bottom-to-top coordinates
    if techdraw:
        svg = '<g transform ="scale(1,-1)">\n    ' + svg + '</g>\n'
    return svg
Ejemplo n.º 45
0
    def cut(self,cutplane):
        "Cuts through the shapes with a given cut plane and builds section faces"
        if DEBUG: print "\n\n======> Starting cut\n\n"
        if self.iscut:
            return
        if not self.shapes:
            if DEBUG: print "No objects to make sections"
        else:
            fill = (1.0,1.0,1.0,1.0)
            placement = FreeCAD.Placement(cutplane.Placement)

            # building boundbox
            bb = self.shapes[0][0].BoundBox 
            for sh in self.shapes[1:]:
                bb.add(sh[0].BoundBox)
            bb.enlarge(1)
            um = vm = wm = 0
            if not bb.isCutPlane(placement.Base,self.wp.axis):
                if DEBUG: print "No objects are cut by the plane"
            else:
                corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
                           FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin),
                           FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMin),
                           FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMin),
                           FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMax),
                           FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMax),
                           FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax),
                           FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)]
                for c in corners:
                    dv = c.sub(placement.Base)
                    um1 = DraftVecUtils.project(dv,self.wp.u).Length
                    um = max(um,um1)
                    vm1 = DraftVecUtils.project(dv,self.wp.v).Length
                    vm = max(vm,vm1)
                    wm1 = DraftVecUtils.project(dv,self.wp.axis).Length
                    wm = max(wm,wm1)
                p1 = FreeCAD.Vector(-um,vm,0)
                p2 = FreeCAD.Vector(um,vm,0)
                p3 = FreeCAD.Vector(um,-vm,0)
                p4 = FreeCAD.Vector(-um,-vm,0)
                cutface = Part.makePolygon([p1,p2,p3,p4,p1])
                cutface = Part.Face(cutface)
                cutface.Placement = placement
                cutnormal = DraftVecUtils.scaleTo(self.wp.axis,wm)
                cutvolume = cutface.extrude(cutnormal)
                shapes = []
                faces = []
                sections = []
                for sh in self.shapes:
                    for sol in sh[0].Solids:
                        c = sol.cut(cutvolume)
                        shapes.append([c]+sh[1:])
                        for f in c.Faces:
                            faces.append([f]+sh[1:])
                            print "iscoplanar:",f.Vertexes[0].Point,f.normalAt(0,0),cutface.Vertexes[0].Point,cutface.normalAt(0,0)
                            if DraftGeomUtils.isCoplanar([f,cutface]):
                                print "COPLANAR"
                                sections.append([f,fill])
                self.shapes = shapes
                self.faces = faces
                self.sections = sections
                if DEBUG: print "Built ",len(self.sections)," sections, ", len(self.faces), " faces retained"
                self.iscut = True
                self.oriented = False
                self.trimmed = False
                self.sorted = False
                self.joined = False
        if DEBUG: print "\n\n======> Finished cut\n\n"
Ejemplo n.º 46
0
    def execute(self,obj):
        if len(obj.InList) != 1:
            return
        if Draft.getType(obj.InList[0]) != "Structure":
            return
        if not obj.InList[0].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.InList[0]
        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj,"Rounding"):
            #print obj.Rounding
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire,radius)
        bpoint, bvec = self.getBaseAndAxis(obj)
        if not bpoint:
            return
        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) #.normalize()
                # don't normalize so the vector can also be used to determine the distance
                size = axis.Length
        #print axis
        #print size
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return

        # all tests ok!
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value/2,bpoint,bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle],True,False,2)
        except:
            print "Arch: error sweeping rebar profile along the base sketch"
            return
        # building final shape
        shapes = []
        if obj.Amount == 1:
            offset = DraftVecUtils.scaleTo(axis,size/2)
            bar.translate(offset)
            shapes.append(bar)
            if hasattr(obj,"Spacing"):
                obj.Spacing = 0
        else:
            if obj.OffsetStart.Value:
                baseoffset = DraftVecUtils.scaleTo(axis,obj.OffsetStart.Value)
            else:
                baseoffset = None
            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:
                        bar.translate(baseoffset)
                    shapes.append(bar)
                else:
                    bar = bar.copy()
                    bar.translate(vinterval)
                    shapes.append(bar)
            if hasattr(obj,"Spacing"):
                obj.Spacing = interval
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
Ejemplo n.º 47
0
    def execute(self, obj):
        "creates the panel shape"

        import Part, DraftGeomUtils

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

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if obj.Base:
            p = FreeCAD.Placement(obj.Base.Placement)
            normal = p.Rotation.multVec(Vector(0, 0, 1))
            normal = normal.multiply(thickness)
            base = obj.Base.Shape.copy()
            if base.Solids:
                pass
            elif base.Faces:
                self.BaseProfile = base
                self.ExtrusionVector = normal
                base = base.extrude(normal)
            elif base.Wires:
                closed = True
                for w in base.Wires:
                    if not w.isClosed():
                        closed = False
                if closed:
                    base = ArchCommands.makeFace(base.Wires)
                    self.BaseProfile = base
                    self.ExtrusionVector = normal
                    base = base.extrude(normal)
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if obj.Base.Mesh.isSolid():
                    if obj.Base.Mesh.countComponents() == 1:
                        sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                        if sh.isClosed() and sh.isValid() and sh.Solids:
                            base = sh
        else:
            normal = Vector(0, 0, 1).multiply(thickness)
            self.ExtrusionVector = normal
            l2 = length / 2 or 0.5
            w2 = width / 2 or 0.5
            v1 = Vector(-l2, -w2, 0)
            v2 = Vector(l2, -w2, 0)
            v3 = Vector(l2, w2, 0)
            v4 = Vector(-l2, w2, 0)
            base = Part.makePolygon([v1, v2, v3, v4, v1])
            base = Part.Face(base)
            self.BaseProfile = base
            base = base.extrude(self.ExtrusionVector)

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

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

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

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(
                            translate("Arch", "Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Ejemplo n.º 48
0
    def getProfiles(self, obj, noplacement=False):
        "Returns the base profile(s) of this component, if applicable"
        wires = []
        if Draft.getType(obj) == "Precast":
            return wires
        n, l, w, h = self.getDefaultValues(obj)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Extrusion"):
                if obj.Base.Base:
                    base = obj.Base.Base.Shape.copy()
                    #if noplacement:
                    #    base.Placement = FreeCAD.Placement()
                    return [base]
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    base = obj.Base.Shape.copy()
                    if noplacement:
                        base.Placement = FreeCAD.Placement()
                    if not base.Solids:
                        if base.Faces:
                            import DraftGeomUtils
                            if not DraftGeomUtils.isCoplanar(base.Faces):
                                return []
                            return [base]

                        basewires = []
                        if not base.Wires:
                            if len(base.Edges) == 1:
                                import Part
                                basewires = [Part.Wire(base.Edges)]
                        else:
                            basewires = base.Wires
                        if basewires:
                            import DraftGeomUtils, DraftVecUtils, Part
                            for wire in basewires:
                                e = wire.Edges[0]
                                if isinstance(e.Curve, Part.Circle):
                                    dvec = e.Vertexes[0].Point.sub(
                                        e.Curve.Center)
                                else:
                                    dvec = DraftGeomUtils.vec(
                                        wire.Edges[0]).cross(n)
                                if not DraftVecUtils.isNull(dvec):
                                    dvec.normalize()
                                sh = None
                                if hasattr(obj, "Align"):
                                    if obj.Align == "Left":
                                        dvec.multiply(w)
                                        if hasattr(obj, "Offset"):
                                            if obj.Offset.Value:
                                                dvec2 = DraftVecUtils.scaleTo(
                                                    dvec, obj.Offset.Value)
                                                wire = DraftGeomUtils.offsetWire(
                                                    wire, dvec2)
                                        w2 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        w1 = Part.Wire(
                                            Part.__sortEdges__(wire.Edges))
                                        sh = DraftGeomUtils.bind(w1, w2)
                                    elif obj.Align == "Right":
                                        dvec.multiply(w)
                                        dvec = dvec.negative()
                                        if hasattr(obj, "Offset"):
                                            if obj.Offset.Value:
                                                dvec2 = DraftVecUtils.scaleTo(
                                                    dvec, obj.Offset.Value)
                                                wire = DraftGeomUtils.offsetWire(
                                                    wire, dvec2)
                                        w2 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        w1 = Part.Wire(
                                            Part.__sortEdges__(wire.Edges))
                                        sh = DraftGeomUtils.bind(w1, w2)
                                    elif obj.Align == "Center":
                                        dvec.multiply(w / 2)
                                        w1 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        dvec = dvec.negative()
                                        w2 = DraftGeomUtils.offsetWire(
                                            wire, dvec)
                                        sh = DraftGeomUtils.bind(w1, w2)
                                    if sh:
                                        wires.append(sh)
                                else:
                                    wires.append(wire)
        elif Draft.getType(obj) in ["Wall", "Structure"]:
            if (Draft.getType(obj) == "Structure") and (l > h):
                if noplacement:
                    h2 = h / 2 or 0.5
                    w2 = w / 2 or 0.5
                    v1 = Vector(-h2, -w2, 0)
                    v2 = Vector(h2, -w2, 0)
                    v3 = Vector(h2, w2, 0)
                    v4 = Vector(-h2, w2, 0)
                else:
                    h2 = h / 2 or 0.5
                    w2 = w / 2 or 0.5
                    v1 = Vector(0, -w2, -h2)
                    v2 = Vector(0, -w2, h2)
                    v3 = Vector(0, w2, h2)
                    v4 = Vector(0, w2, -h2)
            else:
                l2 = l / 2 or 0.5
                w2 = w / 2 or 0.5
                v1 = Vector(-l2, -w2, 0)
                v2 = Vector(l2, -w2, 0)
                v3 = Vector(l2, w2, 0)
                v4 = Vector(-l2, w2, 0)
            import Part
            base = Part.makePolygon([v1, v2, v3, v4, v1])
            return [base]
        return wires
Ejemplo n.º 49
0
    def execute(self, obj):
        import Part
        plm = obj.Placement
        if obj.Base and (not obj.Tool):
            if obj.Base.isDerivedFrom("Sketcher::SketchObject"):
                shape = obj.Base.Shape.copy()
                if obj.Base.Shape.isClosed():
                    if hasattr(obj, "MakeFace"):
                        if obj.MakeFace:
                            shape = Part.Face(shape)
                    else:
                        shape = Part.Face(shape)
                obj.Shape = shape
        elif obj.Base and obj.Tool:
            if hasattr(obj.Base, 'Shape') and hasattr(obj.Tool, 'Shape'):
                if (not obj.Base.Shape.isNull()) and (
                        not obj.Tool.Shape.isNull()):
                    sh1 = obj.Base.Shape.copy()
                    sh2 = obj.Tool.Shape.copy()
                    shape = sh1.fuse(sh2)
                    if DraftGeomUtils.isCoplanar(shape.Faces):
                        shape = DraftGeomUtils.concatenate(shape)
                        obj.Shape = shape
                        p = []
                        for v in shape.Vertexes:
                            p.append(v.Point)
                        if obj.Points != p: obj.Points = p
        elif obj.Points:
            if obj.Points[0] == obj.Points[-1]:
                if not obj.Closed: obj.Closed = True
                obj.Points.pop()
            if obj.Closed and (len(obj.Points) > 2):
                pts = obj.Points
                if hasattr(obj, "Subdivisions"):
                    if obj.Subdivisions > 0:
                        npts = []
                        for i in range(len(pts)):
                            p1 = pts[i]
                            npts.append(pts[i])
                            if i == len(pts) - 1:
                                p2 = pts[0]
                            else:
                                p2 = pts[i + 1]
                            v = p2.sub(p1)
                            v = DraftVecUtils.scaleTo(
                                v, v.Length / (obj.Subdivisions + 1))
                            for j in range(obj.Subdivisions):
                                npts.append(
                                    p1.add(App.Vector(v).multiply(j + 1)))
                        pts = npts
                shape = Part.makePolygon(pts + [pts[0]])
                if "ChamferSize" in obj.PropertiesList:
                    if obj.ChamferSize.Value != 0:
                        w = DraftGeomUtils.filletWire(shape,
                                                      obj.ChamferSize.Value,
                                                      chamfer=True)
                        if w:
                            shape = w
                if "FilletRadius" in obj.PropertiesList:
                    if obj.FilletRadius.Value != 0:
                        w = DraftGeomUtils.filletWire(shape,
                                                      obj.FilletRadius.Value)
                        if w:
                            shape = w
                try:
                    if hasattr(obj, "MakeFace"):
                        if obj.MakeFace:
                            shape = Part.Face(shape)
                    else:
                        shape = Part.Face(shape)
                except Part.OCCError:
                    pass
            else:
                edges = []
                pts = obj.Points[1:]
                lp = obj.Points[0]
                for p in pts:
                    if not DraftVecUtils.equals(lp, p):
                        if hasattr(obj, "Subdivisions"):
                            if obj.Subdivisions > 0:
                                npts = []
                                v = p.sub(lp)
                                v = DraftVecUtils.scaleTo(
                                    v, v.Length / (obj.Subdivisions + 1))
                                edges.append(
                                    Part.LineSegment(lp, lp.add(v)).toShape())
                                lv = lp.add(v)
                                for j in range(obj.Subdivisions):
                                    edges.append(
                                        Part.LineSegment(lv,
                                                         lv.add(v)).toShape())
                                    lv = lv.add(v)
                            else:
                                edges.append(Part.LineSegment(lp, p).toShape())
                        else:
                            edges.append(Part.LineSegment(lp, p).toShape())
                        lp = p
                try:
                    shape = Part.Wire(edges)
                except Part.OCCError:
                    print("Error wiring edges")
                    shape = None
                if "ChamferSize" in obj.PropertiesList:
                    if obj.ChamferSize.Value != 0:
                        w = DraftGeomUtils.filletWire(shape,
                                                      obj.ChamferSize.Value,
                                                      chamfer=True)
                        if w:
                            shape = w
                if "FilletRadius" in obj.PropertiesList:
                    if obj.FilletRadius.Value != 0:
                        w = DraftGeomUtils.filletWire(shape,
                                                      obj.FilletRadius.Value)
                        if w:
                            shape = w
            if shape:
                obj.Shape = shape
                if hasattr(obj, "Area") and hasattr(shape, "Area"):
                    obj.Area = shape.Area
                if hasattr(obj, "Length"):
                    obj.Length = shape.Length

        obj.Placement = plm
        obj.positionBySupport()
        self.onChanged(obj, "Placement")
Ejemplo n.º 50
0
    def updateData(self, obj, prop):
        if hasattr(self, "arc"):
            from pivy import coin
            import Part, DraftGeomUtils
            import DraftGui
            arcsegs = 24

            # calculate the arc data
            if DraftVecUtils.isNull(obj.Normal):
                norm = App.Vector(0, 0, 1)
            else:
                norm = obj.Normal
            radius = (obj.Dimline.sub(obj.Center)).Length
            self.circle = Part.makeCircle(radius, obj.Center, norm,
                                          obj.FirstAngle.Value,
                                          obj.LastAngle.Value)
            self.p2 = self.circle.Vertexes[0].Point
            self.p3 = self.circle.Vertexes[-1].Point
            mp = DraftGeomUtils.findMidpoint(self.circle.Edges[0])
            ray = mp.sub(obj.Center)

            # set text value
            if obj.LastAngle.Value > obj.FirstAngle.Value:
                a = obj.LastAngle.Value - obj.FirstAngle.Value
            else:
                a = (360 - obj.FirstAngle.Value) + obj.LastAngle.Value
            su = True
            if hasattr(obj.ViewObject, "ShowUnit"):
                su = obj.ViewObject.ShowUnit
            if hasattr(obj.ViewObject, "Decimals"):
                self.string = DraftGui.displayExternal(a,
                                                       obj.ViewObject.Decimals,
                                                       'Angle', su)
            else:
                self.string = DraftGui.displayExternal(a, None, 'Angle', su)
            if obj.ViewObject.Override:
                self.string = obj.ViewObject.Override.replace("$dim",\
                    self.string)
            self.text.string = self.text3d.string = utils.string_encode_coin(
                self.string)

            # check display mode
            try:
                m = obj.ViewObject.DisplayMode
            except:  # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
                m = ["2D", "3D"][utils.get_param("dimstyle", 0)]

            # set the arc
            if m == "3D":
                # calculate the spacing of the text
                spacing = (len(self.string) *
                           obj.ViewObject.FontSize.Value) / 8.0
                pts1 = []
                cut = None
                pts2 = []
                for i in range(arcsegs + 1):
                    p = self.circle.valueAt(self.circle.FirstParameter + (
                        (self.circle.LastParameter -
                         self.circle.FirstParameter) / arcsegs) * i)
                    if (p.sub(mp)).Length <= spacing:
                        if cut is None:
                            cut = i
                    else:
                        if cut is None:
                            pts1.append([p.x, p.y, p.z])
                        else:
                            pts2.append([p.x, p.y, p.z])
                self.coords.point.setValues(pts1 + pts2)
                i1 = len(pts1)
                i2 = i1 + len(pts2)
                self.arc.coordIndex.setValues(
                    0,
                    len(pts1) + len(pts2) + 1,
                    list(range(len(pts1))) + [-1] + list(range(i1, i2)))
                if (len(pts1) >= 3) and (len(pts2) >= 3):
                    self.circle1 = Part.Arc(
                        App.Vector(pts1[0][0], pts1[0][1], pts1[0][2]),
                        App.Vector(pts1[1][0], pts1[1][1], pts1[1][2]),
                        App.Vector(pts1[-1][0], pts1[-1][1],
                                   pts1[-1][2])).toShape()
                    self.circle2 = Part.Arc(
                        App.Vector(pts2[0][0], pts2[0][1], pts2[0][2]),
                        App.Vector(pts2[1][0], pts2[1][1], pts2[1][2]),
                        App.Vector(pts2[-1][0], pts2[-1][1],
                                   pts2[-1][2])).toShape()
            else:
                pts = []
                for i in range(arcsegs + 1):
                    p = self.circle.valueAt(self.circle.FirstParameter + (
                        (self.circle.LastParameter -
                         self.circle.FirstParameter) / arcsegs) * i)
                    pts.append([p.x, p.y, p.z])
                self.coords.point.setValues(pts)
                self.arc.coordIndex.setValues(0, arcsegs + 1,
                                              list(range(arcsegs + 1)))

            # set the arrow coords and rotation
            self.trans1.translation.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.coord1.point.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.trans2.translation.setValue((self.p3.x, self.p3.y, self.p3.z))
            self.coord2.point.setValue((self.p3.x, self.p3.y, self.p3.z))
            # calculate small chords to make arrows look better
            arrowlength = 4 * obj.ViewObject.ArrowSize.Value
            u1 = (self.circle.valueAt(self.circle.FirstParameter + arrowlength)
                  ).sub(self.circle.valueAt(
                      self.circle.FirstParameter)).normalize()
            u2 = (self.circle.valueAt(self.circle.LastParameter)).sub(
                self.circle.valueAt(self.circle.LastParameter -
                                    arrowlength)).normalize()
            if hasattr(obj.ViewObject, "FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u1 = u1.negative()
                    u2 = u2.negative()
            w2 = self.circle.Curve.Axis
            w1 = w2.negative()
            v1 = w1.cross(u1)
            v2 = w2.cross(u2)
            q1 = App.Placement(DraftVecUtils.getPlaneRotation(u1, v1,
                                                              w1)).Rotation.Q
            q2 = App.Placement(DraftVecUtils.getPlaneRotation(u2, v2,
                                                              w2)).Rotation.Q
            self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3]))
            self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3]))

            # setting text pos & rot
            self.tbase = mp
            if hasattr(obj.ViewObject, "TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition

            u3 = ray.cross(norm).normalize()
            v3 = norm.cross(u3)
            r = App.Placement(DraftVecUtils.getPlaneRotation(u3, v3,
                                                             norm)).Rotation
            offset = r.multVec(App.Vector(0, 1, 0))

            if hasattr(obj.ViewObject, "TextSpacing"):
                offset = DraftVecUtils.scaleTo(
                    offset, obj.ViewObject.TextSpacing.Value)
            else:
                offset = DraftVecUtils.scaleTo(offset, 0.05)
            if m == "3D":
                offset = offset.negative()
            self.tbase = self.tbase.add(offset)
            q = r.Q
            self.textpos.translation.setValue(
                [self.tbase.x, self.tbase.y, self.tbase.z])
            self.textpos.rotation = coin.SbRotation(q[0], q[1], q[2], q[3])

            # set the angle property
            if round(obj.Angle, utils.precision()) != round(
                    a, utils.precision()):
                obj.Angle = a
Ejemplo n.º 51
0
    def getExtrusionData(self,obj):

        """returns (shape,extrusion vector,placement) or None"""
        import Part,DraftGeomUtils
        data = ArchComponent.Component.getExtrusionData(self,obj)
        if data:
            if not isinstance(data[0],list):
                # multifuses not considered here
                return data
        length  = obj.Length.Value
        width = obj.Width.Value
        height = obj.Height.Value
        if not height:
            for p in obj.InList:
                if Draft.getType(p) in ["Floor","BuildingPart"]:
                    if p.Height.Value:
                        height = p.Height.Value
        if not height:
            return None
        if obj.Normal == Vector(0,0,0):
            normal = Vector(0,0,1)
        else:
            normal = Vector(obj.Normal)
        base = None
        placement = None
        self.basewires = None
        # build wall layers
        layers = []
        if hasattr(obj,"Material"):
            if obj.Material:
                if hasattr(obj.Material,"Materials"):
                    varwidth = 0
                    restwidth = width - sum(obj.Material.Thicknesses)
                    if restwidth > 0:
                        varwidth = [t for t in obj.Material.Thicknesses if t == 0]
                        if varwidth:
                            varwidth = restwidth/len(varwidth)
                    for t in obj.Material.Thicknesses:
                        if t:
                            layers.append(t)
                        elif varwidth:
                            layers.append(varwidth)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        return None
                    elif obj.Face > 0:
                        if len(obj.Base.Shape.Faces) >= obj.Face:
                            face = obj.Base.Shape.Faces[obj.Face-1]
                            # this wall is based on a specific face of its base object
                            normal = face.normalAt(0,0)
                            if normal.getAngle(Vector(0,0,1)) > math.pi/4:
                                normal.multiply(width)
                                base = face.extrude(normal)
                                if obj.Align == "Center":
                                    base.translate(normal.negative().multiply(0.5))
                                elif obj.Align == "Right":
                                    base.translate(normal.negative())
                            else:
                                normal.multiply(height)
                                base = face.extrude(normal)
                            base,placement = self.rebase(base)
                            return (base,normal,placement)
                    elif obj.Base.Shape.Faces:
                        if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                            return None
                        else:
                            base,placement = self.rebase(obj.Base.Shape)
                    elif len(obj.Base.Shape.Edges) == 1:
                        self.basewires = [Part.Wire(obj.Base.Shape.Edges)]
                    else:
                        # self.basewires = obj.Base.Shape.Wires
                        self.basewires = []
                        for cluster in Part.getSortedClusters(obj.Base.Shape.Edges):
                            for c in Part.sortEdges(cluster):
                                self.basewires.append(Part.Wire(c))

                    if self.basewires and width:
                        if (len(self.basewires) == 1) and layers:
                            self.basewires = [self.basewires[0] for l in layers]
                        layeroffset = 0
                        baseface = None
                        for i,wire in enumerate(self.basewires):
                            e = wire.Edges[0]
                            if isinstance(e.Curve,Part.Circle):
                                dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                            else:
                                dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                            if not DraftVecUtils.isNull(dvec):
                                dvec.normalize()
                            sh = None
                            if obj.Align == "Left":
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Right":
                                dvec = dvec.negative()
                                off = obj.Offset.Value
                                if layers:
                                    off = off+layeroffset
                                    dvec.multiply(layers[i])
                                    layeroffset += layers[i]
                                else:
                                    dvec.multiply(width)
                                if off:
                                    dvec2 = DraftVecUtils.scaleTo(dvec,off)
                                    wire = DraftGeomUtils.offsetWire(wire,dvec2)
                                w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                                sh = DraftGeomUtils.bind(w1,w2)
                            elif obj.Align == "Center":
                                if layers:
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w1 = DraftGeomUtils.offsetWire(wire,d1)
                                    layeroffset += layers[i]
                                    off = width/2-layeroffset
                                    d1 = Vector(dvec).multiply(off)
                                    w2 = DraftGeomUtils.offsetWire(wire,d1)
                                else:
                                    dvec.multiply(width/2)
                                    w1 = DraftGeomUtils.offsetWire(wire,dvec)
                                    dvec = dvec.negative()
                                    w2 = DraftGeomUtils.offsetWire(wire,dvec)
                                sh = DraftGeomUtils.bind(w1,w2)
                            if sh:
                                sh.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(sh)
                                if baseface:
                                    if layers:
                                        baseface.append(f)
                                    else:
                                        baseface = baseface.fuse(f)
                                        # baseface = baseface.removeSplitter()
                                        s = DraftGeomUtils.removeSplitter(baseface)
                                        if s:
                                            baseface = s
                                else:
                                    if layers:
                                        baseface = [f]
                                    else:
                                        baseface = f
                        if baseface:
                            base,placement = self.rebase(baseface)
        else:
            if layers:
                totalwidth = sum(layers)
                offset = 0
                base = []
                for l in layers:
                    l2 = length/2 or 0.5
                    w1 = -totalwidth/2 + offset
                    w2 = w1 + l
                    v1 = Vector(-l2,w1,0)
                    v2 = Vector(l2,w1,0)
                    v3 = Vector(l2,w2,0)
                    v4 = Vector(-l2,w2,0)
                    base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])))
                    offset += l
            else:
                l2 = length/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(-l2,-w2,0)
                v2 = Vector(l2,-w2,0)
                v3 = Vector(l2,w2,0)
                v4 = Vector(-l2,w2,0)
                base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            placement = FreeCAD.Placement()
        if base and placement:
            extrusion = normal.multiply(height)
            return (base,extrusion,placement)
        return None
Ejemplo n.º 52
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]
Ejemplo n.º 53
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
        if not obj.Diameter.Value:
            return
        if not obj.Amount:
            return
        father = obj.Host
        fathershape = None
        if not father:
            # support for old-style rebars
            if obj.InList:
                if hasattr(obj.InList[0],"Armatures"):
                    if obj in obj.InList[0].Armatures:
                        father = obj.InList[0]
        if father:
            if father.isDerivedFrom("Part::Feature"):
                fathershape = father.Shape

        wire = obj.Base.Shape.Wires[0]
        if hasattr(obj,"Rounding"):
            #print(obj.Rounding)
            if obj.Rounding:
                radius = obj.Rounding * obj.Diameter.Value
                import DraftGeomUtils
                wire = DraftGeomUtils.filletWire(wire,radius)
        bpoint, bvec = self.getBaseAndAxis(wire)
        if not bpoint:
            return
        axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,0,-1))
        if fathershape:
            size = (ArchCommands.projectToVector(fathershape.copy(),axis)).Length
        else:
            size = 1
        if hasattr(obj,"Direction"):
            if not DraftVecUtils.isNull(obj.Direction):
                axis = FreeCAD.Vector(obj.Direction)
                axis.normalize()
                if fathershape:
                    size = (ArchCommands.projectToVector(fathershape.copy(),axis)).Length
                else:
                    size = 1
        if hasattr(obj,"Distance"):
            if obj.Distance.Value:
                size = obj.Distance.Value
        spacinglist = None
        if hasattr(obj, "CustomSpacing"):
            if obj.CustomSpacing:
                spacinglist = strprocessOfCustomSpacing(obj.CustomSpacing)
                influenceArea = sum(spacinglist) - spacinglist[0] / 2 - spacinglist[-1] / 2
        if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size:
            return
        # all tests ok!
        if hasattr(obj, "Length"):
            length = getLengthOfRebar(obj)
            if length:
                obj.Length = length
        pl = obj.Placement
        import Part
        circle = Part.makeCircle(obj.Diameter.Value/2,bpoint,bvec)
        circle = Part.Wire(circle)
        try:
            bar = wire.makePipeShell([circle],True,False,2)
            basewire = wire.copy()
        except Part.OCCError:
            print("Arch: error sweeping rebar profile along the base sketch")
            return
        # building final shape
        shapes = []
        placementlist = []
        self.wires = []
        rot = FreeCAD.Rotation()
        if obj.Amount == 1:
            barplacement = CalculatePlacement(obj.Amount, 1, obj.Diameter.Value, size, axis, rot, obj.OffsetStart.Value, obj.OffsetEnd.Value, obj.ViewObject.RebarShape)
            placementlist.append(barplacement)
            if hasattr(obj,"Spacing"):
                obj.Spacing = 0
        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)
            for i in range(obj.Amount):
                barplacement = CalculatePlacement(obj.Amount, i+1, obj.Diameter.Value, size, axis, rot, obj.OffsetStart.Value, obj.OffsetEnd.Value, obj.ViewObject.RebarShape)
                placementlist.append(barplacement)
            if hasattr(obj,"Spacing"):
                obj.Spacing = interval
        # Calculate placement of bars from custom spacing.
        if spacinglist:
            placementlist[:] = []
            if obj.ViewObject.RebarShape == "Stirrup":
                reqInfluenceArea = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value + obj.Diameter.Value)
            else:
                reqInfluenceArea = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value)
            # Avoid unnecessary checks to pass like. For eg.: when we have values
            # like influenceArea is 100.00001 and reqInflueneArea is 100
            if round(influenceArea) > round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning("Influence area of rebars is greater than "+ str(reqInfluenceArea) + ".\n")
            elif round(influenceArea) < round(reqInfluenceArea):
                FreeCAD.Console.PrintWarning("Last span is greater that end offset.\n")
            for i in range(len(spacinglist)):
                if i == 0:
                    barplacement = CustomSpacingPlacement(spacinglist, 1, axis, father.Placement.Rotation, obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
                else:
                    barplacement = CustomSpacingPlacement(spacinglist, i+1, axis, father.Placement.Rotation, obj.OffsetStart.Value, obj.OffsetEnd.Value)
                    placementlist.append(barplacement)
            obj.Amount = len(spacinglist)
            obj.Spacing = 0
        obj.PlacementList = placementlist
        for i in range(len(obj.PlacementList)):
            if i == 0:
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                basewire.Placement = obj.PlacementList[i]
                self.wires.append(basewire)
            else:
                bar = bar.copy()
                bar.Placement = obj.PlacementList[i]
                shapes.append(bar)
                w = basewire.copy()
                w.Placement = obj.PlacementList[i]
                self.wires.append(w)
        if shapes:
            obj.Shape = Part.makeCompound(shapes)
            obj.Placement = pl
        obj.TotalLength = obj.Length * len(obj.PlacementList)
Ejemplo n.º 54
0
    def execute(self,obj):
        "creates the panel shape"
        
        if self.clone(obj):
            return

        import Part, DraftGeomUtils

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

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

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

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

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

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(translate("Arch","Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Ejemplo n.º 55
0
def _svg_dimension(obj, plane, scale, linewidth, fontsize, stroke, pointratio,
                   techdraw, rotation):
    """Return the SVG representation of a linear dimension."""
    if not App.GuiUp:
        _wrn("'{}': SVG can only be generated "
             "in GUI mode".format(obj.Label))
        return ""

    if not hasattr(obj.ViewObject, "Proxy") or not obj.ViewObject.Proxy:
        _err("'{}': doesn't have Proxy, "
             "SVG cannot be generated".format(obj.Label))
        return ""

    vobj = obj.ViewObject
    prx = vobj.Proxy

    if not hasattr(prx, "p1"):
        _err("'{}': doesn't have points, "
             "SVG cannot be generated".format(obj.Label))
        return ""

    ts = len(prx.string) * vobj.FontSize.Value / 4.0
    rm = (prx.p3 - prx.p2).Length / 2.0 - ts

    _diff32 = prx.p3 - prx.p2
    _diff23 = prx.p2 - prx.p3

    _v32 = DraftVecUtils.scaleTo(_diff32, rm)
    _v23 = DraftVecUtils.scaleTo(_diff23, rm)

    p2a = get_proj(prx.p2 + _v32, plane)
    p2b = get_proj(prx.p3 + _v23, plane)
    p1 = get_proj(prx.p1, plane)
    p2 = get_proj(prx.p2, plane)
    p3 = get_proj(prx.p3, plane)
    p4 = get_proj(prx.p4, plane)

    tbase = get_proj(prx.tbase, plane)
    r = prx.textpos.rotation.getValue().getValue()
    _rv = App.Rotation(r[0], r[1], r[2], r[3])
    rv = _rv.multVec(App.Vector(1, 0, 0))
    angle = -DraftVecUtils.angle(get_proj(rv, plane))
    # angle = -DraftVecUtils.angle(p3.sub(p2))

    svg = ''
    nolines = False
    if hasattr(vobj, "ShowLine"):
        if not vobj.ShowLine:
            nolines = True

    # drawing lines
    if not nolines:
        svg += '<path '

    if vobj.DisplayMode == "2D":
        tangle = angle
        if tangle > math.pi / 2:
            tangle = tangle - math.pi
        # elif (tangle <= -math.pi/2) or (tangle > math.pi/2):
        #    tangle = tangle + math.pi

        if rotation != 0:
            # print("dim: tangle:", tangle,
            #       " rot: ", rotation,
            #       " text: ", prx.string)
            if abs(tangle + math.radians(rotation)) < 0.0001:
                tangle += math.pi
                _v = App.Vector(0, 2.0 / scale, 0)
                _rot = DraftVecUtils.rotate(_v, tangle)
                tbase = tbase + _rot

        if not nolines:
            svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' '
            svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' '
            svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' '
            svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" '
    else:
        tangle = 0
        if rotation != 0:
            tangle = -math.radians(rotation)

        tbase = tbase + App.Vector(0, -2.0 / scale, 0)
        if not nolines:
            svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' '
            svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' '
            svg += 'L ' + str(p2a.x) + ' ' + str(p2a.y) + ' '
            svg += 'M ' + str(p2b.x) + ' ' + str(p2b.y) + ' '
            svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' '
            svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" '

    if not nolines:
        svg += 'fill="none" stroke="'
        svg += stroke + '" '
        svg += 'stroke-width="' + str(linewidth) + ' px" '
        svg += 'style="stroke-width:' + str(linewidth)
        svg += ';stroke-miterlimit:4;stroke-dasharray:none" '
        svg += 'freecad:basepoint1="' + str(p1.x) + ' ' + str(p1.y) + '" '
        svg += 'freecad:basepoint2="' + str(p4.x) + ' ' + str(p4.y) + '" '
        svg += 'freecad:dimpoint="' + str(p2.x) + ' ' + str(p2.y) + '"'
        svg += '/>\n'

        # drawing dimension and extension lines overshoots
        if hasattr(vobj, "DimOvershoot") and vobj.DimOvershoot.Value:
            shootsize = vobj.DimOvershoot.Value / pointratio
            svg += get_overshoot(p2, shootsize, stroke, linewidth, angle)
            svg += get_overshoot(p3, shootsize, stroke, linewidth,
                                 angle + math.pi)

        if hasattr(vobj, "ExtOvershoot") and vobj.ExtOvershoot.Value:
            shootsize = vobj.ExtOvershoot.Value / pointratio
            shootangle = -DraftVecUtils.angle(p1 - p2)
            svg += get_overshoot(p2, shootsize, stroke, linewidth, shootangle)
            svg += get_overshoot(p3, shootsize, stroke, linewidth, shootangle)

        # drawing arrows
        if hasattr(vobj, "ArrowType"):
            arrowsize = vobj.ArrowSize.Value / pointratio
            if hasattr(vobj, "FlipArrows"):
                if vobj.FlipArrows:
                    angle = angle + math.pi

            svg += get_arrow(obj, vobj.ArrowType, p2, arrowsize, stroke,
                             linewidth, angle)
            svg += get_arrow(obj, vobj.ArrowType, p3, arrowsize, stroke,
                             linewidth, angle + math.pi)

    # drawing text
    svg += svgtext.get_text(plane, techdraw, stroke, fontsize, vobj.FontName,
                            tangle, tbase, prx.string)

    return svg
Ejemplo n.º 56
0
def getCutVolume(cutplane, shapes):
    """getCutVolume(cutplane,shapes): returns a cut face and a cut volume
    from the given shapes and the given cutting plane"""
    if not shapes:
        return None, None, None
    import Part

    if not isinstance(shapes, list):
        shapes = [shapes]
    # building boundbox
    bb = shapes[0].BoundBox
    for sh in shapes[1:]:
        bb.add(sh.BoundBox)
    bb.enlarge(1)
    # building cutplane space
    placement = None
    um = vm = wm = 0
    try:
        if hasattr(cutplane, "Shape"):
            p = cutplane.Shape.copy().Faces[0]
        else:
            p = cutplane.copy().Faces[0]
    except:
        FreeCAD.Console.PrintMessage(translate("Arch", "Invalid cutplane"))
        return None, None, None
    ce = p.CenterOfMass
    ax = p.normalAt(0, 0)
    u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize()
    v = u.cross(ax)
    if not bb.isCutPlane(ce, ax):
        FreeCAD.Console.PrintMessage(translate("Arch", "No objects are cut by the plane"))
        return None, None, None
    else:
        corners = [
            FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin),
            FreeCAD.Vector(bb.XMin, bb.YMax, bb.ZMin),
            FreeCAD.Vector(bb.XMax, bb.YMin, bb.ZMin),
            FreeCAD.Vector(bb.XMax, bb.YMax, bb.ZMin),
            FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMax),
            FreeCAD.Vector(bb.XMin, bb.YMax, bb.ZMax),
            FreeCAD.Vector(bb.XMax, bb.YMin, bb.ZMax),
            FreeCAD.Vector(bb.XMax, bb.YMax, bb.ZMax),
        ]
        for c in corners:
            dv = c.sub(ce)
            um1 = DraftVecUtils.project(dv, u).Length
            um = max(um, um1)
            vm1 = DraftVecUtils.project(dv, v).Length
            vm = max(vm, vm1)
            wm1 = DraftVecUtils.project(dv, ax).Length
            wm = max(wm, wm1)
        vu = DraftVecUtils.scaleTo(u, um)
        vui = vu.negative()
        vv = DraftVecUtils.scaleTo(v, vm)
        vvi = vv.negative()
        p1 = ce.add(vu.add(vvi))
        p2 = ce.add(vu.add(vv))
        p3 = ce.add(vui.add(vv))
        p4 = ce.add(vui.add(vvi))
        cutface = Part.makePolygon([p1, p2, p3, p4, p1])
        cutface = Part.Face(cutface)
        cutnormal = DraftVecUtils.scaleTo(ax, wm)
        cutvolume = cutface.extrude(cutnormal)
        cutnormal = cutnormal.negative()
        invcutvolume = cutface.extrude(cutnormal)
        return cutface, cutvolume, invcutvolume
Ejemplo n.º 57
0
    def action(self, arg):
        """Handle the 3D scene events.

        This is installed as an EventCallback in the Inventor view.

        Parameters
        ----------
        arg: dict
            Dictionary with strings that indicates the type of event received
            from the 3D view.
        """
        if arg["Type"] == "SoKeyboardEvent":
            if arg["Key"] == "ESCAPE":
                self.finish()
        elif arg["Type"] == "SoLocation2Event":  # mouse movement detection
            import DraftGeomUtils
            shift = gui_tool_utils.hasMod(arg, gui_tool_utils.MODCONSTRAIN)
            if self.arcmode or self.point2:
                gui_tool_utils.setMod(arg, gui_tool_utils.MODCONSTRAIN, False)
            (self.point, ctrlPoint, self.info) = gui_tool_utils.getPoint(
                self, arg, noTracker=(len(self.node) > 0))
            if (gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT)
                    or self.selectmode) and (len(self.node) < 3):
                self.dimtrack.off()
                if not self.altdown:
                    self.altdown = True
                    self.ui.switchUi(True)
                    if hasattr(Gui, "Snapper"):
                        Gui.Snapper.setSelectMode(True)
                snapped = self.view.getObjectInfo(
                    (arg["Position"][0], arg["Position"][1]))
                if snapped:
                    ob = self.doc.getObject(snapped['Object'])
                    if "Edge" in snapped['Component']:
                        num = int(snapped['Component'].lstrip('Edge')) - 1
                        ed = ob.Shape.Edges[num]
                        v1 = ed.Vertexes[0].Point
                        v2 = ed.Vertexes[-1].Point
                        self.dimtrack.update([v1, v2, self.cont])
            else:
                if self.node and (len(self.edges) < 2):
                    self.dimtrack.on()
                if len(self.edges) == 2:
                    # angular dimension
                    self.dimtrack.off()
                    r = self.point.sub(self.center)
                    self.arctrack.setRadius(r.Length)
                    a = self.arctrack.getAngle(self.point)
                    pair = DraftGeomUtils.getBoundaryAngles(a, self.pts)
                    if not (pair[0] < a < pair[1]):
                        self.angledata = [
                            4 * math.pi - pair[0], 2 * math.pi - pair[1]
                        ]
                    else:
                        self.angledata = [
                            2 * math.pi - pair[0], 2 * math.pi - pair[1]
                        ]
                    self.arctrack.setStartAngle(self.angledata[0])
                    self.arctrack.setEndAngle(self.angledata[1])
                if self.altdown:
                    self.altdown = False
                    self.ui.switchUi(False)
                    if hasattr(Gui, "Snapper"):
                        Gui.Snapper.setSelectMode(False)
                if self.dir:
                    _p = DraftVecUtils.project(self.point.sub(self.node[0]),
                                               self.dir)
                    self.point = self.node[0].add(_p)
                if len(self.node) == 2:
                    if self.arcmode and self.edges:
                        cen = self.edges[0].Curve.Center
                        rad = self.edges[0].Curve.Radius
                        baseray = self.point.sub(cen)
                        v2 = DraftVecUtils.scaleTo(baseray, rad)
                        v1 = v2.negative()
                        if shift:
                            self.node = [cen, cen.add(v2)]
                            self.arcmode = "radius"
                        else:
                            self.node = [cen.add(v1), cen.add(v2)]
                            self.arcmode = "diameter"
                        self.dimtrack.update(self.node)
                # Draw constraint tracker line.
                if shift and (not self.arcmode):
                    if len(self.node) == 2:
                        if not self.point2:
                            self.point2 = self.node[1]
                        else:
                            self.node[1] = self.point2
                        if not self.force:
                            _p = self.point.sub(self.node[0])
                            a = abs(_p.getAngle(App.DraftWorkingPlane.u))
                            if (a > math.pi / 4) and (a <= 0.75 * math.pi):
                                self.force = 1
                            else:
                                self.force = 2
                        if self.force == 1:
                            self.node[1] = App.Vector(self.node[0].x,
                                                      self.node[1].y,
                                                      self.node[0].z)
                        elif self.force == 2:
                            self.node[1] = App.Vector(self.node[1].x,
                                                      self.node[0].y,
                                                      self.node[0].z)
                else:
                    self.force = None
                    if self.point2 and (len(self.node) > 1):
                        self.node[1] = self.point2
                        self.point2 = None
                # update the dimline
                if self.node and not self.arcmode:
                    self.dimtrack.update(self.node + [self.point] +
                                         [self.cont])
            gui_tool_utils.redraw3DView()
        elif arg["Type"] == "SoMouseButtonEvent":
            if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
                import DraftGeomUtils
                if self.point:
                    self.ui.redraw()
                    if (not self.node) and (not self.support):
                        gui_tool_utils.getSupport(arg)
                    if (gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT)
                            or self.selectmode) and (len(self.node) < 3):
                        # print("snapped: ",self.info)
                        if self.info:
                            ob = self.doc.getObject(self.info['Object'])
                            if 'Edge' in self.info['Component']:
                                num = int(
                                    self.info['Component'].lstrip('Edge')) - 1
                                ed = ob.Shape.Edges[num]
                                v1 = ed.Vertexes[0].Point
                                v2 = ed.Vertexes[-1].Point
                                i1 = i2 = None
                                for i in range(len(ob.Shape.Vertexes)):
                                    if v1 == ob.Shape.Vertexes[i].Point:
                                        i1 = i
                                    if v2 == ob.Shape.Vertexes[i].Point:
                                        i2 = i
                                if (i1 is not None) and (i2 is not None):
                                    self.indices.append(num)
                                    if not self.edges:
                                        # nothing snapped yet, we treat it
                                        # as a normal edge-snapped dimension
                                        self.node = [v1, v2]
                                        self.link = [ob, i1, i2]
                                        self.edges.append(ed)
                                        if DraftGeomUtils.geomType(
                                                ed) == "Circle":
                                            # snapped edge is an arc
                                            self.arcmode = "diameter"
                                            self.link = [ob, num]
                                    else:
                                        # there is already a snapped edge,
                                        # so we start angular dimension
                                        self.edges.append(ed)
                                        # self.node now has the 4 endpoints
                                        self.node.extend([v1, v2])
                                        c = DraftGeomUtils.findIntersection(
                                            self.node[0], self.node[1],
                                            self.node[2], self.node[3], True,
                                            True)
                                        if c:
                                            # print("centers:",c)
                                            self.center = c[0]
                                            self.arctrack.setCenter(
                                                self.center)
                                            self.arctrack.on()
                                            for e in self.edges:
                                                for v in e.Vertexes:
                                                    self.pts.append(
                                                        self.arctrack.getAngle(
                                                            v.Point))
                                            self.link = [self.link[0], ob]
                                        else:
                                            _msg(
                                                translate(
                                                    "draft",
                                                    "Edges don't intersect!"))
                                            self.finish()
                                            return
                                self.dimtrack.on()
                    else:
                        self.node.append(self.point)
                    self.selectmode = False
                    # print("node", self.node)
                    self.dimtrack.update(self.node)
                    if len(self.node) == 2:
                        self.point2 = self.node[1]
                    if len(self.node) == 1:
                        self.dimtrack.on()
                        if self.planetrack:
                            self.planetrack.set(self.node[0])
                    elif len(self.node) == 2 and self.cont:
                        self.node.append(self.cont)
                        self.createObject()
                        if not self.cont:
                            self.finish()
                    elif len(self.node) == 3:
                        # for unlinked arc mode:
                        # if self.arcmode:
                        #     v = self.node[1].sub(self.node[0])
                        #     v.multiply(0.5)
                        #     cen = self.node[0].add(v)
                        #     self.node = [self.node[0], self.node[1], cen]
                        self.createObject()
                        if not self.cont:
                            self.finish()
                    elif self.angledata:
                        self.node.append(self.point)
                        self.createObject()
                        self.finish()
Ejemplo n.º 58
0
    def __init__(self,
                 fc_fro_ax,
                 fc_top_ax,
                 base_h = 2,
                 base_l = 0,
                 base_w = 0,
                 bolt_d = 3,
                 bolt_csunk = 0,
                 ref = 1,
                 pos = V0,
                 extra=1,
                 wfco = 1,
                 intol = 0,
                 name = 'belt_clamp' ):

        doc = FreeCAD.ActiveDocument
        self.name = name

        # if more tolerance is needed in the center
        cb_in_w = CB_IW + intol
        self.cb_in_w = cb_in_w
        cb_wall_w = CB_W - intol/2
        self.cb_wall_w = cb_wall_w

        # normalize and get the other base vector
        nfro_ax = DraftVecUtils.scaleTo(fc_fro_ax,1)
        nfro_ax_n = nfro_ax.negative()
        ntop_ax = DraftVecUtils.scaleTo(fc_top_ax,1)
        ntop_ax_n = ntop_ax.negative()
        nsid_ax = nfro_ax.cross(ntop_ax)

        clamponly_l = CB_L + CS + 2 * CCYL_R
        clamponly_w = max((cb_in_w+2*cb_wall_w), (2*CCYL_R))

        bolt2end = 0 # they will change in case they are used
        clamp2end = 0
        if base_h == 0 and bolt_d == 0:
            # No base
            base = 0
            base_l = 0
        else:
            base = 1
            if bolt_d > 0 :
                d_bolt = kcomp.D912[bolt_d]
                bolt_shank_r = d_bolt['shank_r_tol']
                bolt_head_r = d_bolt['head_r_tol']
                bolt_head_l = d_bolt['head_l']
                # there are bolt holes, calculate the extra length needed
                # from the end to the clamp / cylinder
                bolt2end = fcfun.get_bolt_end_sep(bolt_d,hasnut=0)
                # bolt space on one side
                clamp2end = 2 * bolt2end
                base_min_len = clamponly_l + 2 * clamp2end
                if base_l < base_min_len:
                    logger.debug("base_l too short, taking min len %s",
                                  base_min_len)
                    base_l = base_min_len
                else:
                    clamp2end = (base_l - clamponly_l) /2.
                    bolt2end = clamp2end / 2.
                if bolt_csunk > 0:
                    # there are countersunk holes for the bolts
                    if base_h == 0:
                        # minimum height:
                        base_h = bolt_csunk + bolt_head_l
                    else:
                        # check if there is enough base height
                        if base_h < bolt_csunk + bolt_head_l:
                            base_h = bolt_csunk + bolt_head_l
                            logger.debug("base_h too short,taking height %s",
                                  base_h)
                else:
                    if base_h < self.MIN_BASE_H:
                        base_h = self.MIN_BASE_H
                        logger.debug("taking base height %s",
                                  base_h)
            else: # No bolt
                bolt2end = 0
                if base_l < clamponly_l:
                    if base_l > 0:
                        logger.debug("base_l too short, Taking min len %s",
                                      clamponly_l) 
                    base_l = clamponly_l
                    clamp2end = 0
                else: #base larger than clamp
                    clamp2end = (base_l - clamponly_l) /2.
            if base_w == 0:
                base_w = clamponly_w
            elif base_w < clamponly_w:
                logger.debug("base_w too short, Taking min width %s",
                              clamponly_w)
                base_w = clamponly_w

        ###
        cencyl2froclamp = CB_L+CS+CCYL_R
        #vectors to references:
        # from the center of the cylinder to the front clamp
        vec_1to2 = DraftVecUtils.scale(nfro_ax,cencyl2froclamp)
        vec_2to1 = vec_1to2.negative()
        # from the front clamp to the front bolt
        vec_2to3 = DraftVecUtils.scale(nfro_ax, bolt2end)
        vec_3to2 = vec_2to3.negative()
        # Since not always there is a bolt, from the clamp
        vec_2to4 = DraftVecUtils.scale(nfro_ax, clamp2end)
        vec_4to2 = vec_2to4.negative()
        # from the center of the cylinder to the back bolt
        vec_5to1 = DraftVecUtils.scale(nfro_ax,CCYL_R) + vec_2to3
        vec_1to5 = vec_5to1.negative()
        # from the back bolt to the back end
        vec_6to1 = DraftVecUtils.scale(nfro_ax,CCYL_R) + vec_2to4
        vec_1to6 = vec_6to1.negative()

        # default values
        vec_tocencyl = V0
        vec_tofrontclamp = V0
        vec_tofrontbolt = V0
        vec_tofrontbase = V0
        vec_tobackbolt = V0
        vec_tobackbase = V0
        if ref==1: #ref on the center of the cylinder
            vec_tocencyl = V0
            vec_tofrontclamp = vec_1to2 
            vec_tofrontbolt = vec_1to2 + vec_2to3
            vec_tofrontbase = vec_1to2 + vec_2to4
            vec_tobackbolt = vec_1to5
            vec_tobackbase = vec_1to6
        elif ref==2: #ref on the front of the clamps
            vec_tocencyl = vec_2to1
            vec_tofrontclamp = V0
            vec_tofrontbolt = vec_2to3
            vec_tofrontbase = vec_2to4
            vec_tobackbolt = ve_2to1 + vec_1to5
            vec_tobackbase = ve_2to1 + vec_1to6
        elif ref == 3:
            if clamp2end == 0 or bolt2end == 0:
                logger.error('reference on the bolts, there are no bolts')
            else:
                vec_tocencyl = vec_3to2 + vec_2to1
                vec_tofrontclamp = vec_3to2
                vec_tofrontbolt = V0
                vec_tofrontbase = vec_2to3 #same as 3 to 4
                vec_tobackbolt = vec_3to2 + vec_2to1 + vec_1to5
                vec_tobackbase = vec_3to2 + vec_2to1 + vec_1to6
        elif ref == 4:
            if clamp2end == 0:
                logger.debug('reference at the end, same as the clamps')
            vec_tocencyl = vec_4to2 + vec_2to1
            vec_tofrontclamp = vec_4to2
            vec_tofrontbolt = vec_3to2 # same as 4 to 3
            vec_tofrontbase = V0
            vec_tobackbolt = vec_4to2 + vec_2to1 + vec_1to5
            vec_tobackbase = vec_4to2 + vec_2to1 + vec_1to6
        elif ref == 5:
            if clamp2end == 0 or bolt2end == 0:
                logger.error('reference on the bolts, there are no bolts')
            else:
                vec_tocencyl = vec_5to1
                vec_tofrontclamp = vec_5to1 + vec_1to2
                vec_tofrontbolt = vec_5to1 + vec_1to2 + vec_2to3
                vec_tofrontbase = vec_5to1 + vec_1to2 + vec_2to4
                vec_tobackbolt = V0
                vec_tobackbase = vec_3to2 #5to6: same as 3to2
        elif ref == 6:
            if clamp2end == 0:
                logger.debug('reference at the end, same as the clamps')
            vec_tocencyl = vec_6to1
            vec_tofrontclamp = vec_6to1 + vec_1to2
            vec_tofrontbolt = vec_6to1 + vec_1to2 + vec_2to3
            vec_tofrontbase = vec_6to1 + vec_1to2 + vec_2to4
            vec_tobackbolt = vec_2to3 # same as 6 to 5
            vec_tobackbase = V0
        else:
            logger.error('reference out of range')
          


        if extra == 0:
            extra_pos = V0
        else:
            extra_pos = DraftVecUtils.scale(ntop_ax, -extra)
        pos_extra = pos + extra_pos
        base_top_add = DraftVecUtils.scale(ntop_ax, base_h + extra)
        
        
        # total height of the clamp, including the base
        clamp_tot_h = C_H + base_h + extra
        # position of the clamp cylinder:
        clampcyl_pos = pos_extra + vec_tocencyl
        shp_cyl = fcfun.shp_cyl(CCYL_R, clamp_tot_h, ntop_ax, clampcyl_pos)
        # position of the clamp blocks, without going to the side axis
        clampblock_pos = pos_extra + vec_tofrontclamp
        clampblock_side_add = DraftVecUtils.scale(nsid_ax, 
                                                  (cb_in_w + cb_wall_w)/2.)
        clampblock_1_pos = clampblock_pos + clampblock_side_add
        clampblock_2_pos = clampblock_pos - clampblock_side_add
        shp_clampblock_1 = fcfun.shp_box_dir(box_w = cb_wall_w,
                                             box_d = CB_L,
                                             box_h = clamp_tot_h,
                                             fc_axis_h = ntop_ax,
                                             fc_axis_d = nfro_ax_n,
                                             cw=1, cd=0, ch=0,
                                             pos = clampblock_1_pos)
        shp_clampblock_2 = fcfun.shp_box_dir(box_w = cb_wall_w,
                                             box_d = CB_L,
                                             box_h = clamp_tot_h,
                                             fc_axis_h = ntop_ax,
                                             fc_axis_d = nfro_ax_n,
                                             cw=1, cd=0, ch=0,
                                             pos = clampblock_2_pos)

        shp_clamp = shp_cyl.multiFuse([shp_clampblock_1, shp_clampblock_2])


        #position of the base, we will take it on the point 4 and make it not 
        # centered
        if base == 1:
            base_pos = pos_extra + vec_tofrontbase 
            shp_base = fcfun.shp_box_dir(box_w = base_w,
                                         box_d = base_l,
                                         box_h = base_h + extra,
                                         fc_axis_h = ntop_ax,
                                         fc_axis_d = nfro_ax_n,
                                         cw=1, cd=0, ch=0,
                                         pos = base_pos)
            if base_l > clamponly_l: # chamfer
                shp_base = fcfun.shp_filletchamfer_dir (shp_base,
                                              fc_axis=ntop_ax,
                                              fillet=1, radius= 2)

            # shape of the bolt holes, if there are
            if bolt_d > 0:
                pos_bolt_front = pos_extra + vec_tofrontbolt + base_top_add
                pos_bolt_back = pos_extra + vec_tobackbolt + base_top_add
                if bolt_csunk > 0 :
                    shp_bolt_front = fcfun.shp_bolt_dir(
                                              r_shank = bolt_shank_r,
                                              l_bolt = base_h + extra,
                                              r_head = bolt_head_r,
                                              l_head = bolt_head_l,
                                              support=0,
                                              fc_normal = ntop_ax_n,
                                              pos=pos_bolt_front)
                    shp_bolt_back = fcfun.shp_bolt_dir(
                                              r_shank = bolt_shank_r,
                                              l_bolt = base_h + extra,
                                              r_head = bolt_head_r,
                                              l_head = bolt_head_l,
                                              support=0,
                                              fc_normal = ntop_ax_n,
                                              pos=pos_bolt_back)
                else: # no head, just a cylinder:
                    shp_bolt_front = fcfun.shp_cylcenxtr (
                                              r = bolt_shank_r,
                                              h = base_h + extra,
                                              normal = ntop_ax_n,
                                              ch = 0,
                                              xtr_top=1, xtr_bot=1,
                                              pos = pos_bolt_front)
                    shp_bolt_back = fcfun.shp_cylcenxtr (
                                              r = bolt_shank_r,
                                              h = base_h + extra,
                                              normal = ntop_ax_n,
                                              ch = 0,
                                              xtr_top=1, xtr_bot=1,
                                              pos = pos_bolt_back)


                # fuse the bolts:
                shp_bolts = shp_bolt_front.fuse(shp_bolt_back)
                shp_base = shp_base.cut(shp_bolts)
            shp_clamp = shp_base.fuse(shp_clamp)

              
 

        doc.recompute()
        shp_clamp = shp_clamp.removeSplitter()
        self.shp = shp_clamp

        self.wfco = wfco
        if wfco == 1:
            # a freeCAD object is created
            fco_clamp = doc.addObject("Part::Feature", name )
            fco_clamp.Shape = shp_clamp
            self.fco = fco_clamp
Ejemplo n.º 59
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         if not isinstance(data[0],list):
             # multifuses not considered here
             return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     if obj.Normal == Vector(0,0,0):
         normal = Vector(0,0,1)
     else:
         normal = Vector(obj.Normal)
     base = None
     placement = None
     basewires = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Face > 0:
                     if len(obj.Base.Shape.Faces) >= obj.Face:
                         face = obj.Base.Shape.Faces[obj.Face-1]
                         # this wall is based on a specific face of its base object
                         normal = face.normalAt(0,0)
                         if normal.getAngle(Vector(0,0,1)) > math.pi/4:
                             normal.multiply(width)
                             base = face.extrude(normal)
                             if obj.Align == "Center":
                                 base.translate(normal.negative().multiply(0.5))
                             elif obj.Align == "Right":
                                 base.translate(normal.negative())
                         else:
                             normal.multiply(height)
                             base = face.extrude(normal)
                         base,placement = self.rebase(base)
                         return (base,normal,placement)
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                 elif obj.Base.Shape.Wires:
                     basewires = obj.Base.Shape.Wires
                 elif len(obj.Base.Shape.Edges) == 1:
                     basewires = [Part.Wire(obj.Base.Shape.Edges)]
                 if basewires and width:
                     baseface = None
                     for wire in basewires:
                         e = wire.Edges[0]
                         if isinstance(e.Curve,Part.Circle):
                             dvec = e.Vertexes[0].Point.sub(e.Curve.Center)
                         else:
                             dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal)
                         if not DraftVecUtils.isNull(dvec):
                             dvec.normalize()
                         sh = None
                         if obj.Align == "Left":
                             dvec.multiply(width)
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 wire = DraftGeomUtils.offsetWire(wire,dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1,w2)
                         elif obj.Align == "Right":
                             dvec.multiply(width)
                             dvec = dvec.negative()
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 wire = DraftGeomUtils.offsetWire(wire,dvec2)
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             w1 = Part.Wire(Part.__sortEdges__(wire.Edges))
                             sh = DraftGeomUtils.bind(w1,w2)
                         elif obj.Align == "Center":
                             dvec.multiply(width/2)
                             w1 = DraftGeomUtils.offsetWire(wire,dvec)
                             dvec = dvec.negative()
                             w2 = DraftGeomUtils.offsetWire(wire,dvec)
                             sh = DraftGeomUtils.bind(w1,w2)
                         if sh:
                             sh.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(sh)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                     if baseface:
                         base,placement = self.rebase(baseface)
     else:
         l2 = length/2 or 0.5
         w2 = width/2 or 0.5
         v1 = Vector(-l2,-w2,0)
         v2 = Vector(l2,-w2,0)
         v3 = Vector(l2,w2,0)
         v4 = Vector(-l2,w2,0)
         base = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         placement = FreeCAD.Placement()
     if base and placement:
         extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None