Ejemplo n.º 1
0
def isPlanar(shape):
    """Return True if the given shape or list of points is planar."""
    n = getNormal(shape)
    if not n:
        return False

    if isinstance(shape, list):
        if len(shape) <= 3:
            return True
        else:
            for v in shape[3:]:
                pv = v.sub(shape[0])
                rv = DraftVecUtils.project(pv, n)
                if not DraftVecUtils.isNull(rv):
                    return False
    else:
        if len(shape.Vertexes) <= 3:
            return True

        for p in shape.Vertexes[1:]:
            pv = p.Point.sub(shape.Vertexes[0].Point)
            rv = DraftVecUtils.project(pv, n)
            if not DraftVecUtils.isNull(rv):
                return False

    return True
Ejemplo n.º 2
0
def polar_placements(base_placement,
                     center, angle,
                     number, axis, axisvector):
    """Determine the placements where the polar copies will be."""
    # print("angle ",angle," num ",num)
    placements = [base_placement.copy()]

    if number == 0:
        return placements

    spin = App.Placement(App.Vector(), base_placement.Rotation)
    pl = App.Placement(base_placement.Base, App.Rotation())
    center = center.sub(base_placement.Base)

    if angle == 360:
        fraction = float(angle)/number
    else:
        fraction = float(angle)/(number - 1)

    center_tuple = DraftVecUtils.tup(center)
    axis_tuple = DraftVecUtils.tup(axis)

    for i in range(number - 1):
        currangle = fraction + (i*fraction)
        npl = pl.copy()
        npl.rotate(center_tuple, axis_tuple, currangle)
        npl = npl.multiply(spin)
        if axisvector:
            if not DraftVecUtils.isNull(axisvector):
                npl.translate(App.Vector(axisvector).multiply(i+1))
        placements.append(npl)

    return placements
Ejemplo n.º 3
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 = dvec.multiply(width)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
         sh = DraftGeomUtils.bind(w1,w2)
     elif obj.Align == "Right":
         dvec = dvec.multiply(width)
         dvec = DraftVecUtils.neg(dvec)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         w1 = Part.Wire(DraftGeomUtils.sortEdges(wire.Edges))
         sh = DraftGeomUtils.bind(w1,w2)
     elif obj.Align == "Center":
         dvec = dvec.multiply(width/2)
         w1 = DraftGeomUtils.offsetWire(wire,dvec)
         dvec = DraftVecUtils.neg(dvec)
         w2 = DraftGeomUtils.offsetWire(wire,dvec)
         sh = DraftGeomUtils.bind(w1,w2)
     # fixing self-intersections
     sh.fix(0.1,0,1)
     if height and (not flat):
         norm = Vector(normal).multiply(height)
         sh = sh.extrude(norm)
     return sh
Ejemplo n.º 4
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)
         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()
         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)
     if height and (not flat):
         norm = Vector(normal).multiply(height)
         sh = sh.extrude(norm)
     return sh
Ejemplo n.º 5
0
def getCircleFromSpline(edge):
    """Return a circle-based edge from a bspline-based edge."""
    if geomType(edge) != "BSplineCurve":
        return None
    if len(edge.Vertexes) != 1:
        return None
    # get 2 points
    p1 = edge.Curve.value(0)
    p2 = edge.Curve.value(math.pi / 2)
    # get 2 tangents
    t1 = edge.Curve.tangent(0)[0]
    t2 = edge.Curve.tangent(math.pi / 2)[0]
    # get normal
    n = p1.cross(p2)
    if DraftVecUtils.isNull(n):
        return None
    # get rays
    r1 = DraftVecUtils.rotate(t1, math.pi / 2, n)
    r2 = DraftVecUtils.rotate(t2, math.pi / 2, n)
    # get center (intersection of rays)
    i = findIntersection(p1, p1.add(r1), p2, p2.add(r2), True, True)
    if not i:
        return None
    c = i[0]
    r = (p1.sub(c)).Length
    circle = Part.makeCircle(r, c, n)
    #print(circle.Curve)
    return circle
Ejemplo n.º 6
0
def isClockwise(edge, ref=None):
    """Return True if a circle-based edge has a clockwise direction."""
    if not geomType(edge) == "Circle":
        return True

    v1 = edge.Curve.tangent(edge.ParameterRange[0])[0]
    if DraftVecUtils.isNull(v1):
        return True

    # we take an arbitrary other point on the edge that has little chances
    # to be aligned with the first one
    v2 = edge.Curve.tangent(edge.ParameterRange[0] + 0.01)[0]
    n = edge.Curve.Axis
    # if that axis points "the wrong way" from the reference, we invert it
    if not ref:
        ref = FreeCAD.Vector(0, 0, 1)
    if n.getAngle(ref) > math.pi / 2:
        n = n.negative()

    if DraftVecUtils.angle(v1, v2, n) < 0:
        return False

    if n.z < 0:
        return False

    return True
Ejemplo n.º 7
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.º 8
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.º 9
0
    def handle_mouse_move_event(self, arg):
        """Handle the mouse when moving."""
        plane = App.DraftWorkingPlane

        for ghost in self.ghosts:
            ghost.off()
        self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg)
        # this is to make sure radius is what you see on screen
        if self.center and DraftVecUtils.dist(self.point, self.center):
            viewdelta = DraftVecUtils.project(self.point.sub(self.center),
                                              plane.axis)
            if not DraftVecUtils.isNull(viewdelta):
                self.point = self.point.add(viewdelta.negative())
        if self.extendedCopy:
            if not gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                self.step = 3
                self.finish()
        if self.step == 0:
            pass
        elif self.step == 1:
            currentrad = DraftVecUtils.dist(self.point, self.center)
            if currentrad != 0:
                angle = DraftVecUtils.angle(plane.u,
                                            self.point.sub(self.center),
                                            plane.axis)
            else:
                angle = 0
            self.ui.setRadiusValue(math.degrees(angle), unit="Angle")
            self.firstangle = angle
            self.ui.radiusValue.setFocus()
            self.ui.radiusValue.selectAll()
        elif self.step == 2:
            currentrad = DraftVecUtils.dist(self.point, self.center)
            if currentrad != 0:
                angle = DraftVecUtils.angle(plane.u,
                                            self.point.sub(self.center),
                                            plane.axis)
            else:
                angle = 0
            if angle < self.firstangle:
                sweep = (2 * math.pi - self.firstangle) + angle
            else:
                sweep = angle - self.firstangle
            self.arctrack.setApertureAngle(sweep)
            for ghost in self.ghosts:
                ghost.rotate(plane.axis, sweep)
                ghost.on()
            self.ui.setRadiusValue(math.degrees(sweep), 'Angle')
            self.ui.radiusValue.setFocus()
            self.ui.radiusValue.selectAll()
        gui_tool_utils.redraw3DView()
Ejemplo n.º 10
0
 def getTextPosition(self, vobj):
     pos = FreeCAD.Vector()
     if hasattr(vobj, "TextPosition"):
         import DraftVecUtils
         if DraftVecUtils.isNull(vobj.TextPosition):
             try:
                 pos = vobj.Object.Shape.CenterOfMass
                 z = vobj.Object.Shape.BoundBox.ZMin
                 pos = FreeCAD.Vector(pos.x, pos.y, z)
             except (AttributeError, RuntimeError):
                 pos = FreeCAD.Vector()
         else:
             pos = vobj.TextPosition
     return pos
