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]
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]
def execute(self, obj): self.Width = float(obj.Width) self.Height = float(obj.Height) self.Length = float(obj.Length) self.Radius = float(obj.Radius) self.Thickness = float(obj.Thickness) self.Chamfer = obj.Chamfer Result = None # base rectangle vertices and walls after a cut V1_FSQ = [ App.Vector(0, 0, 0), App.Vector(self.Width, 0, 0), App.Vector(self.Width, self.Length, 0), App.Vector(0.0, self.Length, 0), App.Vector(0, 0, 0) ] # cut middle part to make walls V2_FSQ = [ App.Vector(self.Thickness, self.Thickness, 0), App.Vector(self.Width - self.Thickness, self.Thickness, 0), App.Vector(self.Width - self.Thickness, self.Length - self.Thickness, 0), App.Vector(self.Thickness, self.Length - self.Thickness, 0), App.Vector(self.Thickness, self.Thickness, 0) ] W1 = Part.makePolygon(V1_FSQ) W11 = DraftGeomUtils.filletWire(W1, self.Radius, chamfer=self.Chamfer) firstFace1 = Part.Face(W11) # one used with secondFace to cut firstFace2 = firstFace1.copy() # Other used to make the bottom W2 = Part.makePolygon(V2_FSQ) W22 = DraftGeomUtils.filletWire(W2, self.Radius, chamfer=self.Chamfer) secondFace = Part.Face(W22) resultButtom = firstFace1.cut(secondFace) extrude1 = resultButtom.extrude(App.Vector(0, 0, self.Height)) extrude2 = firstFace2.extrude(App.Vector(0, 0, self.Thickness)) fused = extrude1.fuse(extrude2) Result = fused.removeSplitter() obj.Shape = Result
def execute(self, obj): if (obj.FacesNumber >= 3) and (obj.Radius.Value > 0): import Part plm = obj.Placement angle = (math.pi * 2) / obj.FacesNumber if obj.DrawMode == 'inscribed': delta = obj.Radius.Value else: delta = obj.Radius.Value / math.cos(angle / 2.0) pts = [App.Vector(delta, 0, 0)] for i in range(obj.FacesNumber - 1): ang = (i + 1) * angle pts.append( App.Vector(delta * math.cos(ang), delta * math.sin(ang), 0)) pts.append(pts[0]) shape = Part.makePolygon(pts) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: shape = Part.Face(shape) obj.Shape = shape if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area obj.Placement = plm obj.positionBySupport()
def smBase(thk=2.0, length=10.0, radius=1.0, Side="Inside", MainObject=None): WireList = MainObject.Shape.Wires[0] #print(sketch_normal) if WireList.isClosed(): sketch_face = Part.makeFace(MainObject.Shape.Wires, "Part::FaceMakerBullseye") wallSolid = sketch_face.extrude(sketch_face.normalAt(0, 0) * thk) else: if len(WireList.Edges) > 1: if Side == "Inside": wire = WireList.makeOffset2D(thk / 2.0, openResult=True, join=2) elif Side == "Outside": wire = WireList.makeOffset2D(-thk / 2.0, openResult=True, join=2) else: wire = WireList #Part.show(wire) filletedWire = DraftGeomUtils.filletWire(wire, (radius + thk / 2)) #Part.show(filletedWire) offsetwire = filletedWire.makeOffset2D(thk / 2.0, openResult=True) #Part.show(offsetwire) sketch_face = offsetwire.makeOffset2D(thk, openResult=True, fill=True) #Part.show(sketch_face) Edge_Dir = sketch_face.normalAt(0, 0) offsetSolid = offsetwire.extrude(Edge_Dir * length) CutList = [] for x in offsetSolid.Faces: if issubclass(type(x.Surface), Part.Plane): offsetSolid = x.extrude(x.normalAt(0, 0) * -thk) CutList.append(offsetSolid) #Part.show(offsetSolid) wallSolid = sketch_face.extrude(Edge_Dir * length) offsetSolids = CutList[0].multiFuse(CutList[1:]) wallSolid = wallSolid.fuse(offsetSolids) else: if MainObject.TypeId == 'Sketcher::SketchObject': mat = MainObject.getGlobalPlacement() normal = mat.multVec(FreeCAD.Vector(0, 0, 1)) sketch_face = MainObject.Shape.Wires[0].extrude(normal * -length) #Part.show(sketch_face) wallSolid = sketch_face.extrude( sketch_face.Faces[0].normalAt(0, 0) * -thk) Gui.ActiveDocument.getObject(MainObject.Name).Visibility = False return wallSolid
def execute(self, obj): self.Height = float(obj.Height) self.Radius = float(obj.Radius) self.SideOneRadius = float(obj.SideOneRadius) self.Thickness = float(obj.Thickness) self.Chamfer = obj.Chamfer Result = None # base None-uniformed vertices and walls after a cut V1_FSQ = [] V1_FSQ = self.Vertices W1 = Part.makePolygon(V1_FSQ) if self.Radius > 0: W11 = DraftGeomUtils.filletWire(W1, self.Radius, chamfer=self.Chamfer) else: W11 = W1 firstFace1 = Part.Face(W11) # One used with secondFace to cut if self.SideOneRadius > 0: W12 = DraftGeomUtils.filletWire(W1, self.SideOneRadius, chamfer=self.Chamfer) else: W12 = W1 # Other used to make the bottom firstFace2 = Part.Face(W12) secondFace = firstFace2.makeOffset2D(-self.Thickness) resultButtom = firstFace1.cut(secondFace) extrude1 = resultButtom.extrude(App.Vector(0, 0, self.Height)) extrude2 = firstFace2.extrude(App.Vector(0, 0, self.Thickness)) fused = extrude1.fuse(extrude2) Result = fused.removeSplitter() obj.Shape = Result
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)
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
def getUShapeRebarSVGData( rebar, view_plane, rebars_svg, rebars_stroke_width, rebars_color_style, longitudinal_line_dia=None, ): """getUShapeRebarSVGData(UShapeRebar, ViewPlane, RebarsSVG, RebarsStrokeWidth, RebarsColorStyle, longitudinal_line_dia): Returns dictionary containing UShape rebar svg data. rebars_color_style can be: - "shape color" to select color of rebar shape - color name or hex value of color Returns dictionary format: { "svg": u_rebar_svg, "visibility": is_rebar_visible, } """ if longitudinal_line_dia is None: longitudinal_line_dia = 2 * 2 * rebars_stroke_width rebars_color = getRebarColor(rebar, rebars_color_style) u_rebar_svg = ElementTree.Element("g", attrib={"id": str(rebar.Name)}) is_rebar_visible = False drawing_plane_normal = view_plane.axis if round(drawing_plane_normal.cross(getRebarsSpanAxis(rebar)).Length) == 0: basewire = rebar.Base.Shape.Wires[0].copy() basewire.Placement = rebar.PlacementList[0].multiply( basewire.Placement) edges = Part.__sortEdges__( DraftGeomUtils.filletWire( basewire, rebar.Rounding * rebar.Diameter.Value, ).Edges) for edge in edges: if DraftGeomUtils.geomType(edge) == "Line": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) if round(p1.x) == round(p2.x) and round(p1.y) == round(p2.y): edge_svg = getPointSVG(p1, radius=longitudinal_line_dia / 2, fill=rebars_color) else: edge_svg = getLineSVG(p1, p2, rebars_stroke_width, rebars_color) if not isLineInSVG(p1, p2, rebars_svg): is_rebar_visible = True if is_rebar_visible: u_rebar_svg.append(edge_svg) is_rebar_visible = True elif DraftGeomUtils.geomType(edge) == "Circle": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) if round(p1.x) == round(p2.x) or round(p1.y) == round(p2.y): edge_svg = getLineSVG(p1, p2, rebars_stroke_width, rebars_color) if not isLineInSVG(p1, p2, rebars_svg): is_rebar_visible = True else: edge_svg = getRoundEdgeSVG(edge, view_plane, rebars_stroke_width, rebars_color) if not isRoundCornerInSVG( edge, rebar.Rounding * rebar.Diameter.Value, view_plane, rebars_svg, ): is_rebar_visible = True if is_rebar_visible: u_rebar_svg.append(edge_svg) else: basewire = rebar.Base.Shape.Wires[0] for placement in rebar.PlacementList: wire = basewire.copy() wire.Placement = placement.multiply(basewire.Placement) edges = Part.__sortEdges__( DraftGeomUtils.filletWire( wire, rebar.Rounding * rebar.Diameter.Value, ).Edges) for edge in edges: if DraftGeomUtils.geomType(edge) == "Line": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) if round(p1.x) == round(p2.x) and round(p1.y) == round( p2.y): edge_svg = getPointSVG( p1, radius=longitudinal_line_dia / 2, fill=rebars_color, ) else: edge_svg = getLineSVG(p1, p2, rebars_stroke_width, rebars_color) if not isLineInSVG(p1, p2, rebars_svg): is_rebar_visible = True if is_rebar_visible or not isLineInSVG(p1, p2, rebars_svg): u_rebar_svg.append(edge_svg) is_rebar_visible = True elif DraftGeomUtils.geomType(edge) == "Circle": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) if round(p1.x) == round(p2.x) or round(p1.y) == round( p2.y): edge_svg = getLineSVG(p1, p2, rebars_stroke_width, rebars_color) if not isLineInSVG(p1, p2, rebars_svg): is_rebar_visible = True else: edge_svg = getRoundEdgeSVG(edge, view_plane, rebars_stroke_width, rebars_color) if not isRoundCornerInSVG( edge, rebar.Rounding * rebar.Diameter.Value, view_plane, rebars_svg, ): is_rebar_visible = True if is_rebar_visible: u_rebar_svg.append(edge_svg) return { "svg": u_rebar_svg, "visibility": is_rebar_visible, }
def getStirrupSVGData(rebar, view_plane, rebars_svg, rebars_stroke_width, rebars_color_style): """getStirrupSVGData(StirrupRebar, ViewPlane, RebarsSVG, RebarsStrokeWidth, RebarsColorStyle): Returns dictionary containing stirrup svg data. rebars_color_style can be: - "shape color" to select color of rebar shape - color name or hex value of color Returns dictionary format: { "svg": stirrup_svg, "visibility": is_rebar_visible, } """ rebars_color = getRebarColor(rebar, rebars_color_style) stirrup_svg = ElementTree.Element("g", attrib={"id": str(rebar.Name)}) is_rebar_visible = False drawing_plane_normal = view_plane.axis stirrup_span_axis = getRebarsSpanAxis(rebar) if round(drawing_plane_normal.cross(stirrup_span_axis).Length) == 0: basewire = rebar.Base.Shape.Wires[0].copy() basewire.Placement = rebar.PlacementList[0].multiply( basewire.Placement) edges = Part.__sortEdges__( DraftGeomUtils.filletWire( basewire, rebar.Rounding * rebar.Diameter.Value, ).Edges) for edge in edges: if DraftGeomUtils.geomType(edge) == "Line": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) edge_svg = getLineSVG(p1, p2, rebars_stroke_width, rebars_color) if is_rebar_visible or not isLineInSVG(p1, p2, rebars_svg): stirrup_svg.append(edge_svg) is_rebar_visible = True elif DraftGeomUtils.geomType(edge) == "Circle": edge_svg = getRoundEdgeSVG(edge, view_plane, rebars_stroke_width, rebars_color) if is_rebar_visible or not isRoundCornerInSVG( edge, rebar.Rounding * rebar.Diameter.Value, view_plane, rebars_svg, ): stirrup_svg.append(edge_svg) is_rebar_visible = True else: if round(stirrup_span_axis.cross(view_plane.u).Length) == 0: stirrup_alignment = "V" else: stirrup_alignment = "H" basewire = DraftGeomUtils.filletWire( rebar.Base.Shape.Wires[0], rebar.Rounding * rebar.Diameter.Value) for placement in rebar.PlacementList: wire = basewire.copy() wire.Placement = placement.multiply(basewire.Placement) p1, p2 = getStirrupSVGPoints(wire, stirrup_alignment, view_plane) rebar_svg = getLineSVG(p1, p2, rebars_stroke_width, rebars_color) if not isLineInSVG(p1, p2, rebars_svg): is_rebar_visible = True if is_rebar_visible: stirrup_svg.append(rebar_svg) return { "svg": stirrup_svg, "visibility": is_rebar_visible, }
def execute(self, obj): import Part plm = obj.Placement if obj.Base and (not obj.Tool): if obj.Base.isDerivedFrom("Sketcher::SketchObject"): shape = obj.Base.Shape.copy() if obj.Base.Shape.isClosed(): if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: shape = Part.Face(shape) obj.Shape = shape elif obj.Base and obj.Tool: if hasattr(obj.Base, 'Shape') and hasattr(obj.Tool, 'Shape'): if (not obj.Base.Shape.isNull()) and ( not obj.Tool.Shape.isNull()): sh1 = obj.Base.Shape.copy() sh2 = obj.Tool.Shape.copy() shape = sh1.fuse(sh2) if DraftGeomUtils.isCoplanar(shape.Faces): shape = DraftGeomUtils.concatenate(shape) obj.Shape = shape p = [] for v in shape.Vertexes: p.append(v.Point) if obj.Points != p: obj.Points = p elif obj.Points: if obj.Points[0] == obj.Points[-1]: if not obj.Closed: obj.Closed = True obj.Points.pop() if obj.Closed and (len(obj.Points) > 2): pts = obj.Points if hasattr(obj, "Subdivisions"): if obj.Subdivisions > 0: npts = [] for i in range(len(pts)): p1 = pts[i] npts.append(pts[i]) if i == len(pts) - 1: p2 = pts[0] else: p2 = pts[i + 1] v = p2.sub(p1) v = DraftVecUtils.scaleTo( v, v.Length / (obj.Subdivisions + 1)) for j in range(obj.Subdivisions): npts.append( p1.add(App.Vector(v).multiply(j + 1))) pts = npts shape = Part.makePolygon(pts + [pts[0]]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w try: if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: shape = Part.Face(shape) except Part.OCCError: pass else: edges = [] pts = obj.Points[1:] lp = obj.Points[0] for p in pts: if not DraftVecUtils.equals(lp, p): if hasattr(obj, "Subdivisions"): if obj.Subdivisions > 0: npts = [] v = p.sub(lp) v = DraftVecUtils.scaleTo( v, v.Length / (obj.Subdivisions + 1)) edges.append( Part.LineSegment(lp, lp.add(v)).toShape()) lv = lp.add(v) for j in range(obj.Subdivisions): edges.append( Part.LineSegment(lv, lv.add(v)).toShape()) lv = lv.add(v) else: edges.append(Part.LineSegment(lp, p).toShape()) else: edges.append(Part.LineSegment(lp, p).toShape()) lp = p try: shape = Part.Wire(edges) except Part.OCCError: print("Error wiring edges") shape = None if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w if shape: obj.Shape = shape if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area if hasattr(obj, "Length"): obj.Length = shape.Length obj.Placement = plm obj.positionBySupport() self.onChanged(obj, "Placement")
def execute(self, obj): """This method is run when the object is created or recomputed.""" import Part if (obj.Length.Value == 0) or (obj.Height.Value == 0): obj.positionBySupport() return plm = obj.Placement shape = None if hasattr(obj, "Rows") and hasattr(obj, "Columns"): # TODO: verify if this is needed: if obj.Rows > 1: rows = obj.Rows else: rows = 1 if obj.Columns > 1: columns = obj.Columns else: columns = 1 # TODO: till here if (rows > 1) or (columns > 1): shapes = [] l = obj.Length.Value / columns h = obj.Height.Value / rows for i in range(columns): for j in range(rows): p1 = App.Vector(i * l, j * h, 0) p2 = App.Vector(p1.x + l, p1.y, p1.z) p3 = App.Vector(p1.x + l, p1.y + h, p1.z) p4 = App.Vector(p1.x, p1.y + h, p1.z) p = Part.makePolygon([p1, p2, p3, p4, p1]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire( p, obj.ChamferSize.Value, chamfer=True) if w: p = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire( p, obj.FilletRadius.Value) if w: p = w if hasattr(obj, "MakeFace"): if obj.MakeFace: p = Part.Face(p) shapes.append(p) if shapes: shape = Part.makeCompound(shapes) if not shape: p1 = App.Vector(0, 0, 0) p2 = App.Vector(p1.x + obj.Length.Value, p1.y, p1.z) p3 = App.Vector(p1.x + obj.Length.Value, p1.y + obj.Height.Value, p1.z) p4 = App.Vector(p1.x, p1.y + obj.Height.Value, p1.z) shape = Part.makePolygon([p1, p2, p3, p4, p1]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: shape = Part.Face(shape) obj.Shape = shape if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area obj.Placement = plm obj.positionBySupport()
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
def getRebarShapeSVG( rebar, view_direction: Union[FreeCAD.Vector, WorkingPlane.Plane] = FreeCAD.Vector(0, 0, 0), include_mark: bool = True, stirrup_extended_edge_offset: float = 2, rebar_stroke_width: float = 0.35, rebar_color_style: str = "shape color", include_dimensions: bool = True, rebar_dimension_units: str = "mm", rebar_length_dimension_precision: int = 0, include_units_in_dimension_label: bool = False, bent_angle_dimension_exclude_list: Union[Tuple[float, ...], List[float]] = ( 45, 90, 180, ), dimension_font_family: str = "DejaVu Sans", dimension_font_size: float = 2, helical_rebar_dimension_label_format: str = "%L,r=%R,pitch=%P", scale: float = 1, max_height: float = 0, max_width: float = 0, side_padding: float = 1, horizontal_shape: bool = False, ) -> ElementTree.Element: """Generate and return rebar shape svg. Parameters ---------- rebar: <ArchRebar._Rebar> or <rebar2.BaseRebar> Rebar to generate its shape svg. view_direction: FreeCAD.Vector or WorkingPlane.Plane, optional The view point direction for rebar shape. Default is FreeCAD.Vector(0, 0, 0) to automatically choose view_direction. include_mark: bool, optional If True, then rebar.Mark will be included in rebar shape svg. Default is True. stirrup_extended_edge_offset: float, optional The offset of extended end edges of stirrup, so that end edges of stirrup with 90 degree bent angle do not overlap with stirrup edges. Default is 2. rebar_stroke_width: float, optional The stroke-width of rebar in svg. Default is 0.35 rebar_color_style: {"shape color", "color_name", "hex_value_of_color"} The color style of rebar. "shape color" means select color of rebar shape. include_dimensions: bool, optional If True, then each rebar edge dimensions and bent angle dimensions will be included in rebar shape svg. rebar_dimension_units: str, optional The units to be used for rebar length dimensions. Default is "mm". rebar_length_dimension_precision: int, optional The number of decimals that should be shown for rebar length as dimension label. Set it to None to use user preferred unit precision from FreeCAD unit preferences. Default is 0 include_units_in_dimension_label: bool, optional If it is True, then rebar length units will be shown in dimension label. Default is False. bent_angle_dimension_exclude_list: list or tuple of float, optional The list of bent angles to not include their dimensions. Default is (45, 90, 180). dimension_font_family: str, optional The font-family of dimension text. Default is "DejaVu Sans". dimension_font_size: float, optional The font-size of dimension text. Default is 2 helical_rebar_dimension_label_format: str, optional The format of helical rebar dimension label. %L -> Length of helical rebar %R -> Helix radius of helical rebar %P -> Helix pitch of helical rebar Default is "%L,r=%R,pitch=%P". scale: float, optional The scale value to scale rebar svg. The scale parameter helps to scale down rebar_stroke_width and dimension_font_size to make them resolution independent. If max_height or max_width is set to non-zero value, then scale parameter will be ignored. Default is 1 max_height: float, optional The maximum height of rebar shape svg. Default is 0 to set rebar shape svg height based on scale parameter. max_width: float, optional The maximum width of rebar shape svg. Default is 0 to set rebar shape svg width based on scale parameter. side_padding: float, optional The padding on each side of rebar shape. Default is 1. horizontal_shape: bool, optional If True, then rebar shape will be made horizontal by rotating max length edge of rebar shape. Default is False. Returns ------- ElementTree.Element The generated rebar shape svg. """ if isinstance(view_direction, FreeCAD.Vector): if DraftVecUtils.isNull(view_direction): if (hasattr(rebar, "RebarShape") and rebar.RebarShape == "HelicalRebar"): view_direction = rebar.Base.Placement.Rotation.multVec( FreeCAD.Vector(0, -1, 0)) if hasattr(rebar, "Direction") and not DraftVecUtils.isNull( rebar.Direction): view_direction = FreeCAD.Vector(rebar.Direction) view_direction.normalize() else: view_direction = getRebarsSpanAxis(rebar) view_plane = getSVGPlaneFromAxis(view_direction) elif isinstance(view_direction, WorkingPlane.Plane): view_plane = view_direction else: FreeCAD.Console.PrintError( "Invalid view_direction type. Supported view_direction types: " "FreeCAD.Vector, WorkingPlane.Plane\n") return ElementTree.Element("g") if rebar_length_dimension_precision is None: # Get user preferred unit precision precision: int = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Units").GetInt("Decimals") else: precision = abs(int(rebar_length_dimension_precision)) rebar_color = getRebarColor(rebar, rebar_color_style) # Create required svg elements svg = getSVGRootElement() rebar_shape_svg = ElementTree.Element("g", attrib={"id": str(rebar.Name)}) svg.append(rebar_shape_svg) rebar_edges_svg = ElementTree.Element("g") edge_dimension_svg = ElementTree.Element("g") rebar_shape_svg.extend([rebar_edges_svg, edge_dimension_svg]) # Get basewire and fillet_basewire (basewire with round edges) basewire = rebar.Base.Shape.Wires[0].copy() fillet_radius = rebar.Rounding * rebar.Diameter.Value if fillet_radius: fillet_basewire = DraftGeomUtils.filletWire(basewire, fillet_radius) else: fillet_basewire = basewire ( rebar_shape_min_x, rebar_shape_min_y, rebar_shape_max_x, rebar_shape_max_y, ) = getVertexesMinMaxXY(fillet_basewire.Vertexes, view_plane) # If rebar shape should be horizontal and its width is less than its # height, then we should rotate basewire to make rebar shape horizontal rebar_shape_rotation_angle = 0 if horizontal_shape: line_type_edges = [ edge for edge in basewire.Edges if DraftGeomUtils.geomType(edge) == "Line" ] if line_type_edges: max_length_edge = max(line_type_edges, key=lambda x: x.Length) rebar_shape_rotation_angle = math.degrees( DraftVecUtils.angle( max_length_edge.lastVertex().Point.sub( max_length_edge.firstVertex().Point), view_plane.u, view_plane.axis, )) elif (rebar_shape_max_x - rebar_shape_min_x) < (rebar_shape_max_y - rebar_shape_min_y): rebar_shape_rotation_angle = -90 basewire.rotate(basewire.CenterOfMass, view_plane.axis, rebar_shape_rotation_angle) fillet_radius = rebar.Rounding * rebar.Diameter.Value if fillet_radius: fillet_basewire = DraftGeomUtils.filletWire( basewire, fillet_radius) else: fillet_basewire = basewire ( rebar_shape_min_x, rebar_shape_min_y, rebar_shape_max_x, rebar_shape_max_y, ) = getVertexesMinMaxXY(fillet_basewire.Vertexes, view_plane) # Check if stirrup will be having extended edges separated apart if (hasattr(rebar, "RebarShape") and rebar.RebarShape == "Stirrup" and hasattr(rebar, "BentAngle") and rebar.BentAngle == 90): apply_stirrup_extended_edge_offset = True else: apply_stirrup_extended_edge_offset = False # Apply max_height and max_width of rebar shape svg And calculate scaling # factor rebar_shape_height = (rebar_shape_max_y - rebar_shape_min_y) or 1 rebar_shape_width = (rebar_shape_max_x - rebar_shape_min_x) or 1 h_scaling_factor = v_scaling_factor = scale if max_height: v_scaling_factor = ( max_height - dimension_font_size * ((2 if include_mark else 0) + (2 if include_dimensions else 0)) - 2 * side_padding - (stirrup_extended_edge_offset if apply_stirrup_extended_edge_offset and (round( getProjectionToSVGPlane( Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point, view_plane, ).y) in (round(rebar_shape_min_y), round(rebar_shape_max_y))) else 0)) / rebar_shape_height if max_width: h_scaling_factor = ( max_width - dimension_font_size * (2 if include_dimensions else 0) - 2 * side_padding - (stirrup_extended_edge_offset if apply_stirrup_extended_edge_offset and (round( getProjectionToSVGPlane( Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point, view_plane, ).x) in (round(rebar_shape_min_x), round(rebar_shape_max_x))) else 0)) / rebar_shape_width scale = min(h_scaling_factor, v_scaling_factor) svg_height = ( rebar_shape_height * scale + dimension_font_size * ((2 if include_mark else 0) + (2 if include_dimensions else 0)) + 2 * side_padding + (stirrup_extended_edge_offset if apply_stirrup_extended_edge_offset and (round( getProjectionToSVGPlane( Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point, view_plane, ).y) in (round(rebar_shape_min_y), round(rebar_shape_max_y))) else 0)) svg_width = ( rebar_shape_width * scale + dimension_font_size * (2 if include_dimensions else 0) + 2 * side_padding + (stirrup_extended_edge_offset if apply_stirrup_extended_edge_offset and (round( getProjectionToSVGPlane( Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point, view_plane, ).x) in (round(rebar_shape_min_x), round(rebar_shape_max_x))) else 0)) # Move (min_x, min_y) point in svg plane to (0, 0) so that entire basewire # should be visible in svg view box and apply required scaling translate_x = round( -(rebar_shape_min_x - (dimension_font_size if include_dimensions else 0) / scale - side_padding / scale - (stirrup_extended_edge_offset / scale if apply_stirrup_extended_edge_offset and (round( getProjectionToSVGPlane( Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point, view_plane, ).x) == round(rebar_shape_min_x)) else 0))) translate_y = round( -(rebar_shape_min_y - ((2 if include_mark else 0) + (1 if include_dimensions else 0)) * dimension_font_size / scale - side_padding / scale - (stirrup_extended_edge_offset / scale if apply_stirrup_extended_edge_offset and (round( getProjectionToSVGPlane( Part.__sortEdges__(basewire.Edges)[0].firstVertex().Point, view_plane, ).y) == round(rebar_shape_min_y)) else 0))) rebar_shape_svg.set( "transform", "scale({}) translate({} {})".format(scale, translate_x, translate_y), ) svg.set("width", "{}mm".format(round(svg_width))) svg.set("height", "{}mm".format(round(svg_height))) svg.set("viewBox", "0 0 {} {}".format(round(svg_width), round(svg_height))) # Scale down rebar_stroke_width and dimension_font_size to make them # resolution independent rebar_stroke_width /= scale dimension_font_size /= scale # Include rebar.Mark in rebar shape svg if include_mark: if hasattr(rebar, "Mark"): mark = rebar.Mark elif hasattr(rebar, "MarkNumber"): mark = rebar.MarkNumber else: mark = "" rebar_shape_svg.append( getSVGTextElement( mark, rebar_shape_min_x, rebar_shape_min_y - (0.5 + bool(include_dimensions)) * dimension_font_size, dimension_font_family, 1.5 * dimension_font_size, )) if hasattr(rebar, "RebarShape") and rebar.RebarShape == "HelicalRebar": helical_rebar_shape_svg = Draft.getSVG( rebar, direction=view_plane, linewidth=rebar_stroke_width, fillstyle="none", color=rebar_color, ) if helical_rebar_shape_svg: helical_rebar_shape_svg_element = ElementTree.fromstring( "<g>{}</g>".format(helical_rebar_shape_svg)) rebar_edges_svg.append(helical_rebar_shape_svg_element) helical_rebar_center = getProjectionToSVGPlane( rebar.Base.Shape.CenterOfMass, view_plane) helical_rebar_shape_svg_element.set( "transform", "rotate({} {} {})".format( rebar_shape_rotation_angle, helical_rebar_center.x, helical_rebar_center.y, ), ) if include_dimensions: # Create rebar dimension svg top_mid_point = FreeCAD.Vector( (rebar_shape_min_x + rebar_shape_max_x) / 2, rebar_shape_min_y) helical_rebar_length = str( round( FreeCAD.Units.Quantity("{}mm".format( rebar.Base.Shape.Wires[0].Length)).getValueAs( rebar_dimension_units).Value, precision, )) helix_radius = str( round( rebar.Base.Radius.getValueAs(rebar_dimension_units).Value, precision, )) helix_pitch = str( round( rebar.Base.Pitch.getValueAs(rebar_dimension_units).Value, precision, )) if "." in helical_rebar_length: helical_rebar_length = helical_rebar_length.rstrip("0").rstrip( ".") if "." in helix_radius: helix_radius = helix_radius.rstrip("0").rstrip(".") if "." in helix_pitch: helix_pitch = helix_pitch.rstrip("0").rstrip(".") if include_units_in_dimension_label: helical_rebar_length += rebar_dimension_units helix_radius += rebar_dimension_units helix_pitch += rebar_dimension_units edge_dimension_svg.append( getSVGTextElement( helical_rebar_dimension_label_format.replace( "%L", helical_rebar_length).replace( "%R", helix_radius).replace("%P", helix_pitch), top_mid_point.x, top_mid_point.y - rebar_stroke_width * 2, dimension_font_family, dimension_font_size, "middle", )) else: if stirrup_extended_edge_offset and apply_stirrup_extended_edge_offset: basewire = getBasewireOfStirrupWithExtendedEdges( rebar, view_plane, stirrup_extended_edge_offset / scale) basewire.rotate( basewire.CenterOfMass, view_plane.axis, rebar_shape_rotation_angle, ) fillet_radius = rebar.Rounding * rebar.Diameter.Value if fillet_radius: fillet_basewire = DraftGeomUtils.filletWire( basewire, fillet_radius) else: fillet_basewire = basewire edges = Part.__sortEdges__(fillet_basewire.Edges) straight_edges = Part.__sortEdges__(rebar.Base.Shape.Wires[0].Edges) for edge in list(straight_edges): if DraftGeomUtils.geomType(edge) != "Line": straight_edges.remove(edge) current_straight_edge_index = 0 for edge_index, edge in enumerate(edges): if DraftGeomUtils.geomType(edge) == "Line": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) # Create Edge svg if round(p1.x) == round(p2.x) and round(p1.y) == round(p2.y): edge_svg = getPointSVG(p1, radius=2 * rebar_stroke_width, fill=rebar_color) else: edge_svg = getLineSVG(p1, p2, rebar_stroke_width, rebar_color) if include_dimensions: # Create edge dimension svg mid_point = FreeCAD.Vector((p1.x + p2.x) / 2, (p1.y + p2.y) / 2) dimension_rotation = (math.degrees( math.atan((p2.y - p1.y) / (p2.x - p1.x))) if round(p2.x) != round(p1.x) else -90) edge_length = str( round( FreeCAD.Units.Quantity("{}mm".format( straight_edges[current_straight_edge_index]. Length)).getValueAs( rebar_dimension_units).Value, precision, )) if "." in edge_length: edge_length = edge_length.rstrip("0").rstrip(".") if include_units_in_dimension_label: edge_length += rebar_dimension_units edge_dimension_svg.append( getSVGTextElement( edge_length, mid_point.x, mid_point.y - rebar_stroke_width * 2, dimension_font_family, dimension_font_size, "middle", )) edge_dimension_svg[-1].set( "transform", "rotate({} {} {})".format( dimension_rotation, round(mid_point.x), round(mid_point.y), ), ) current_straight_edge_index += 1 if (0 <= edge_index - 1 and DraftGeomUtils.geomType( edges[edge_index - 1]) == "Line"): radius = max(fillet_radius, dimension_font_size * 0.8) bent_angle_svg = getEdgesAngleSVG( edges[edge_index - 1], edge, radius, view_plane, dimension_font_family, dimension_font_size * 0.8, bent_angle_dimension_exclude_list, 0.2 / scale, ) edge_dimension_svg.append(bent_angle_svg) elif DraftGeomUtils.geomType(edge) == "Circle": p1 = getProjectionToSVGPlane(edge.Vertexes[0].Point, view_plane) p2 = getProjectionToSVGPlane(edge.Vertexes[1].Point, view_plane) if round(p1.x) == round(p2.x) or round(p1.y) == round(p2.y): edge_svg = getLineSVG(p1, p2, rebar_stroke_width, rebar_color) else: edge_svg = getRoundEdgeSVG(edge, view_plane, rebar_stroke_width, rebar_color) if include_dimensions: # Create bent angle svg if 0 <= edge_index - 1 and edge_index + 1 < len(edges): prev_edge = edges[edge_index - 1] next_edge = edges[edge_index + 1] if (DraftGeomUtils.geomType(prev_edge) == DraftGeomUtils.geomType(next_edge) == "Line"): radius = max(fillet_radius, dimension_font_size * 0.8) bent_angle_svg = getEdgesAngleSVG( prev_edge, next_edge, radius, view_plane, dimension_font_family, dimension_font_size * 0.8, bent_angle_dimension_exclude_list, 0.2 / scale, ) edge_dimension_svg.append(bent_angle_svg) else: edge_svg = ElementTree.Element("g") rebar_edges_svg.append(edge_svg) return svg
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)