Ejemplo n.º 11
0
 def updateData(self, obj, prop):
     if prop == "Points":
         if obj.Points:
             p = obj.Points[-1]
             if hasattr(self,"coords"):
                 self.coords.translation.setValue((p.x,p.y,p.z))
                 if len(obj.Points) >= 2:
                     v1 = obj.Points[-2].sub(obj.Points[-1])
                     if not DraftVecUtils.isNull(v1):
                         v1.normalize()
                         _rot = coin.SbRotation()
                         _rot.setValue(coin.SbVec3f(1, 0, 0), coin.SbVec3f(v1[0], v1[1], v1[2]))
                         self.coords.rotation.setValue(_rot)
     return
Ejemplo n.º 12
0
 def getTextPosition(self,vobj):
     pos = FreeCAD.Vector()
     if hasattr(vobj,"TextPosition"):
         import DraftVecUtils
         if DraftVecUtils.isNull(vobj.TextPosition):
             try:
                 pos = vobj.Object.Shape.CenterOfMass
                 z = vobj.Object.Shape.BoundBox.ZMin
                 pos = FreeCAD.Vector(pos.x,pos.y,z)
             except:
                 pos = FreeCAD.Vector()
         else:
             pos = vobj.TextPosition
     return pos
Ejemplo n.º 13
0
    def getTextPosition(self,vobj):

        pos = FreeCAD.Vector()
        if hasattr(vobj,"TextPosition"):
            import DraftVecUtils
            if DraftVecUtils.isNull(vobj.TextPosition):
                try:
                    pos = vobj.Object.Shape.CenterOfMass
                    z = vobj.Object.Shape.BoundBox.ZMin
                    pos = FreeCAD.Vector(pos.x,pos.y,z)
                except (AttributeError, RuntimeError):
                    pos = FreeCAD.Vector()
            else:
                pos = vobj.TextPosition
        # placement's displacement will be already added by the coin node
        pos = vobj.Object.Placement.inverse().multVec(pos)
        return pos
Ejemplo n.º 14
0
def getRebarsSpanAxis(rebar):
    """getRebarsSpanAxis(Rebar):
    Returns span axis of rebars.
    """
    if (Draft.getType(rebar.Base) == "Wire"
            or rebar.Base.Shape.ShapeType == "Wire") and len(
                rebar.Base.Shape.Wires[0].Edges
            ) != 1:  # Draft Wires can have "wrong" placement
        # This works fine instead for straight rebars i.e. for rebars having
        # base wire with only one edge
        axis = DraftGeomUtils.getNormal(rebar.Base.Shape)
    else:
        axis = rebar.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1))
    if hasattr(rebar, "Direction"):
        if not DraftVecUtils.isNull(rebar.Direction):
            axis = FreeCAD.Vector(rebar.Direction)
            axis.normalize()
    return axis
Ejemplo n.º 15
0
    def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2):
        if pt1:
            # first check if we don't already have coincident endpoints
            if pt1 in [pt3, pt4]:
                return [pt1]
            elif (pt2 in [pt3, pt4]):
                return [pt2]
        norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
        norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))

        if not DraftVecUtils.isNull(norm1):
            try:
                norm1.normalize()
            except Part.OCCError:
                return []

        if not DraftVecUtils.isNull(norm2):
            try:
                norm2.normalize()
            except Part.OCCError:
                return []

        if DraftVecUtils.isNull(norm1.cross(norm2)):
            vec1 = pt2.sub(pt1)
            vec2 = pt4.sub(pt3)
            if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2):
                return []  # One of the lines has zero-length
            try:
                vec1.normalize()
                vec2.normalize()
            except Part.OCCError:
                return []
            norm3 = vec1.cross(vec2)
            denom = norm3.x + norm3.y + norm3.z
            if not DraftVecUtils.isNull(norm3) and denom != 0:
                k = ((pt3.z - pt1.z) * (vec2.x - vec2.y) + (pt3.y - pt1.y) *
                     (vec2.z - vec2.x) + (pt3.x - pt1.x) *
                     (vec2.y - vec2.z)) / denom
                vec1.scale(k, k, k)
                intp = pt1.add(vec1)

                if infinite1 is False and not isPtOnEdge(intp, edge1):
                    return []

                if infinite2 is False and not isPtOnEdge(intp, edge2):
                    return []

                return [intp]
            else:
                return []  # Lines have same direction
        else:
            return []  # Lines aren't on same plane
Ejemplo n.º 16
0
def areColinear(e1, e2):
    """Return True if both edges are colinear."""
    if not isinstance(e1.Curve, (Part.LineSegment, Part.Line)):
        return False
    if not isinstance(e2.Curve, (Part.LineSegment, Part.Line)):
        return False

    v1 = vec(e1)
    v2 = vec(e2)
    a = round(v1.getAngle(v2), precision())
    if (a == 0) or (a == round(math.pi, precision())):
        v3 = e2.Vertexes[0].Point.sub(e1.Vertexes[0].Point)
        if DraftVecUtils.isNull(v3):
            return True
        else:
            a2 = round(v1.getAngle(v3), precision())
            if (a2 == 0) or (a2 == round(math.pi, precision())):
                return True
    return False
Ejemplo n.º 17
0
    def update_arrow(self, obj, vobj):
        """Update the arrow tip of the line."""
        if hasattr(self, "symbol"):
            if self.arrow.findChild(self.symbol) != -1:
                self.arrow.removeChild(self.symbol)

        s = utils.ARROW_TYPES.index(vobj.ArrowType)
        self.symbol = gui_utils.dim_symbol(s)

        if vobj.ArrowType == "Circle":
            # TODO: fix behavior of the 'Circle' marker.
            # Instead of appearing at the tip of the line
            # the 'Circle' marker appears displaced and duplicated
            # a certain distance from the tip, which is the `TargetPoint`.
            # Somehow the translation is added to the position of the tip
            # resulting in a wrong value.
            # So the arrow position is reset; nevertheless, this doesn't
            # entirely fix the issue.
            coords2 = coin.SoCoordinate3()
            coords2.point.setValues([obj.Points[-1]])
            self.arrow.addChild(coords2)
            self.arrowpos.translation.setValue((0, 0, 0))
        else:
            self.arrowpos.translation.setValue(obj.Points[-1])
        self.arrow.addChild(self.symbol)

        v1 = obj.Points[-2].sub(obj.Points[-1])

        if not DraftVecUtils.isNull(v1):
            v1.normalize()
            v2 = App.Vector(0, 0, 1)
            if round(v2.getAngle(v1), 4) in [0, round(math.pi, 4)]:
                v2 = App.Vector(0, 1, 0)

            v3 = v1.cross(v2).negative()

            _rot_mat = DraftVecUtils.getPlaneRotation(v1, v3, v2)
            q = App.Placement(_rot_mat).Rotation.Q
            self.arrowpos.rotation.setValue((q[0], q[1], q[2], q[3]))
Ejemplo n.º 18
0
 def polarArray(self, spl, center, angle, num, axis, axisvector):
     #print("angle ",angle," num ",num)
     spin = App.Placement(App.Vector(), spl.Rotation)
     pl = App.Placement(spl.Base, App.Rotation())
     center = center.sub(spl.Base)
     base = [spl.copy()]
     if angle == 360:
         fraction = float(angle) / num
     else:
         if num == 0:
             return base
         fraction = float(angle) / (num - 1)
     ctr = DraftVecUtils.tup(center)
     axs = DraftVecUtils.tup(axis)
     for i in range(num - 1):
         currangle = fraction + (i * fraction)
         npl = pl.copy()
         npl.rotate(ctr, axs, currangle)
         npl = npl.multiply(spin)
         if axisvector:
             if not DraftVecUtils.isNull(axisvector):
                 npl.translate(App.Vector(axisvector).multiply(i + 1))
         base.append(npl)
     return base
Ejemplo n.º 19
0
def get_dxf(obj, direction=None):
    """Return a DXF entity from the given object.

    If direction is given, the object is projected in 2D.
    """
    plane = None
    result = ""
    if (obj.isDerivedFrom("Drawing::View")
            or obj.isDerivedFrom("TechDraw::DrawView")):
        if obj.Source.isDerivedFrom("App::DocumentObjectGroup"):
            for o in obj.Source.Group:
                result += get_dxf(o, obj.Direction)
        else:
            result += get_dxf(obj.Source, obj.Direction)
        return result

    if direction and isinstance(direction, App.Vector):
        if direction != App.Vector(0, 0, 0):
            plane = WorkingPlane.Plane()
            plane.alignToPointAndAxis(App.Vector(0, 0, 0), direction)

    if utils.get_type(obj) in ("Dimension", "LinearDimension"):
        p1 = _get_proj(obj.Start, plane=plane)
        p2 = _get_proj(obj.End, plane=plane)
        p3 = _get_proj(obj.Dimline, plane=plane)
        result += "0\nDIMENSION\n8\n0\n62\n0\n3\nStandard\n70\n1\n"
        result += "10\n" + str(p3.x) + "\n20\n" + str(p3.y) + "\n30\n" + str(
            p3.z) + "\n"
        result += "13\n" + str(p1.x) + "\n23\n" + str(p1.y) + "\n33\n" + str(
            p1.z) + "\n"
        result += "14\n" + str(p2.x) + "\n24\n" + str(p2.y) + "\n34\n" + str(
            p2.z) + "\n"

    elif utils.get_type(obj) == "Annotation":
        # Only for App::Annotation
        p = _get_proj(obj.Position, plane=plane)
        count = 0
        for t in obj.LabeLtext:
            result += "0\nTEXT\n8\n0\n62\n0\n"
            result += "10\n"
            result += str(p.x) + "\n20\n"
            result += str(p.y + count) + "\n30\n"
            result += str(p.z) + "\n"
            result += "40\n1\n"
            result += "1\n" + str(t) + "\n"
            result += "7\nSTANDARD\n"
            count += 1

    elif hasattr(obj, 'Shape'):
        # TODO do this the Draft way, for ex. using polylines and rectangles
        if not direction:
            direction = App.Vector(0, 0, -1)

        if DraftVecUtils.isNull(direction):
            direction = App.Vector(0, 0, -1)

        try:
            d = Drawing.projectToDXF(obj.Shape, direction)
        except Exception:
            # TODO: trap only specific exception.
            # Impossible to generate DXF from Shape? Which exception is throw?
            _wrn("get_dxf: "
                 "unable to project '{}' to {}".format(obj.Label, direction))
        else:
            result += d
    else:
        _wrn("get_dxf: unsupported object, '{}'".format(obj.Label))

    return result
Ejemplo n.º 20
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.º 21
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.º 22
0
    def execute(self,obj):
        
        if self.clone(obj):
            return
        
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

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

        if self.isEnabled("extension"):
            tsnap = self.snapToExtOrtho(last,constrain,eline)
            if tsnap:
                if (tsnap[0].sub(point)).Length < self.radius:
                    if self.tracker:
                        self.tracker.setCoords(tsnap[2])
                        self.tracker.setMarker(self.mk[tsnap[1]])
                        self.tracker.on()
                    if self.extLine:
                        self.extLine.p2(tsnap[2])
                        self.extLine.on()
                    self.setCursor(tsnap[1])
                    return tsnap[2],eline
            else:
                tsnap = self.snapToExtPerpendicular(last)
                if tsnap:
                    if (tsnap[0].sub(point)).Length < self.radius:
                        if self.tracker:
                            self.tracker.setCoords(tsnap[2])
                            self.tracker.setMarker(self.mk[tsnap[1]])
                            self.tracker.on()
                        if self.extLine:
                            self.extLine.p2(tsnap[2])
                            self.extLine.on()
                        self.setCursor(tsnap[1])
                        return tsnap[2],eline
                
        for o in [self.lastObj[1],self.lastObj[0]]:
            if o:
                ob = FreeCAD.ActiveDocument.getObject(o)
                if ob:
                    if ob.isDerivedFrom("Part::Feature"):
                        edges = ob.Shape.Edges
                        if (not self.maxEdges) or (len(edges) <= self.maxEdges):
                            for e in edges:
                                if DraftGeomUtils.geomType(e) == "Line":
                                    np = self.getPerpendicular(e,point)
                                    if not DraftGeomUtils.isPtOnEdge(np,e):
                                        if (np.sub(point)).Length < self.radius:
                                            if self.isEnabled('extension'):
                                                if np != e.Vertexes[0].Point:
                                                    if self.tracker:
                                                        self.tracker.setCoords(np)
                                                        self.tracker.setMarker(self.mk['extension'])
                                                        self.tracker.on()
                                                    if self.extLine:
                                                        self.extLine.p1(e.Vertexes[0].Point)
                                                        self.extLine.p2(np)
                                                        self.extLine.on()
                                                    self.setCursor('extension')
                                                    return np,Part.Line(e.Vertexes[0].Point,np).toShape()
                                        else:
                                            if self.isEnabled('parallel'):
                                                if last:
                                                    ve = DraftGeomUtils.vec(e)
                                                    if not DraftVecUtils.isNull(ve):
                                                        de = Part.Line(last,last.add(ve)).toShape()  
                                                        np = self.getPerpendicular(de,point)
                                                        if (np.sub(point)).Length < self.radius:
                                                            if self.tracker:
                                                                self.tracker.setCoords(np)
                                                                self.tracker.setMarker(self.mk['parallel'])
                                                                self.tracker.on()
                                                            self.setCursor('parallel')
                                                            return np,de
        return point,eline
Ejemplo n.º 26
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.º 27
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.
        """
        import DraftGeomUtils

        if arg["Type"] == "SoKeyboardEvent":
            if arg["Key"] == "ESCAPE":
                self.finish()
        elif arg["Type"] == "SoLocation2Event":  # mouse movement detection
            self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg)

            # this is to make sure radius is what you see on screen
            if self.center and DraftVecUtils.dist(self.point, self.center) > 0:
                viewdelta = DraftVecUtils.project(self.point.sub(self.center),
                                                  App.DraftWorkingPlane.axis)
                if not DraftVecUtils.isNull(viewdelta):
                    self.point = self.point.add(viewdelta.negative())
            if self.step == 0:  # choose center
                if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                    if not self.altdown:
                        self.altdown = True
                        self.ui.switchUi(True)
                else:
                    if self.altdown:
                        self.altdown = False
                        self.ui.switchUi(False)
            else:  # choose radius
                if len(self.tangents) == 2:
                    cir = DraftGeomUtils.circleFrom2tan1pt(
                        self.tangents[0], self.tangents[1], self.point)
                    _c = DraftGeomUtils.findClosestCircle(self.point, cir)
                    self.center = _c.Center
                    self.arctrack.setCenter(self.center)
                elif self.tangents and self.tanpoints:
                    cir = DraftGeomUtils.circleFrom1tan2pt(
                        self.tangents[0], self.tanpoints[0], self.point)
                    _c = DraftGeomUtils.findClosestCircle(self.point, cir)
                    self.center = _c.Center
                    self.arctrack.setCenter(self.center)
                if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                    if not self.altdown:
                        self.altdown = True
                    snapped = self.view.getObjectInfo(
                        (arg["Position"][0], arg["Position"][1]))
                    if snapped:
                        ob = self.doc.getObject(snapped['Object'])
                        num = int(snapped['Component'].lstrip('Edge')) - 1
                        ed = ob.Shape.Edges[num]
                        if len(self.tangents) == 2:
                            cir = DraftGeomUtils.circleFrom3tan(
                                self.tangents[0], self.tangents[1], ed)
                            cl = DraftGeomUtils.findClosestCircle(
                                self.point, cir)
                            self.center = cl.Center
                            self.rad = cl.Radius
                            self.arctrack.setCenter(self.center)
                        else:
                            self.rad = self.center.add(
                                DraftGeomUtils.findDistance(
                                    self.center, ed).sub(self.center)).Length
                    else:
                        self.rad = DraftVecUtils.dist(self.point, self.center)
                else:
                    if self.altdown:
                        self.altdown = False
                    self.rad = DraftVecUtils.dist(self.point, self.center)
                self.ui.setRadiusValue(self.rad, 'Length')
                self.arctrack.setRadius(self.rad)

            gui_tool_utils.redraw3DView()

        elif (arg["Type"] == "SoMouseButtonEvent" and arg["State"] == "DOWN"
              and arg["Button"] == "BUTTON1"):  # mouse click
            if self.point:
                if self.step == 0:  # choose center
                    if (not self.node) and (not self.support):
                        gui_tool_utils.getSupport(arg)
                        (self.point, ctrlPoint,
                         info) = gui_tool_utils.getPoint(self, arg)
                    if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT):
                        snapped = self.view.getObjectInfo(
                            (arg["Position"][0], arg["Position"][1]))
                        if snapped:
                            ob = self.doc.getObject(snapped['Object'])
                            num = int(snapped['Component'].lstrip('Edge')) - 1
                            ed = ob.Shape.Edges[num]
                            self.tangents.append(ed)
                            if len(self.tangents) == 2:
                                self.arctrack.on()
                                self.ui.radiusUi()
                                self.step = 1
                                _msg(translate("draft", "Pick radius"))
                    else:
                        if len(self.tangents) == 1:
                            self.tanpoints.append(self.point)
                        else:
                            self.center = self.point
                            self.node = [self.point]
                            self.arctrack.setCenter(self.center)
                        self.arctrack.on()
                        self.ui.radiusUi()
                        self.step = 1
                        _msg(translate("draft", "Pick radius"))
                        if self.planetrack:
                            self.planetrack.set(self.point)
                elif self.step == 1:  # choose radius
                    self.drawPolygon()
Ejemplo n.º 28
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.º 29
0
    def compare(self,face1,face2):
        "zsorts two faces. Returns 1 if face1 is closer, 2 if face2 is closer, 0 otherwise"

        #print face1,face2

        if not face1:
            if DEBUG: print "Warning, undefined face!" 
            return 31
        elif not face2:
            if DEBUG: print "Warning, undefined face!" 
            return 32

        # theory from
        # http://www.siggraph.org/education/materials/HyperGraph/scanline/visibility/painter.htm
        # and practical application http://vrm.ao2.it/ (blender vector renderer)

        b1 = face1[0].BoundBox
        b2 = face2[0].BoundBox

        # test 1: if faces don't overlap, no comparison possible
        if DEBUG: print "doing test 1"
        if b1.XMax < b2.XMin:
            return 0
        if b1.XMin > b2.XMax:
            return 0
        if b1.YMax < b2.YMin:
            return 0
        if b1.YMin > b2.YMax:
            return 0
        if DEBUG: print "failed, faces bboxes are not distinct"

        # test 2: if Z bounds dont overlap, it's easy to know the closest
        if DEBUG: print "doing test 2"
        if b1.ZMax < b2.ZMin:
            return 2
        if b2.ZMax < b1.ZMin:
            return 1
        if DEBUG: print "failed, faces Z are not distinct"

        # test 3: all verts of face1 are in front or behind the plane of face2
        if DEBUG: print "doing test 3"
        norm = face2[0].normalAt(0,0)
        behind = 0
        front = 0
        for v in face1[0].Vertexes:
            dv = v.Point.sub(face2[0].Vertexes[0].Point)
            dv = DraftVecUtils.project(dv,norm)
            if DraftVecUtils.isNull(dv):
                behind += 1
                front += 1
            else:
                if dv.getAngle(norm) > 1:
                    behind += 1
                else:
                    front += 1
        if DEBUG: print "front: ",front," behind: ",behind
        if behind == len(face1[0].Vertexes):
            return 2
        elif front == len(face1[0].Vertexes):
            return 1
        if DEBUG: print "failed, cannot say if face 1 is in front or behind"

        # test 4: all verts of face2 are in front or behind the plane of face1
        if DEBUG: print "doing test 4"
        norm = face1[0].normalAt(0,0)
        behind = 0
        front = 0
        for v in face2[0].Vertexes:
            dv = v.Point.sub(face1[0].Vertexes[0].Point)
            dv = DraftVecUtils.project(dv,norm)
            if DraftVecUtils.isNull(dv):
                behind += 1
                front += 1
            else:
                if dv.getAngle(norm) > 1:
                    behind += 1
                else:
                    front += 1
        if DEBUG: print "front: ",front," behind: ",behind
        if behind == len(face2[0].Vertexes):
            return 1
        elif front == len(face2[0].Vertexes):
            return 2
        if DEBUG: print "failed, cannot say if face 2 is in front or behind"

        # test 5: see if faces projections don't overlap, vertexwise
        if DEBUG: print "doing test 5"
        if not self.zOverlaps(face1,face2):
            return 0
        elif not self.zOverlaps(face2,face1):
            return 0
        if DEBUG: print "failed, faces are overlapping" 

        if DEBUG: print "Houston, all tests passed, and still no results" 
        return 0
Ejemplo n.º 30
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
Ejemplo n.º 31
0
def findIntersection(edge1,
                     edge2,
                     infinite1=False,
                     infinite2=False,
                     ex1=False,
                     ex2=False,
                     dts=True,
                     findAll=False):
    """Return a list containing the intersection points of 2 edges.

    You can also feed 4 points instead of `edge1` and `edge2`.
    If `dts` is used, `Shape.distToShape()` is used, which can be buggy.
    """
    def getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2):
        if pt1:
            # first check if we don't already have coincident endpoints
            if pt1 in [pt3, pt4]:
                return [pt1]
            elif (pt2 in [pt3, pt4]):
                return [pt2]
        norm1 = pt2.sub(pt1).cross(pt3.sub(pt1))
        norm2 = pt2.sub(pt4).cross(pt3.sub(pt4))

        if not DraftVecUtils.isNull(norm1):
            try:
                norm1.normalize()
            except Part.OCCError:
                return []

        if not DraftVecUtils.isNull(norm2):
            try:
                norm2.normalize()
            except Part.OCCError:
                return []

        if DraftVecUtils.isNull(norm1.cross(norm2)):
            vec1 = pt2.sub(pt1)
            vec2 = pt4.sub(pt3)
            if DraftVecUtils.isNull(vec1) or DraftVecUtils.isNull(vec2):
                return []  # One of the lines has zero-length
            try:
                vec1.normalize()
                vec2.normalize()
            except Part.OCCError:
                return []
            norm3 = vec1.cross(vec2)
            denom = norm3.x + norm3.y + norm3.z
            if not DraftVecUtils.isNull(norm3) and denom != 0:
                k = ((pt3.z - pt1.z) * (vec2.x - vec2.y) + (pt3.y - pt1.y) *
                     (vec2.z - vec2.x) + (pt3.x - pt1.x) *
                     (vec2.y - vec2.z)) / denom
                vec1.scale(k, k, k)
                intp = pt1.add(vec1)

                if infinite1 is False and not isPtOnEdge(intp, edge1):
                    return []

                if infinite2 is False and not isPtOnEdge(intp, edge2):
                    return []

                return [intp]
            else:
                return []  # Lines have same direction
        else:
            return []  # Lines aren't on same plane

    # First, check bound boxes
    if (isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
            and (not infinite1) and (not infinite2)):
        if not edge1.BoundBox.intersect(edge2.BoundBox):
            return []  # bound boxes don't intersect

    # First, try to use distToShape if possible
    if (dts and isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
            and (not infinite1) and (not infinite2)):
        dist, pts, geom = edge1.distToShape(edge2)
        sol = []
        if round(dist, precision()) == 0:
            for p in pts:
                if p not in sol:
                    sol.append(p[0])
        return sol

    pt1 = None

    if isinstance(edge1, FreeCAD.Vector) and isinstance(edge2, FreeCAD.Vector):
        # we got points directly
        pt1 = edge1
        pt2 = edge2
        pt3 = infinite1
        pt4 = infinite2
        infinite1 = ex1
        infinite2 = ex2
        return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2)

    elif (geomType(edge1) == "Line") and (geomType(edge2) == "Line"):
        # we have 2 straight lines
        pt1, pt2, pt3, pt4 = [
            edge1.Vertexes[0].Point, edge1.Vertexes[1].Point,
            edge2.Vertexes[0].Point, edge2.Vertexes[1].Point
        ]
        return getLineIntersections(pt1, pt2, pt3, pt4, infinite1, infinite2)

    elif ((geomType(edge1) == "Circle") and (geomType(edge2) == "Line")
          or (geomType(edge1) == "Line") and (geomType(edge2) == "Circle")):

        # deals with an arc or circle and a line
        edges = [edge1, edge2]
        for edge in edges:
            if geomType(edge) == "Line":
                line = edge
            else:
                arc = edge

        dirVec = vec(line)
        dirVec.normalize()
        pt1 = line.Vertexes[0].Point
        pt2 = line.Vertexes[1].Point
        pt3 = arc.Vertexes[0].Point
        pt4 = arc.Vertexes[-1].Point
        center = arc.Curve.Center

        int = []
        # first check for coincident endpoints
        if DraftVecUtils.equals(pt1, pt3) or DraftVecUtils.equals(pt1, pt4):
            if findAll:
                int.append(pt1)
            else:
                return [pt1]
        elif pt2 in [pt3, pt4]:
            if findAll:
                int.append(pt2)
            else:
                return [pt2]

        if DraftVecUtils.isNull(
                pt1.sub(center).cross(pt2.sub(center)).cross(arc.Curve.Axis)):
            # Line and Arc are on same plane

            dOnLine = center.sub(pt1).dot(dirVec)
            onLine = FreeCAD.Vector(dirVec)
            onLine.scale(dOnLine, dOnLine, dOnLine)
            toLine = pt1.sub(center).add(onLine)

            if toLine.Length < arc.Curve.Radius:
                dOnLine = (arc.Curve.Radius**2 - toLine.Length**2)**(0.5)
                onLine = FreeCAD.Vector(dirVec)
                onLine.scale(dOnLine, dOnLine, dOnLine)
                int += [center.add(toLine).add(onLine)]
                onLine = FreeCAD.Vector(dirVec)
                onLine.scale(-dOnLine, -dOnLine, -dOnLine)
                int += [center.add(toLine).add(onLine)]
            elif round(toLine.Length - arc.Curve.Radius, precision()) == 0:
                int = [center.add(toLine)]
            else:
                return []

        else:
            # Line isn't on Arc's plane
            if dirVec.dot(arc.Curve.Axis) != 0:
                toPlane = FreeCAD.Vector(arc.Curve.Axis)
                toPlane.normalize()
                d = pt1.dot(toPlane)
                if not d:
                    return []
                dToPlane = center.sub(pt1).dot(toPlane)
                toPlane = FreeCAD.Vector(pt1)
                toPlane.scale(dToPlane / d, dToPlane / d, dToPlane / d)
                ptOnPlane = toPlane.add(pt1)
                if round(
                        ptOnPlane.sub(center).Length - arc.Curve.Radius,
                        precision()) == 0:
                    int = [ptOnPlane]
                else:
                    return []
            else:
                return []

        if infinite1 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge1):
                    del int[i]
        if infinite2 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge2):
                    del int[i]
        return int

    elif (geomType(edge1) == "Circle") and (geomType(edge2) == "Circle"):
        # deals with 2 arcs or circles
        cent1, cent2 = edge1.Curve.Center, edge2.Curve.Center
        rad1, rad2 = edge1.Curve.Radius, edge2.Curve.Radius
        axis1, axis2 = edge1.Curve.Axis, edge2.Curve.Axis
        c2c = cent2.sub(cent1)

        if cent1.sub(cent2).Length == 0:
            # circles are concentric
            return []

        if DraftVecUtils.isNull(axis1.cross(axis2)):
            if round(c2c.dot(axis1), precision()) == 0:
                # circles are on same plane
                dc2c = c2c.Length
                if not DraftVecUtils.isNull(c2c):
                    c2c.normalize()
                if (round(rad1 + rad2 - dc2c, precision()) < 0
                        or round(rad1 - dc2c - rad2, precision()) > 0
                        or round(rad2 - dc2c - rad1, precision()) > 0):
                    return []
                else:
                    norm = c2c.cross(axis1)
                    if not DraftVecUtils.isNull(norm):
                        norm.normalize()
                    if DraftVecUtils.isNull(norm):
                        x = 0
                    else:
                        x = (dc2c**2 + rad1**2 - rad2**2) / (2 * dc2c)
                    y = abs(rad1**2 - x**2)**(0.5)
                    c2c.scale(x, x, x)
                    if round(y, precision()) != 0:
                        norm.scale(y, y, y)
                        int = [cent1.add(c2c).add(norm)]
                        int += [cent1.add(c2c).sub(norm)]
                    else:
                        int = [cent1.add(c2c)]
            else:
                return []  # circles are on parallel planes
        else:
            # circles aren't on same plane
            axis1.normalize()
            axis2.normalize()
            U = axis1.cross(axis2)
            V = axis1.cross(U)
            dToPlane = c2c.dot(axis2)
            d = V.add(cent1).dot(axis2)
            V.scale(dToPlane / d, dToPlane / d, dToPlane / d)
            PtOn2Planes = V.add(cent1)
            planeIntersectionVector = U.add(PtOn2Planes)
            intTemp = findIntersection(planeIntersectionVector, edge1, True,
                                       True)
            int = []
            for pt in intTemp:
                if round(pt.sub(cent2).Length - rad2, precision()) == 0:
                    int += [pt]

        if infinite1 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge1):
                    del int[i]
        if infinite2 is False:
            for i in range(len(int) - 1, -1, -1):
                if not isPtOnEdge(int[i], edge2):
                    del int[i]

        return int
    else:
        print("DraftGeomUtils: Unsupported curve type: "
              "(" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")")
        return []
Ejemplo n.º 32
0
    def execute(self,obj):
        
        if self.clone(obj):
            return
        
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

        pl = obj.Placement
        if obj.Base.Shape.Solids:
            obj.Shape = obj.Base.Shape.copy()
            if not pl.isNull():
                obj.Placement = obj.Shape.Placement.multiply(pl)
        else:
            if not obj.Profile:
                return
            if not obj.Profile.isDerivedFrom("Part::Part2DObject"):
                return
            if not obj.Profile.Shape:
                return
            if not obj.Profile.Shape.Wires:
                return
            if not obj.Profile.Shape.Faces:
                for w in obj.Profile.Shape.Wires:
                    if not w.isClosed():
                        return
            import DraftGeomUtils, Part, math
            baseprofile = obj.Profile.Shape.copy()
            if hasattr(obj,"ProfilePlacement"):
                if not obj.ProfilePlacement.isNull():
                    baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement)
            if not baseprofile.Faces:
                f = []
                for w in baseprofile.Wires:
                    f.append(Part.Face(w))
                if len(f) == 1:
                    baseprofile = f[0]
                else:
                    baseprofile = Part.makeCompound(f)
            shapes = []
            normal = DraftGeomUtils.getNormal(obj.Base.Shape)
            #for wire in obj.Base.Shape.Wires:
            for e in obj.Base.Shape.Edges:
                #e = wire.Edges[0]
                bvec = DraftGeomUtils.vec(e)
                bpoint = e.Vertexes[0].Point
                profile = baseprofile.copy()
                #basepoint = profile.Placement.Base
                if hasattr(obj,"BasePoint"):
                    edges = Part.__sortEdges__(profile.Edges)
                    basepointliste = [profile.CenterOfMass]
                    for edge in edges:
                        basepointliste.append(DraftGeomUtils.findMidpoint(edge))
                        basepointliste.append(edge.Vertexes[-1].Point)
                    try:
                        basepoint = basepointliste[obj.BasePoint]
                    except IndexError:
                        FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n"))
                        basepoint = basepointliste[0]
                else :
                    basepoint = profile.CenterOfMass
                profile.translate(bpoint.sub(basepoint))
                if obj.Align:
                    axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1))
                    angle = bvec.getAngle(axis)
                    if round(angle,Draft.precision()) != 0:
                        if round(angle,Draft.precision()) != round(math.pi,Draft.precision()):
                            rotaxis = axis.cross(bvec)
                            profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle))
                if obj.Rotation:
                    profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation)
                #profile = wire.makePipeShell([profile],True,False,2) TODO buggy
                profile = profile.extrude(bvec)
                if obj.Offset:
                    if not DraftVecUtils.isNull(obj.Offset):
                        profile.translate(obj.Offset)
                shapes.append(profile)
            if shapes:
                obj.Shape = Part.makeCompound(shapes)
                obj.Placement = pl
Ejemplo n.º 33
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.º 34
0
def getReinforcementDrawingSVGData(
    structure,
    rebars_list,
    view_direction,
    rebars_stroke_width,
    rebars_color_style,
    structure_stroke_width,
    structure_fill_style,
):
    """getReinforcementDrawingSVGData(Structure, RebarsList, ViewDirection,
    RebarsStrokeWidth, RebarsFillStyle, StructureStrokeWidth,
    StructureFillStyle):
    Generates Reinforcement Drawing View.

    view_direction is FreeCAD.Vector() or WorkingPlane.plane() corresponding to
    direction of view point.

    rebars_color_style can be:
        - "shape color" to select color of rebar shape
        - color name or hex value of color
    structure_fill_style can be:
        - "shape color" to select color of rebar shape
        - color name or hex value of color
        - "none" to not fill structure shape

    Returns dictionary format:
    {
        "svg": reinforcement_drawing_svg,
        "rebars": visible_rebars,
    }
    """
    if isinstance(view_direction, FreeCAD.Vector):
        if not DraftVecUtils.isNull(view_direction):
            view_plane = getSVGPlaneFromAxis(view_direction)
    elif isinstance(view_direction, WorkingPlane.Plane):
        view_plane = view_direction

    min_x, min_y, max_x, max_y = getDrawingMinMaxXY(structure, rebars_list,
                                                    view_plane)

    svg = getSVGRootElement()

    reinforcement_drawing = ElementTree.Element(
        "g", attrib={"id": "reinforcement_drawing"})
    svg.append(reinforcement_drawing)

    # Filter rebars created using Reinforcement Workbench
    stirrups = []
    bent_rebars = []
    u_rebars = []
    l_rebars = []
    straight_rebars = []
    helical_rebars = []
    custom_rebars = []
    for rebar in rebars_list:
        if not hasattr(rebar, "RebarShape"):
            custom_rebars.append(rebar)
        elif rebar.RebarShape == "Stirrup":
            stirrups.append(rebar)
        elif rebar.RebarShape == "BentShapeRebar":
            bent_rebars.append(rebar)
        elif rebar.RebarShape == "UShapeRebar":
            u_rebars.append(rebar)
        elif rebar.RebarShape == "LShapeRebar":
            l_rebars.append(rebar)
        elif rebar.RebarShape == "StraightRebar":
            straight_rebars.append(rebar)
        elif rebar.RebarShape == "HelicalRebar":
            helical_rebars.append(rebar)
        else:
            custom_rebars.append(rebar)

    rebars_svg = ElementTree.Element("g", attrib={"id": "Rebars"})
    reinforcement_drawing.append(rebars_svg)

    visible_rebars = []
    stirrups_svg = ElementTree.Element("g", attrib={"id": "Stirrup"})
    rebars_svg.append(stirrups_svg)
    for rebar in stirrups:
        rebar_data = getStirrupSVGData(
            rebar,
            view_plane,
            rebars_svg,
            rebars_stroke_width,
            rebars_color_style,
        )
        if rebar_data["visibility"]:
            stirrups_svg.append(rebar_data["svg"])
            visible_rebars.append(rebar)

    bent_rebars_svg = ElementTree.Element("g", attrib={"id": "BentShapeRebar"})
    rebars_svg.append(bent_rebars_svg)
    for rebar in bent_rebars:
        rebar_data = getUShapeRebarSVGData(
            rebar,
            view_plane,
            rebars_svg,
            rebars_stroke_width,
            rebars_color_style,
        )
        if rebar_data["visibility"]:
            bent_rebars_svg.append(rebar_data["svg"])
            visible_rebars.append(rebar)

    u_rebars_svg = ElementTree.Element("g", attrib={"id": "UShapeRebar"})
    rebars_svg.append(u_rebars_svg)
    for rebar in u_rebars:
        rebar_data = getUShapeRebarSVGData(
            rebar,
            view_plane,
            rebars_svg,
            rebars_stroke_width,
            rebars_color_style,
        )
        if rebar_data["visibility"]:
            u_rebars_svg.append(rebar_data["svg"])
            visible_rebars.append(rebar)

    l_rebars_svg = ElementTree.Element("g", attrib={"id": "LShapeRebar"})
    rebars_svg.append(l_rebars_svg)
    for rebar in l_rebars:
        rebar_data = getUShapeRebarSVGData(
            rebar,
            view_plane,
            rebars_svg,
            rebars_stroke_width,
            rebars_color_style,
        )
        if rebar_data["visibility"]:
            l_rebars_svg.append(rebar_data["svg"])
            visible_rebars.append(rebar)

    straight_rebars_svg = ElementTree.Element("g",
                                              attrib={"id": "StraightRebar"})
    rebars_svg.append(straight_rebars_svg)

    for rebar in straight_rebars:
        rebar_data = getStraightRebarSVGData(
            rebar,
            view_plane,
            rebars_svg,
            rebars_stroke_width,
            rebars_color_style,
        )
        if rebar_data["visibility"]:
            straight_rebars_svg.append(rebar_data["svg"])
            visible_rebars.append(rebar)

    helical_rebars_svg = ElementTree.Element("g",
                                             attrib={"id": "HelicalRebar"})
    rebars_svg.append(helical_rebars_svg)

    # SVG is generated for all helical rebars, because all helical rebars in
    # circular column are assumed to be visible, not overlapped by any other
    # rebar type (it makes sense for me). Please create an issue on github
    # repository if you think its wrong assumption
    for rebar in helical_rebars:
        rebars_color = getRebarColor(rebar, rebars_color_style)
        rebars_color = getcolor(rebars_color)
        rebar_svg_draft = Draft.get_svg(
            rebar,
            direction=view_plane,
            linewidth=rebars_stroke_width,
            fillstyle="none",
            color=rebars_color,
        )
        if rebar_svg_draft:
            helical_rebars_svg.append(ElementTree.fromstring(rebar_svg_draft))
            visible_rebars.append(rebar)

    custom_rebars_svg = ElementTree.Element("g", attrib={"id": "CustomRebar"})
    rebars_svg.append(custom_rebars_svg)
    for rebar in custom_rebars:
        rebars_color = getRebarColor(rebar, rebars_color_style)
        rebars_color = getcolor(rebars_color)
        rebar_svg_draft = Draft.get_svg(
            rebar,
            direction=view_plane,
            linewidth=rebars_stroke_width,
            fillstyle="none",
            color=rebars_color,
        )
        if rebar_svg_draft:
            custom_rebars_svg.append(ElementTree.fromstring(rebar_svg_draft))

    # Create Structure SVG
    _structure_svg = '<g id="structure">{}</g>'.format(
        Draft.get_svg(
            structure,
            direction=view_plane,
            linewidth=structure_stroke_width,
            fillstyle=structure_fill_style,
        ))

    # Fix structure transparency (useful in console mode where
    # obj.ViewObject.Transparency is not available OR in gui mode if
    # structure transparency is ~0)
    if structure_fill_style != "none":
        if _structure_svg.find("fill-opacity") == -1:
            _structure_svg = _structure_svg.replace(";fill:",
                                                    ";fill-opacity:0.2;fill:")
        else:
            import re

            _structure_svg = re.sub('(fill-opacity:)([^:]+)(;|")', r"\1 0.2\3",
                                    _structure_svg)

    structure_svg = ElementTree.fromstring(_structure_svg)
    reinforcement_drawing.append(structure_svg)
    reinforcement_drawing.set(
        "transform",
        "translate({}, {})".format(round(-min_x), round(-min_y)),
    )

    svg_width = round(max_x - min_x)
    svg_height = round(max_y - min_y)

    svg.set("width", "{}mm".format(svg_width))
    svg.set("height", "{}mm".format(svg_height))
    svg.set("viewBox", "0 0 {} {}".format(svg_width, svg_height))

    return {"svg": svg, "rebars": visible_rebars}
Ejemplo n.º 35
0
    def execute(self, obj):
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

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

        #print(face1,face2)

        if not face1:
            if DEBUG: print("Warning, undefined face!")
            return 31
        elif not face2:
            if DEBUG: print("Warning, undefined face!")
            return 32

        # theory from
        # http://www.siggraph.org/education/materials/HyperGraph/scanline/visibility/painter.htm
        # and practical application http://vrm.ao2.it/ (blender vector renderer)

        b1 = face1[0].BoundBox
        b2 = face2[0].BoundBox

        # test 1: if faces don't overlap, no comparison possible
        if DEBUG: print("doing test 1")
        if b1.XMax < b2.XMin:
            return 0
        if b1.XMin > b2.XMax:
            return 0
        if b1.YMax < b2.YMin:
            return 0
        if b1.YMin > b2.YMax:
            return 0
        if DEBUG: print("failed, faces bboxes are not distinct")

        # test 2: if Z bounds don't overlap, it's easy to know the closest
        if DEBUG: print("doing test 2")
        if b1.ZMax < b2.ZMin:
            return 2
        if b2.ZMax < b1.ZMin:
            return 1
        if DEBUG: print("failed, faces Z are not distinct")

        # test 3: all verts of face1 are in front or behind the plane of face2
        if DEBUG: print("doing test 3")
        norm = face2[0].normalAt(0, 0)
        behind = 0
        front = 0
        for v in face1[0].Vertexes:
            dv = v.Point.sub(face2[0].Vertexes[0].Point)
            dv = DraftVecUtils.project(dv, norm)
            if DraftVecUtils.isNull(dv):
                behind += 1
                front += 1
            else:
                if dv.getAngle(norm) > 1:
                    behind += 1
                else:
                    front += 1
        if DEBUG: print("front: ", front, " behind: ", behind)
        if behind == len(face1[0].Vertexes):
            return 2
        elif front == len(face1[0].Vertexes):
            return 1
        if DEBUG: print("failed, cannot say if face 1 is in front or behind")

        # test 4: all verts of face2 are in front or behind the plane of face1
        if DEBUG: print("doing test 4")
        norm = face1[0].normalAt(0, 0)
        behind = 0
        front = 0
        for v in face2[0].Vertexes:
            dv = v.Point.sub(face1[0].Vertexes[0].Point)
            dv = DraftVecUtils.project(dv, norm)
            if DraftVecUtils.isNull(dv):
                behind += 1
                front += 1
            else:
                if dv.getAngle(norm) > 1:
                    behind += 1
                else:
                    front += 1
        if DEBUG: print("front: ", front, " behind: ", behind)
        if behind == len(face2[0].Vertexes):
            return 1
        elif front == len(face2[0].Vertexes):
            return 2
        if DEBUG: print("failed, cannot say if face 2 is in front or behind")

        # test 5: see if faces projections don't overlap, vertexwise
        if DEBUG: print("doing test 5")
        if not self.zOverlaps(face1, face2):
            return 0
        elif not self.zOverlaps(face2, face1):
            return 0
        if DEBUG: print("failed, faces are overlapping")

        if DEBUG: print("Houston, all tests passed, and still no results")
        return 0
Ejemplo n.º 37
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.º 38
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.º 39
0
    def doStretch(self):
        """Do the actual stretching once the points are selected."""
        commitops = []
        if self.displacement:
            if self.displacement.Length > 0:
                _doc = "FreeCAD.ActiveDocument."
                # print("displacement: ", self.displacement)

                # TODO: break this section into individual functions
                # depending on the type of object (wire, curve, sketch,
                # rectangle, etc.) that is selected, and use variables
                # with common strings to avoid repeating
                # the same information every time, for example, the `_doc`
                # variable.
                # This is necessary to reduce the number of indentation levels
                # and make the code easier to read.
                for ops in self.ops:
                    tp = utils.getType(ops[0])
                    _rot = ops[0].Placement.Rotation
                    localdisp = _rot.inverted().multVec(self.displacement)
                    if tp in ["Wire", "BSpline", "BezCurve"]:
                        pts = []
                        for i in range(len(ops[1])):
                            if ops[1][i] is False:
                                pts.append(ops[0].Points[i])
                            else:
                                pts.append(ops[0].Points[i].add(localdisp))
                        pts = str(pts).replace("Vector ", "FreeCAD.Vector")
                        _cmd = _doc + ops[0].Name + ".Points=" + pts
                        commitops.append(_cmd)
                    elif tp in ["Sketch"]:
                        baseverts = [
                            ops[0].Shape.Vertexes[i].Point
                            for i in range(len(ops[1])) if ops[1][i]
                        ]
                        for i in range(ops[0].GeometryCount):
                            j = 0
                            while True:
                                try:
                                    p = ops[0].getPoint(i, j)
                                except ValueError:
                                    break
                                else:
                                    p = ops[0].Placement.multVec(p)
                                    r = None
                                    for bv in baseverts:
                                        if DraftVecUtils.isNull(p.sub(bv)):
                                            _cmd = _doc
                                            _cmd += ops[0].Name
                                            _cmd += ".movePoint"
                                            _cmd += "("
                                            _cmd += str(i) + ", "
                                            _cmd += str(j) + ", "
                                            _cmd += "FreeCAD." + str(
                                                localdisp) + ", "
                                            _cmd += "True"
                                            _cmd += ")"
                                            commitops.append(_cmd)
                                            r = bv
                                            break
                                    if r:
                                        baseverts.remove(r)
                                    j += 1
                    elif tp in ["Rectangle"]:
                        p1 = App.Vector(0, 0, 0)
                        p2 = App.Vector(ops[0].Length.Value, 0, 0)
                        p3 = App.Vector(ops[0].Length.Value,
                                        ops[0].Height.Value, 0)
                        p4 = App.Vector(0, ops[0].Height.Value, 0)
                        if ops[1] == [False, True, True, False]:
                            optype = 1
                        elif ops[1] == [False, False, True, True]:
                            optype = 2
                        elif ops[1] == [True, False, False, True]:
                            optype = 3
                        elif ops[1] == [True, True, False, False]:
                            optype = 4
                        else:
                            optype = 0
                        # print("length:", ops[0].Length,
                        #       "height:", ops[0].Height,
                        #       " - ", ops[1],
                        #       " - ", self.displacement)
                        done = False
                        if optype > 0:
                            v1 = ops[0].Placement.multVec(p2).sub(
                                ops[0].Placement.multVec(p1))
                            a1 = round(self.displacement.getAngle(v1), 4)
                            v2 = ops[0].Placement.multVec(p4).sub(
                                ops[0].Placement.multVec(p1))
                            a2 = round(self.displacement.getAngle(v2), 4)
                            # check if the displacement is along one
                            # of the rectangle directions
                            if a1 == 0:  # 0 degrees
                                if optype == 1:
                                    if ops[0].Length.Value >= 0:
                                        d = ops[
                                            0].Length.Value + self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Length.Value - self.displacement.Length
                                    _cmd = _doc
                                    _cmd += ops[0].Name + ".Length=" + str(d)
                                    commitops.append(_cmd)
                                    done = True
                                elif optype == 3:
                                    if ops[0].Length.Value >= 0:
                                        d = ops[
                                            0].Length.Value - self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Length.Value + self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Length=" + str(d)
                                    _pl = _doc + ops[0].Name
                                    _pl += ".Placement.Base=FreeCAD."
                                    _pl += str(ops[0].Placement.Base.add(
                                        self.displacement))
                                    commitops.append(_cmd)
                                    commitops.append(_pl)
                                    done = True
                            elif a1 == 3.1416:  # pi radians, 180 degrees
                                if optype == 1:
                                    if ops[0].Length.Value >= 0:
                                        d = ops[
                                            0].Length.Value - self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Length.Value + self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Length=" + str(d)
                                    commitops.append(_cmd)
                                    done = True
                                elif optype == 3:
                                    if ops[0].Length.Value >= 0:
                                        d = ops[
                                            0].Length.Value + self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Length.Value - self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Length=" + str(d)
                                    _pl = _doc + ops[0].Name
                                    _pl += ".Placement.Base=FreeCAD."
                                    _pl += str(ops[0].Placement.Base.add(
                                        self.displacement))
                                    commitops.append(_cmd)
                                    commitops.append(_pl)
                                    done = True
                            elif a2 == 0:  # 0 degrees
                                if optype == 2:
                                    if ops[0].Height.Value >= 0:
                                        d = ops[
                                            0].Height.Value + self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Height.Value - self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Height=" + str(d)
                                    commitops.append(_cmd)
                                    done = True
                                elif optype == 4:
                                    if ops[0].Height.Value >= 0:
                                        d = ops[
                                            0].Height.Value - self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Height.Value + self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Height=" + str(d)
                                    _pl = _doc + ops[0].Name
                                    _pl += ".Placement.Base=FreeCAD."
                                    _pl += str(ops[0].Placement.Base.add(
                                        self.displacement))
                                    commitops.append(_cmd)
                                    commitops.append(_pl)
                                    done = True
                            elif a2 == 3.1416:  # pi radians, 180 degrees
                                if optype == 2:
                                    if ops[0].Height.Value >= 0:
                                        d = ops[
                                            0].Height.Value - self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Height.Value + self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Height=" + str(d)
                                    commitops.append(_cmd)
                                    done = True
                                elif optype == 4:
                                    if ops[0].Height.Value >= 0:
                                        d = ops[
                                            0].Height.Value + self.displacement.Length
                                    else:
                                        d = ops[
                                            0].Height.Value - self.displacement.Length
                                    _cmd = _doc + ops[0].Name
                                    _cmd += ".Height=" + str(d)
                                    _pl = _doc + ops[0].Name
                                    _pl += ".Placement.Base=FreeCAD."
                                    _pl += str(ops[0].Placement.Base.add(
                                        self.displacement))
                                    commitops.append(_cmd)
                                    commitops.append(_pl)
                                    done = True
                        if not done:
                            # otherwise create a wire copy and stretch it instead
                            _msg(
                                translate("draft",
                                          "Turning one Rectangle into a Wire"))
                            pts = []
                            vts = ops[0].Shape.Vertexes
                            for i in range(4):
                                if ops[1][i] == False:
                                    pts.append(vts[i].Point)
                                else:
                                    pts.append(vts[i].Point.add(
                                        self.displacement))
                            pts = str(pts).replace("Vector ", "FreeCAD.Vector")
                            _cmd = "Draft.make_wire"
                            _cmd += "(" + pts + ", closed=True, "
                            _cmd += "face=" + str(ops[0].MakeFace)
                            _cmd += ")"
                            _format = "Draft.formatObject"
                            _format += "(w, "
                            _format += _doc + ops[0].Name
                            _format += ")"
                            _hide = _doc + ops[0].Name + ".ViewObject.hide()"
                            commitops.append("w = " + _cmd)
                            commitops.append(_format)
                            commitops.append(_hide)
                    else:
                        _pl = _doc + ops[0].Name
                        _pl += ".Placement.Base=FreeCAD."
                        _pl += str(ops[0].Placement.Base.add(
                            self.displacement))
                        commitops.append(_pl)
        if commitops:
            commitops.append("FreeCAD.ActiveDocument.recompute()")
            Gui.addModule("Draft")
            self.commit(translate("draft", "Stretch"), commitops)
        self.finish()
Ejemplo n.º 40
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.º 41
0
    def execute(self,obj):
        
        if self.clone(obj):
            return
        
        if not obj.Base:
            return
        if not obj.Base.Shape:
            return
        if not obj.Base.Shape.Wires:
            return

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

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