def makeRebar(baseobj,sketch,diameter=None,amount=1,offset=None,name="Rebar"): """makeRebar(baseobj,sketch,[diameter,amount,offset,name]): adds a Reinforcement Bar object to the given structural object, using the given sketch as profile.""" p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) obj.Label = translate("Arch",name) _Rebar(obj) if FreeCAD.GuiUp: _ViewProviderRebar(obj.ViewObject) if hasattr(sketch,"Support"): if sketch.Support: if isinstance(sketch.Support,tuple): if sketch.Support[0] == baseobj: sketch.Support = None elif sketch.Support == baseobj: sketch.Support = None obj.Base = sketch if FreeCAD.GuiUp: sketch.ViewObject.hide() a = baseobj.Armatures a.append(obj) baseobj.Armatures = a if diameter: obj.Diameter = diameter else: obj.Diameter = p.GetFloat("RebarDiameter",6) obj.Amount = amount if offset: obj.OffsetStart = offset obj.OffsetEnd = offset else: obj.OffsetStart = p.GetFloat("RebarOffset",30) obj.OffsetEnd = p.GetFloat("RebarOffset",30) ArchCommands.fixDAG(obj) return obj
def removeFromComponent(compobject, subobject): """removeFromComponent(compobject,subobject): subtracts subobject from the given component. If the subobject is already part of the component (as addition, subtraction, etc... it is removed. Otherwise, it is added as a subtraction.""" if compobject == subobject: return found = False attribs = ["Additions", "Subtractions", "Objects", "Components", "Base", "Axes", "Fixtures"] for a in attribs: if hasattr(compobject, a): if a == "Base": if subobject == getattr(compobject, a): setattr(compobject, a, None) subobject.ViewObject.show() found = True else: if subobject in getattr(compobject, a): l = getattr(compobject, a) l.remove(subobject) setattr(compobject, a, l) subobject.ViewObject.show() found = True if not found: if hasattr(compobject, "Subtractions"): l = compobject.Subtractions l.append(subobject) compobject.Subtractions = l if (Draft.getType(subobject) != "Window") and (not Draft.isClone(subobject, "Window", True)): ArchCommands.setAsSubcomponent(subobject)
def Activated(self): sel = FreeCADGui.Selection.getSelection() p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") link = p.GetBool("FreeLinking",False) siteobj = [] warning = False for obj in sel : if Draft.getType(obj) == "Building": siteobj.append(obj) else : if link == True : siteobj.append(obj) else: warning = True if warning : message = translate( "Arch" , "Please select only Building objects or nothing!\n\ Site are not allowed to accept other object than Building.\n\ Other objects will be removed from the selection.\n\ You can change that in the preferences." ) ArchCommands.printMessage( message ) if sel and len(siteobj) == 0: message = translate( "Arch" , "There is no valid object in the selection.\n\ Site creation aborted." ) ArchCommands.printMessage( message ) else : ss = "[ " for o in siteobj: ss += "FreeCAD.ActiveDocument." + o.Name + ", " ss += "]" FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Site")) FreeCADGui.addModule("Arch") FreeCADGui.doCommand("Arch.makeSite("+ss+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute()
def Activated(self): sel = FreeCADGui.Selection.getSelection() p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") link = p.GetBool("FreeLinking",False) floorobj = [] warning = False for obj in sel : if not Draft.getType(obj) in ["Site", "Building"] : floorobj.append(obj) else : if link == True : floorobj.append(obj) else: warning = True if warning : message = translate( "Arch" , "You can put anything but Site, Building, Floor object in a Floor object.\n\ Floor object are not allowed to accept Site or Building object.\n\ Site, Building and Floor objects will be removed from the selection.\n\ You can change that in the preferences.\n" ) ArchCommands.printMessage( message ) if sel and len(floorobj) == 0: message = translate( "Arch" , "There is no valid object in the selection.\n\ Floor creation aborted.\n" ) ArchCommands.printMessage( message ) else : ss = "[ " for o in floorobj: ss += "FreeCAD.ActiveDocument." + o.Name + ", " ss += "]" FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Floor")) FreeCADGui.addModule("Arch") FreeCADGui.doCommand("Arch.makeFloor("+ss+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute()
def Activated(self): sel = FreeCADGui.Selection.getSelection() ok = False if (len(sel) == 1): if Draft.getType(sel[0]) in ["Cell","Building","Floor"]: FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Type conversion"))) FreeCADGui.doCommand("import Arch") FreeCADGui.doCommand("obj = Arch.makeSite()") FreeCADGui.doCommand("Arch.copyProperties(FreeCAD.ActiveDocument."+sel[0].Name+",obj)") FreeCADGui.doCommand('FreeCAD.ActiveDocument.removeObject("'+sel[0].Name+'")') nobj = makeSite() ArchCommands.copyProperties(sel[0],nobj) FreeCAD.ActiveDocument.removeObject(sel[0].Name) FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: ss = "[" for o in sel: if len(ss) > 1: ss += "," ss += "FreeCAD.ActiveDocument."+o.Name ss += "]" FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Site"))) FreeCADGui.doCommand("import Arch") FreeCADGui.doCommand("Arch.makeSite("+ss+")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute()
def Activated(self): p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") self.Length = p.GetFloat("StructureLength", 100) self.Width = p.GetFloat("StructureWidth", 100) self.Height = p.GetFloat("StructureHeight", 1000) self.Profile = None self.continueCmd = False sel = FreeCADGui.Selection.getSelection() if sel: st = Draft.getObjectsOfType(sel, "Structure") ax = Draft.getObjectsOfType(sel, "Axis") if ax: FreeCAD.ActiveDocument.openTransaction(str(translate("Arch", "Create Structural System"))) FreeCADGui.addModule("Arch") if st: FreeCADGui.doCommand( "Arch.makeStructuralSystem(" + ArchCommands.getStringList(st) + "," + ArchCommands.getStringList(ax) + ")" ) else: FreeCADGui.doCommand("Arch.makeStructuralSystem(axes=" + ArchCommands.getStringList(ax) + ")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() return elif not (ax) and not (st): FreeCAD.ActiveDocument.openTransaction(str(translate("Arch", "Create Structure"))) FreeCADGui.addModule("Arch") for obj in sel: FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument." + obj.Name + ")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() return # interactive mode if hasattr(FreeCAD, "DraftWorkingPlane"): FreeCAD.DraftWorkingPlane.setup() import DraftTrackers, ArchPrecast self.points = [] self.tracker = DraftTrackers.boxTracker() self.tracker.width(self.Width) self.tracker.height(self.Height) self.tracker.length(self.Length) self.tracker.on() self.precast = ArchPrecast._PrecastTaskPanel() self.dents = ArchPrecast._DentsTaskPanel() self.precast.Dents = self.dents FreeCADGui.Snapper.getPoint( callback=self.getPoint, movecallback=self.update, extradlg=[self.taskbox(), self.precast.form, self.dents.form], )
def cutComponentwithPlane(archObject, cutPlane, sideFace): """cut object from a plan define by a face, Behind = 0 , front = 1""" cutVolume = ArchCommands.getCutVolume(cutPlane, archObject.Object.Shape) if sideFace == 0: cutVolume = cutVolume[2] else: cutVolume = cutVolume[1] if cutVolume: obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "CutVolume") obj.Shape = cutVolume # add substraction component to Arch object return ArchCommands.removeComponents(obj,archObject.Object)
def makeStructure(baseobj=None,length=None,width=None,height=None,name="Structure"): '''makeStructure([obj],[length],[width],[heigth],[swap]): creates a structure element based on the given profile object and the given extrusion height. If no base object is given, you can also specify length and width for a cubic object.''' p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) obj.Label = translate("Arch",name) _Structure(obj) if FreeCAD.GuiUp: _ViewProviderStructure(obj.ViewObject) obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Structure") if baseobj: obj.Base = baseobj if FreeCAD.GuiUp: obj.Base.ViewObject.hide() if width: obj.Width = width else: obj.Width = p.GetFloat("StructureWidth",100) if height: obj.Height = height else: obj.Height = p.GetFloat("StructureHeight",1000) if length: obj.Length = length else: if not baseobj: # don't set the length if we have a base object, otherwise the lenght X height calc # gets wrong obj.Length = p.GetFloat("StructureLength",100) if height > length: obj.Role = "Column" return obj
def Activated(self): sel = FreeCADGui.Selection.getSelection() ok = False if len(sel) == 1: if Draft.getType(sel[0]) in ["Cell", "Site", "Floor"]: FreeCAD.ActiveDocument.openTransaction("Type conversion") nobj = makeBuilding() ArchCommands.copyProperties(sel[0], nobj) FreeCAD.ActiveDocument.removeObject(sel[0].Name) FreeCAD.ActiveDocument.commitTransaction() ok = True if not ok: FreeCAD.ActiveDocument.openTransaction("Building") makeBuilding(sel) FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute()
def makeWall(baseobj=None,length=None,width=None,height=None,align="Center",face=None,name=translate("Arch","Wall")): '''makeWall([obj],[length],[width],[height],[align],[face],[name]): creates a wall based on the given object, which can be a sketch, a draft object, a face or a solid, or no object at all, then you must provide length, width and height. Align can be "Center","Left" or "Right", face can be an index number of a face in the base object to base the wall on.''' p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name) _Wall(obj) _ViewProviderWall(obj.ViewObject) if baseobj: obj.Base = baseobj if face: obj.Face = face if length: obj.Length = length if width: obj.Width = width else: obj.Width = p.GetFloat("WallWidth",200) if height: obj.Height = height else: obj.Height = p.GetFloat("WallHeight",3000) obj.Align = align if obj.Base: if Draft.getType(obj.Base) != "Space": obj.Base.ViewObject.hide() obj.ViewObject.ShapeColor = ArchCommands.getDefaultColor("Wall") return obj
def Activated(self): global QtGui, QtCore from PyQt4 import QtGui, QtCore self.Length = 0.5 self.Width = 0.2 self.Height = 1 self.continueCmd = False sel = FreeCADGui.Selection.getSelection() if sel: # direct creation FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Structure"))) FreeCADGui.doCommand("import Arch") # if selection contains structs and axes, make a system st = Draft.getObjectsOfType(sel,"Structure") ax = Draft.getObjectsOfType(sel,"Axis") if st and ax: FreeCADGui.doCommand("Arch.makeStructuralSystem(" + ArchCommands.getStringList(st) + "," + ArchCommands.getStringList(ax) + ")") else: # else, do normal structs for obj in sel: FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument." + obj.Name + ")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() else: # interactive mode import DraftTrackers self.points = [] self.tracker = DraftTrackers.boxTracker() self.tracker.width(self.Width) self.tracker.height(self.Height) self.tracker.length(self.Length) self.tracker.on() FreeCADGui.Snapper.getPoint(callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox())
def projectFace(self,face): "projects a single face on the WP" #print "VRM: projectFace start: ",len(face[0].Vertexes)," verts, ",len(face[0].Edges)," edges" wires = [] if not face[0].Wires: if DEBUG: print "Error: Unable to project face on the WP" return None norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] edges = DraftGeomUtils.sortEdges(w.Edges) #print len(edges)," edges after sorting" for e in edges: v = e.Vertexes[0].Point #print v v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) if len(verts) > 2: #print "new wire with ",len(verts) wires.append(Part.makePolygon(verts)) try: sh = ArchCommands.makeFace(wires) except: if DEBUG: print "Error: Unable to project face on the WP" return None else: # restoring flipped normals vnorm = self.wp.getLocalCoords(norm) if vnorm.getAngle(sh.normalAt(0,0)) > 1: sh.reverse() #print "VRM: projectFace end: ",len(sh.Vertexes)," verts" return [sh]+face[1:]
def getArea(self,obj): "returns the horizontal area at the center of the space" import Part,DraftGeomUtils if not hasattr(obj.Shape,"CenterOfMass"): return 0 try: pl = Part.makePlane(1,1) pl.translate(obj.Shape.CenterOfMass) sh = obj.Shape.copy() cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh) e = sh.section(cutplane) e = Part.__sortEdges__(e.Edges) w = Part.Wire(e) f = Part.Face(w) except Part.OCCError: return 0 else: if hasattr(obj,"PerimeterLength"): if w.Length != obj.PerimeterLength.Value: obj.PerimeterLength = w.Length if hasattr(obj,"VerticalArea"): a = 0 for f in sh.Faces: ang = f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1)) if (ang > 1.57) and (ang < 1.571): a += f.Area if a != obj.VerticalArea.Value: obj.VerticalArea = a #print "area of ",obj.Label," : ",f.Area return f.Area
def __init__(self,vobj): vobj.addExtension("Gui::ViewProviderGroupExtensionPython", self) #vobj.addExtension("Gui::ViewProviderGeoFeatureGroupExtensionPython", self) vobj.Proxy = self self.setProperties(vobj) vobj.ShapeColor = ArchCommands.getDefaultColor("Helpers")
def __init__(self, vobj): ArchComponent.ViewProviderComponent.__init__(self, vobj) vobj.addProperty( "App::PropertyBool", "ShowNodes", "Arch", QT_TRANSLATE_NOOP("App::Property", "If the nodes are visible or not"), ).ShowNodes = False vobj.addProperty( "App::PropertyFloat", "NodeLine", "Base", QT_TRANSLATE_NOOP("App::Property", "The width of the nodes line") ) vobj.addProperty( "App::PropertyFloat", "NodeSize", "Base", QT_TRANSLATE_NOOP("App::Property", "The size of the node points") ) vobj.addProperty( "App::PropertyColor", "NodeColor", "Base", QT_TRANSLATE_NOOP("App::Property", "The color of the nodes line") ) vobj.addProperty( "App::PropertyEnumeration", "NodeType", "Arch", QT_TRANSLATE_NOOP("App::Property", "The type of structural node"), ) vobj.NodeColor = (1.0, 1.0, 1.0, 1.0) vobj.NodeSize = 6 vobj.NodeType = ["Linear", "Area"] vobj.ShapeColor = ArchCommands.getDefaultColor("Structure")
def projectFace(self,face): "projects a single face on the WP" wires = [] norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] edges = DraftGeomUtils.sortEdges(w.Edges) for e in edges: v = e.Vertexes[0].Point v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) if len(verts) > 2: wires.append(Part.makePolygon(verts)) try: sh = ArchCommands.makeFace(wires) except: if DEBUG: print "Error: Unable to project face on the WP" return None else: # restoring flipped normals vnorm = self.wp.getLocalCoords(norm) if vnorm.getAngle(sh.normalAt(0,0)) > 1: sh.reverse() return [sh]+face[1:]
def Activated(self): global QtGui, QtCore from PyQt4 import QtGui, QtCore p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") self.Length = p.GetFloat("StructureLength", 100) self.Width = p.GetFloat("StructureWidth", 100) self.Height = p.GetFloat("StructureHeight", 1000) self.Profile = 0 self.continueCmd = False sel = FreeCADGui.Selection.getSelection() if sel: # direct creation FreeCAD.ActiveDocument.openTransaction(str(translate("Arch", "Create Structure"))) FreeCADGui.doCommand("import Arch") # if selection contains structs and axes, make a system st = Draft.getObjectsOfType(sel, "Structure") ax = Draft.getObjectsOfType(sel, "Axis") if st and ax: FreeCADGui.doCommand( "Arch.makeStructuralSystem(" + ArchCommands.getStringList(st) + "," + ArchCommands.getStringList(ax) + ")" ) else: # else, do normal structs for obj in sel: FreeCADGui.doCommand("Arch.makeStructure(FreeCAD.ActiveDocument." + obj.Name + ")") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() else: # interactive mode if hasattr(FreeCAD, "DraftWorkingPlane"): FreeCAD.DraftWorkingPlane.setup() import DraftTrackers self.points = [] self.tracker = DraftTrackers.boxTracker() self.tracker.width(self.Width) self.tracker.height(self.Height) self.tracker.length(self.Length) self.tracker.on() FreeCADGui.Snapper.getPoint(callback=self.getPoint, movecallback=self.update, extradlg=self.taskbox())
def execute(self,obj): "builds the wall shape" if self.clone(obj): return import Part, DraftGeomUtils base = None pl = obj.Placement extdata = self.getExtrusionData(obj) if extdata: base = extdata[0] extv = extdata[2].Rotation.multVec(extdata[1]) if isinstance(base,list): shps = [] for b in base: b.Placement = extdata[2].multiply(b.Placement) b = b.extrude(extv) shps.append(b) base = Part.makeCompound(shps) else: base.Placement = extdata[2].multiply(base.Placement) base = base.extrude(extv) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return elif obj.Base.Shape.Solids: base = obj.Base.Shape.copy() elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning(translate("Arch","This mesh is an invalid solid")+"\n") obj.Base.ViewObject.show() if not base: FreeCAD.Console.PrintError(translate("Arch","Error: Invalid base object")+"\n") return base = self.processSubShapes(obj,base,pl) self.applyShape(obj,base,pl) # set the length property if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Edges: if not obj.Base.Shape.Faces: if hasattr(obj.Base.Shape,"Length"): l = obj.Base.Shape.Length if obj.Length.Value != l: obj.Length = l
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 __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) vobj.addProperty("App::PropertyBool","ShowNodes","Arch","If the nodes are visible or not").ShowNodes = False vobj.addProperty("App::PropertyFloat","NodeLine","Base","The width of the nodes line") vobj.addProperty("App::PropertyFloat","NodeSize","Base","The size of the node points") vobj.addProperty("App::PropertyColor","NodeColor","Base","The color of the nodes line") vobj.NodeColor = (1.0,1.0,1.0,1.0) vobj.NodeSize = 6 vobj.ShapeColor = ArchCommands.getDefaultColor("Structure")
def execute(self, obj): #print("TimberMachiningCut Start Execute") face = obj.Face faceObject = face[0] faceNumber = int(face[1][0][4:]) - 1 face = faceObject.Shape.Faces[faceNumber] structure = obj.Structure cutVolume = ArchCommands.getCutVolume(face, structure.Shape) machining = cutVolume[2].common(beam.Shape) obj.Shape = machining
def Activated(self): sel = FreeCADGui.Selection.getSelectionEx() beam = sel[0].Object beam = 'FreeCAD.ActiveDocument.' + beam.Name structure = sel[0].Object.Base structure = 'FreeCAD.ActiveDocument.' + structure.Name face = sel[1].Object, sel[1].SubElementNames[0] face = '[FreeCAD.ActiveDocument.' + face[0].Name + ',"' + face[1] + '"]' if beam and face : FreeCAD.ActiveDocument.openTransaction(str(translate("Timber","Create Cut Machining"))) FreeCADGui.addModule("Timber") FreeCADGui.addModule("ArchComponent") FreeCADGui.doCommand('m = Timber.makeTimberMachiningCut(' + structure + ' , ' + face + ')') FreeCADGui.doCommand('ArchComponent.addToComponent(' + beam + ' , ' + 'm, "Subtractions")') FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() else : ArchCommands.printMessage(translate("Timber","TimberMachiningcut need a reference plane and a beam to cut")) print(translate("Timber","TimberMachiningcut need a reference plane and a beam to cut"))
def cutComponentwithPlane(archObject, cutPlane, sideFace): """cut object from a plan define by a face, Behind = 0 , front = 1""" cutVolume = ArchCommands.getCutVolume(cutPlane, archObject.Object.Shape) if sideFace == 0: cutVolume = cutVolume[2] else: cutVolume = cutVolume[1] if cutVolume: obj = FreeCAD.ActiveDocument.addObject("Part::Feature", str(translate("Arch","CutVolume"))) obj.Shape = cutVolume obj.ViewObject.ShapeColor = (1.00,0.00,0.00) obj.ViewObject.Transparency = 75 if "Additions" in archObject.Object.PropertiesList: return ArchCommands.removeComponents(obj,archObject.Object) else: cutObj = FreeCAD.ActiveDocument.addObject("Part::Cut", str(translate("Arch","CutPlane"))) cutObj.Base = archObject.Object cutObj.Tool = obj return cutObj
def getSchema(): "retrieves the express schema" p = None p = os.path.join(FreeCAD.ConfigGet("UserAppData"),SCHEMA.split('/')[-1]) if os.path.exists(p): return p import ArchCommands p = ArchCommands.download(SCHEMA) if p: return p return None
def getExtrusionData(self,obj): "returns (shape,extrusion vector,placement) or None" if hasattr(obj,"CloneOf"): if obj.CloneOf: if hasattr(obj.CloneOf,"Proxy"): if hasattr(obj.CloneOf.Proxy,"getExtrusionData"): data = obj.CloneOf.Proxy.getExtrusionData(obj.CloneOf) if data: return data if obj.Base: if obj.Base.isDerivedFrom("Part::Extrusion"): if obj.Base.Base: base,placement = self.rebase(obj.Base.Base.Shape) extrusion = FreeCAD.Vector(obj.Base.Dir) if extrusion.Length == 0: extrusion = FreeCAD.Vector(0,0,1) else: extrusion = placement.inverse().Rotation.multVec(extrusion) if hasattr(obj.Base,"LengthFwd"): if obj.Base.LengthFwd.Value: extrusion = extrusion.multiply(obj.Base.LengthFwd.Value) return (base,extrusion,placement) elif obj.Base.isDerivedFrom("Part::MultiFuse"): rshapes = [] revs = [] rpls = [] for sub in obj.Base.Shapes: if sub.isDerivedFrom("Part::Extrusion"): if sub.Base: base,placement = self.rebase(sub.Base.Shape) extrusion = FreeCAD.Vector(sub.Dir) if extrusion.Length == 0: extrusion = FreeCAD.Vector(0,0,1) else: extrusion = placement.inverse().Rotation.multVec(extrusion) if hasattr(sub,"LengthFwd"): if sub.LengthFwd.Value: extrusion = extrusion.multiply(sub.LengthFwd.Value) placement = obj.Placement.multiply(placement) rshapes.append(base) revs.append(extrusion) rpls.append(placement) else: exdata = ArchCommands.getExtrusionData(sub.Shape) if exdata: base,placement = self.rebase(exdata[0]) extrusion = placement.inverse().Rotation.multVec(exdata[1]) placement = obj.Placement.multiply(placement) rshapes.append(base) revs.append(extrusion) rpls.append(placement) if rshapes and revs and rpls: return (rshapes,revs,rpls) return None
def Activated(self): FreeCAD.ActiveDocument.openTransaction(translate("Arch","Create Axis")) FreeCADGui.addModule("Arch") sel = FreeCADGui.Selection.getSelection() st = Draft.getObjectsOfType(sel,"Structure") if st: FreeCADGui.doCommand("axe = Arch.makeAxis()") FreeCADGui.doCommand("Arch.makeStructuralSystem(" + ArchCommands.getStringList(st) + ",[axe])") else: FreeCADGui.doCommand("Arch.makeAxis()") FreeCAD.ActiveDocument.commitTransaction()
def __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) self.setProperties(vobj) prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") vobj.Transparency = prefs.GetInt("defaultSpaceTransparency",85) vobj.LineWidth = Draft.getParam("linewidth") vobj.LineColor = ArchCommands.getDefaultColor("Space") vobj.DrawStyle = ["Solid","Dashed","Dotted","Dashdot"][prefs.GetInt("defaultSpaceStyle",2)] if prefs.GetInt("defaultSpaceTransparency",85) == 100: vobj.DisplayMode = "Wireframe"
def previewCutVolume(self, i): cutVolume = ArchCommands.getCutVolume(FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0], FreeCADGui.Selection.getSelectionEx()[0].Object.Shape) FreeCAD.ActiveDocument.removeObject(self.previewObj.Name) self.previewObj = FreeCAD.ActiveDocument.addObject("Part::Feature", "PreviewCutVolume") self.previewObj.ViewObject.ShapeColor = (1.00,0.00,0.00) self.previewObj.ViewObject.Transparency = 75 if i == 1: cutVolume = cutVolume[1] else: cutVolume = cutVolume[2] if cutVolume: self.previewObj.Shape = cutVolume
def execute(self, obj): "creates the structure shape" import Part, DraftGeomUtils if self.clone(obj): return import Part, DraftGeomUtils base = None pl = obj.Placement extdata = self.getExtrusionData(obj) if extdata: base = extdata[0] base.Placement = extdata[2].multiply(base.Placement) extv = extdata[2].Rotation.multVec(extdata[1]) if obj.Tool: try: base = obj.Tool.Shape.copy().makePipe(obj.Base.Shape.copy()) except Part.OCCError: FreeCAD.Console.PrintError( translate("Arch", "Error: The base shape couldn't be extruded along this tool object") + "\n" ) return else: base = base.extrude(extv) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return elif obj.Base.Shape.Solids: base = obj.Base.Shape.copy() elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning(translate("Arch", "This mesh is an invalid solid") + "\n") obj.Base.ViewObject.show() if not base: FreeCAD.Console.PrintError(translate("Arch", "Error: Invalid base object") + "\n") return base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl)
def getPoint(self,point=None,obj=None): "this function is called by the snapper when it has a 3D point" if obj: if Draft.getType(obj) == "Wall": if not obj in self.existing: self.existing.append(obj) if point == None: self.tracker.finalize() return self.points.append(point) if len(self.points) == 1: self.tracker.on() FreeCADGui.Snapper.getPoint(last=self.points[0],callback=self.getPoint,movecallback=self.update,extradlg=self.taskbox()) elif len(self.points) == 2: import Part add = False l = Part.Line(self.points[0],self.points[1]) self.tracker.finalize() FreeCAD.ActiveDocument.openTransaction("Wall") if not self.existing: self.addDefault(l) else: w = joinWalls(self.existing) if w: if areSameWallTypes([w,self]): w.Base.addGeometry(l) else: nw = self.addDefault(l) add = True else: self.addDefault(l) FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() if add: import ArchCommands ArchCommands.addComponents(nw,w) if self.continueCmd: self.Activated()
def execute(self, obj): "builds the wall shape" if self.clone(obj): return import Part, DraftGeomUtils pl = obj.Placement normal, length, width, height = self.getDefaultValues(obj) base = None face = None if obj.Base: # computing a shape from a base object if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return if hasattr(obj, "Face"): if obj.Face > 0: if len(obj.Base.Shape.Faces) >= obj.Face: face = obj.Base.Shape.Faces[obj.Face - 1] if face: # case 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) elif obj.Base.Shape.Solids: # case 2: the base is already a solid base = obj.Base.Shape.copy() elif obj.Base.Shape.Edges: # case 3: the base is flat, we need to extrude it profiles = self.getProfiles(obj) if profiles: normal.multiply(height) base = profiles.pop() base.fix(0.1, 0, 1) base = base.extrude(normal) for p in profiles: p.fix(0.1, 0, 1) p = p.extrude(normal) base = base.fuse(p) else: base = None else: base = None FreeCAD.Console.PrintError( str(translate("Arch", "Error: Invalid base object"))) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and ( not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning( str( translate( "Arch", "This mesh is an invalid solid"))) obj.Base.ViewObject.show() else: # computing a shape from scratch if length and width and height: base = Part.makeBox(length, width, height) base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl)
def makeStraightRebar( f_cover, coverAlong, rt_cover, lb_cover, diameter, amount_spacing_check, amount_spacing_value, orientation="Horizontal", structure=None, facename=None, ): """Adds the straight reinforcement bar to the selected structural object. Case I: When orientation of straight rebar is 'Horizontal': makeStraightRebar(FrontCover, CoverAlong, RightCover, LeftCover, Diameter, AmountSpacingCheck, AmountSpacingValue, Orientation = "Horizontal", Structure, Facename) Note: Type of CoverAlong argument is a tuple. Syntax: (<Along>, <Value>). Here we have horizontal orientation so we can pass Top Side and Bottom Side to <Along> arguments. For eg. ("Top Side", 20) and ("Bottom Side", 20) Case II: When orientation of straight rebar is 'Vertical': makeStraightRebar(FrontCover, CoverAlong, TopCover, BottomCover, Diameter, AmountSpacingCheck, AmountSpacingValue, Orientation = "Horizontal", Structure, Facename) Note: Type of CoverAlong argument is a tuple. Syntax: (<Along>, <Value>). Here we have vertical orientation so we can pass Left Side and Right Side to <Along> arguments. For eg. ("Left Side", 20) and ("Right Side", 20) """ if not structure and not facename: selected_obj = FreeCADGui.Selection.getSelectionEx()[0] structure = selected_obj.Object facename = selected_obj.SubElementNames[0] face = structure.Shape.Faces[getFaceNumber(facename) - 1] # StructurePRM = getTrueParametersOfStructure(structure) FacePRM = getParametersOfFace(structure, facename) if not FacePRM: FreeCAD.Console.PrintError( "Cannot identified shape or from which base object sturctural " "element is derived\n" ) return # Get points of Striaght rebar points = getpointsOfStraightRebar( FacePRM, rt_cover, lb_cover, coverAlong, orientation, diameter ) import Part import Arch sketch = FreeCAD.activeDocument().addObject( "Sketcher::SketchObject", "Sketch" ) sketch.MapMode = "FlatFace" sketch.Support = [(structure, facename)] FreeCAD.ActiveDocument.recompute() sketch.addGeometry(Part.LineSegment(points[0], points[1]), False) if amount_spacing_check: rebar = Arch.makeRebar( structure, sketch, diameter, amount_spacing_value, f_cover + diameter / 2, name="StraightRebar", ) FreeCAD.ActiveDocument.recompute() else: size = ( ArchCommands.projectToVector( structure.Shape.copy(), face.normalAt(0, 0) ) ).Length rebar = Arch.makeRebar( structure, sketch, diameter, int((size - diameter) / amount_spacing_value), f_cover + diameter / 2, name="StraightRebar", ) # Adds properties to the rebar object rebar.addProperty( "App::PropertyEnumeration", "RebarShape", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar"), ).RebarShape = RebarTypes.tolist() rebar.RebarShape = "StraightRebar" rebar.setEditorMode("RebarShape", 2) rebar.addProperty( "App::PropertyDistance", "FrontCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Front cover of rebar"), ).FrontCover = f_cover rebar.setEditorMode("FrontCover", 2) rebar.addProperty( "App::PropertyDistance", "RightTopCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Right/Top Side cover of rebar"), ).RightTopCover = rt_cover rebar.setEditorMode("RightTopCover", 2) rebar.addProperty( "App::PropertyDistance", "LeftBottomCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Left/Bottom Side cover of rebar"), ).LeftBottomCover = lb_cover rebar.setEditorMode("LeftBottomCover", 2) rebar.addProperty( "App::PropertyString", "CoverAlong", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Cover along"), ).CoverAlong = coverAlong[0] rebar.setEditorMode("CoverAlong", 2) rebar.addProperty( "App::PropertyDistance", "Cover", "RebarDialog", QT_TRANSLATE_NOOP( "App::Property", "Cover of rebar along user selected side" ), ).Cover = coverAlong[1] rebar.setEditorMode("Cover", 2) rebar.addProperty( "App::PropertyBool", "AmountCheck", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Amount radio button is checked"), ) rebar.setEditorMode("AmountCheck", 2) rebar.addProperty( "App::PropertyDistance", "TrueSpacing", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Spacing between of rebars"), ).TrueSpacing = amount_spacing_value rebar.setEditorMode("TrueSpacing", 2) rebar.addProperty( "App::PropertyString", "Orientation", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar"), ).Orientation = orientation rebar.setEditorMode("Orientation", 2) if amount_spacing_check: rebar.AmountCheck = True else: rebar.AmountCheck = False rebar.TrueSpacing = amount_spacing_value FreeCAD.ActiveDocument.recompute() return rebar
def createGeometry(self, obj): "builds the wall shape" if not obj.Base: return import Part, DraftGeomUtils flat = False if hasattr(obj.ViewObject, "DisplayMode"): flat = (obj.ViewObject.DisplayMode == "Flat 2D") width = 1.0 if hasattr(obj, "Width"): if obj.Width: width = obj.Width def getbase(wire): "returns a full shape from a base wire" dvec = DraftGeomUtils.vec(wire.Edges[0]).cross(normal) 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 pl = obj.Placement # getting default values height = normal = None if obj.Height: height = obj.Height else: for p in obj.InList: if Draft.getType(p) == "Floor": height = p.Height if not height: height = 1 if obj.Normal == Vector(0, 0, 0): normal = Vector(0, 0, 1) else: normal = Vector(obj.Normal) # computing shape base = None if obj.Base.isDerivedFrom("Part::Feature"): if not obj.Base.Shape.isNull(): if obj.Base.Shape.isValid(): base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces and (not obj.ForceWire): if height: norm = normal.multiply(height) base = base.extrude(norm) elif base.Wires: temp = None for wire in obj.Base.Shape.Wires: sh = getbase(wire) if temp: temp = temp.fuse(sh) else: temp = sh base = temp elif base.Edges: wire = Part.Wire(base.Edges) sh = getbase(wire) if sh: base = sh else: base = None FreeCAD.Console.PrintError( str(translate("Arch", "Error: Invalid base object"))) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and ( not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning( str( translate("Arch", "This mesh is an invalid solid"))) obj.Base.ViewObject.show() if base: for app in obj.Additions: if Draft.getType(app) == "Window": # window if app.Base and obj.Width: f = self.getSubVolume(app.Base, width) if f: base = base.cut(f) elif Draft.isClone(app, "Window"): if app.Objects[0].Base and width: f = self.getSubVolume(app.Objects[0].Base, width, app.Placement) if f: base = base.cut(f) elif app.isDerivedFrom("Part::Feature"): if app.Shape: if not app.Shape.isNull(): base = base.fuse(app.Shape) app.ViewObject.hide() #to be removed for hole in obj.Subtractions: if Draft.getType(hole) == "Window": # window if hole.Base and obj.Width: f = self.getSubVolume(hole.Base, width) if f: base = base.cut(f) elif Draft.isClone(hole, "Window"): if hole.Objects[0].Base and width: f = self.getSubVolume(hole.Objects[0].Base, width, hole.Placement) if f: base = base.cut(f) elif hole.isDerivedFrom("Part::Feature"): if hole.Shape: if not hole.Shape.isNull(): base = base.cut(hole.Shape) hole.ViewObject.hide() # to be removed if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( str( translate("Arch", "Couldn't compute the wall shape"))) return try: base = base.removeSplitter() except: FreeCAD.Console.PrintError( str( translate( "Arch", "Error removing splitter from wall shape")) ) obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl
def getSVG(section, allOn=False, renderMode="Wireframe", showHidden=False, showFill=False, scale=1, linewidth=1, fontsize=1): """getSVG(section,[allOn,renderMode,showHidden,showFill,scale,linewidth,fontsize]) : returns an SVG fragment from an Arch section plane. If allOn is True, all cut objects are shown, regardless if they are visible or not. renderMode can be Wireframe (default) or Solid to use the Arch solid renderer. If showHidden is True, the hidden geometry above the section plane is shown in dashed line. If showFill is True, the cut areas get filled with a pattern""" if not section.Objects: return import DraftGeomUtils p = FreeCAD.Placement(section.Placement) direction = p.Rotation.multVec(FreeCAD.Vector(0, 0, 1)) objs = Draft.getGroupContents(section.Objects, walls=True, addgroups=True) if not allOn: objs = Draft.removeHidden(objs) # separate spaces spaces = [] nonspaces = [] for o in objs: if Draft.getType(o) == "Space": spaces.append(o) else: nonspaces.append(o) objs = nonspaces svg = '' fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"' fillpattern += ' x="0" y="0" width="10" height="10">' fillpattern += '<g>' fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>' # generating SVG if renderMode == "Solid": # render using the Arch Vector Renderer import ArchVRM, WorkingPlane wp = WorkingPlane.plane() wp.setFromPlacement(section.Placement) #wp.inverse() render = ArchVRM.Renderer() render.setWorkingPlane(wp) render.addObjects(objs) if showHidden: render.cut(section.Shape, showHidden) else: render.cut(section.Shape) svg += '<g transform="scale(1,-1)">\n' svg += render.getViewSVG(linewidth="LWPlaceholder") svg += fillpattern svg += render.getSectionSVG(linewidth="SWPlaceholder", fillpattern="sectionfill") if showHidden: svg += render.getHiddenSVG(linewidth="LWPlaceholder") svg += '</g>\n' # print render.info() else: # render using the Drawing module import Drawing, Part shapes = [] hshapes = [] sshapes = [] for o in objs: if o.isDerivedFrom("Part::Feature"): if o.Shape.isNull(): pass elif o.Shape.isValid(): if section.OnlySolids: shapes.extend(o.Shape.Solids) else: shapes.append(o.Shape) else: print section.Label, ": Skipping invalid object:", o.Label cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume( section.Shape.copy(), shapes) if cutvolume: nsh = [] for sh in shapes: for sol in sh.Solids: if sol.Volume < 0: sol.reverse() c = sol.cut(cutvolume) s = sol.section(cutface) try: wires = DraftGeomUtils.findWires(s.Edges) for w in wires: f = Part.Face(w) sshapes.append(f) #s = Part.Wire(s.Edges) #s = Part.Face(s) except Part.OCCError: #print "ArchDrawingView: unable to get a face" sshapes.append(s) nsh.extend(c.Solids) #sshapes.append(s) if showHidden: c = sol.cut(invcutvolume) hshapes.append(c) shapes = nsh if shapes: baseshape = Part.makeCompound(shapes) svgf = Drawing.projectToSVG(baseshape, direction) if svgf: svgf = svgf.replace('stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace('stroke-width="1"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace('stroke-width:0.01', 'stroke-width:LWPlaceholder') svg += svgf if hshapes: hshapes = Part.makeCompound(hshapes) svgh = Drawing.projectToSVG(hshapes, direction) if svgh: svgh = svgh.replace('stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace('stroke-width="1"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace('stroke-width:0.01', 'stroke-width:LWPlaceholder') svgh = svgh.replace( 'fill="none"', 'fill="none"\nstroke-dasharray="DAPlaceholder"') svg += svgh if sshapes: svgs = "" if showFill: svgs += fillpattern svgs += '<g transform="rotate(180)">\n' for s in sshapes: if s.Edges: f = Draft.getSVG(s, direction=direction.negative(), linewidth=0, fillstyle="sectionfill", color=(0, 0, 0)) svgs += f svgs += "</g>\n" sshapes = Part.makeCompound(sshapes) svgs += Drawing.projectToSVG(sshapes, direction) if svgs: svgs = svgs.replace('stroke-width="0.35"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace('stroke-width="1"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace('stroke-width:0.01', 'stroke-width:SWPlaceholder') svgs = svgs.replace('stroke-width="0.35 px"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace('stroke-width:0.35', 'stroke-width:SWPlaceholder') svg += svgs linewidth = linewidth / scale st = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Arch").GetFloat( "CutLineThickness", 2) da = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Arch").GetString( "archHiddenPattern", "30,10") da = da.replace(" ", "") svg = svg.replace('LWPlaceholder', str(linewidth) + 'px') svg = svg.replace('SWPlaceholder', str(linewidth * st) + 'px') svg = svg.replace('DAPlaceholder', str(da)) if spaces and round( direction.getAngle(FreeCAD.Vector(0, 0, 1)), Draft.precision()) in [0, round(math.pi, Draft.precision())]: svg += '<g transform="scale(1,-1)">' for s in spaces: svg += Draft.getSVG(s, scale=scale, fontsize=fontsize, direction=direction) svg += '</g>' # print "complete node:",svg return svg
def setProperties(self, vobj): pl = vobj.PropertiesList d = 0 if "DisplaySize" in pl: d = vobj.DisplaySize.Value vobj.removeProperty("DisplaySize") if not "DisplayLength" in pl: vobj.addProperty( "App::PropertyLength", "DisplayLength", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "The display length of this section plane")) if d: vobj.DisplayLength = d else: vobj.DisplayLength = 1000 if not "DisplayHeight" in pl: vobj.addProperty( "App::PropertyLength", "DisplayHeight", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "The display height of this section plane")) if d: vobj.DisplayHeight = d else: vobj.DisplayHeight = 1000 if not "ArrowSize" in pl: vobj.addProperty( "App::PropertyLength", "ArrowSize", "SectionPlane", QT_TRANSLATE_NOOP( "App::Property", "The size of the arrows of this section plane")) vobj.ArrowSize = 50 if not "Transparency" in pl: vobj.addProperty( "App::PropertyPercent", "Transparency", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "The transparency of this object")) vobj.Transparency = 85 if not "LineWidth" in pl: vobj.addProperty( "App::PropertyFloat", "LineWidth", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "The line width of this object")) vobj.LineWidth = 1 if not "CutDistance" in pl: vobj.addProperty( "App::PropertyLength", "CutDistance", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "Show the cut in the 3D view")) if not "LineColor" in pl: vobj.addProperty( "App::PropertyColor", "LineColor", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "The color of this object")) vobj.LineColor = ArchCommands.getDefaultColor("Helpers") if not "CutView" in pl: vobj.addProperty( "App::PropertyBool", "CutView", "SectionPlane", QT_TRANSLATE_NOOP("App::Property", "Show the cut in the 3D view")) if not "CutMargin" in pl: vobj.addProperty( "App::PropertyLength", "CutMargin", "SectionPlane", QT_TRANSLATE_NOOP( "App::Property", "The distance between the cut plane and the actual view cut (keep this a very small value but not zero)" )) vobj.CutMargin = 1 self.Object = vobj.Object
def execute(self, obj): "creates the structure shape" import Part, DraftGeomUtils # getting default values length = 1 width = 1 height = 1 if hasattr(obj, "Length"): if obj.Length.Value: length = obj.Length.Value if hasattr(obj, "Width"): if obj.Width.Value: width = obj.Width.Value if hasattr(obj, "Height"): if obj.Height.Value: height = obj.Height.Value else: for p in obj.InList: if Draft.getType(p) == "Floor": if p.Height.Value: height = p.Height.Value # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if hasattr(obj, "Tool"): if obj.Tool: try: base = obj.Tool.Shape.copy().makePipe( obj.Base.Shape.copy()) except: FreeCAD.Console.PrintError( translate( "Arch", "Error: The base shape couldn't be extruded along this tool object" )) return if not base: if obj.Normal == Vector(0, 0, 0): p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(Vector(0, 0, 1)) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: self.BaseProfile = base self.ExtrusionVector = normal base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): base = Part.Face(base.Wires[0]) self.BaseProfile = base self.ExtrusionVector = normal base = base.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: if obj.Normal == Vector(0, 0, 0): if length > height: normal = Vector(1, 0, 0).multiply(length) else: normal = Vector(0, 0, 1).multiply(height) else: normal = Vector(obj.Normal).multiply(height) self.ExtrusionVector = normal if length > height: h2 = height / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(0, -w2, -h2) v2 = Vector(0, -w2, h2) v3 = Vector(0, w2, h2) v4 = Vector(0, w2, -h2) else: l2 = length / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) base = Part.makePolygon([v1, v2, v3, v4, v1]) base = Part.Face(base) self.BaseProfile = base base = base.extrude(self.ExtrusionVector) base = self.processSubShapes(obj, base, pl) if base: # applying axes pts = self.getAxisPoints(obj) apl = self.getAxisPlacement(obj) if pts: fsh = [] for i in range(len(pts)): if hasattr(obj, "Exclude"): if i in obj.Exclude: continue sh = base.copy() if apl: sh.Placement.Rotation = apl.Rotation sh.translate(pts[i]) fsh.append(sh) obj.Shape = Part.makeCompound(fsh) # finalizing else: if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( translate("Arch", "Couldn't compute a shape")) return base = base.removeSplitter() obj.Shape = base if not pl.isNull(): obj.Placement = pl
def execute(self,obj): "builds the wall shape" if self.clone(obj): return import Part, DraftGeomUtils base = None pl = obj.Placement extdata = self.getExtrusionData(obj) if extdata: bplates = extdata[0] extv = extdata[2].Rotation.multVec(extdata[1]) if isinstance(bplates,list): shps = [] for b in bplates: b.Placement = extdata[2].multiply(b.Placement) b = b.extrude(extv) shps.append(b) base = Part.makeCompound(shps) else: bplates.Placement = extdata[2].multiply(bplates.Placement) base = bplates.extrude(extv) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return elif obj.Base.Shape.Solids: base = obj.Base.Shape.copy() # blocks calculation elif hasattr(obj,"MakeBlocks") and hasattr(self,"basewires"): if obj.MakeBlocks and self.basewires and extdata and obj.Width and obj.Height: #print "calculating blocks" if len(self.basewires) == 1: blocks = [] n = FreeCAD.Vector(extv) n.normalize() cuts1 = [] cuts2 = [] if obj.BlockLength.Value: for i in range(2): if i == 0: offset = obj.OffsetFirst.Value else: offset = obj.OffsetSecond.Value for edge in self.basewires[0].Edges: while offset < (edge.Length-obj.Joint.Value): #print i," Edge ",edge," : ",edge.Length," - ",offset if offset: t = edge.tangentAt(offset) p = t.cross(n) p.multiply(1.1*obj.Width.Value+obj.Offset.Value) p1 = edge.valueAt(offset).add(p) p2 = edge.valueAt(offset).add(p.negative()) sh = Part.LineSegment(p1,p2).toShape() if obj.Joint.Value: sh = sh.extrude(t.multiply(obj.Joint.Value)) sh = sh.extrude(n) if i == 0: cuts1.append(sh) else: cuts2.append(sh) offset += (obj.BlockLength.Value + obj.Joint.Value) else: offset -= (edge.Length - obj.Joint.Value) if isinstance(bplates,list): bplates = bplates[0] if obj.BlockHeight.Value: fsize = obj.BlockHeight.Value + obj.Joint.Value bh = obj.BlockHeight.Value else: fsize = obj.Height.Value bh = obj.Height.Value bvec = FreeCAD.Vector(n) bvec.multiply(bh) svec = FreeCAD.Vector(n) svec.multiply(fsize) if cuts1: plate1 = bplates.cut(cuts1).Faces else: plate1 = bplates.Faces blocks1 = Part.makeCompound([f.extrude(bvec) for f in plate1]) if cuts2: plate2 = bplates.cut(cuts2).Faces else: plate2 = bplates.Faces blocks2 = Part.makeCompound([f.extrude(bvec) for f in plate2]) interval = extv.Length/(fsize) entires = int(interval) rest = (interval - entires) for i in range(entires): if i % 2: # odd b = blocks2.copy() else: b = blocks1.copy() if i: t = FreeCAD.Vector(svec) t.multiply(i) b.translate(t) blocks.append(b) if rest: rest = extv.Length-(entires*fsize) rvec = FreeCAD.Vector(n) rvec.multiply(rest) if entires % 2: b = Part.makeCompound([f.extrude(rvec) for f in plate2]) else: b = Part.makeCompound([f.extrude(rvec) for f in plate1]) t = FreeCAD.Vector(svec) t.multiply(entires) b.translate(t) blocks.append(b) if blocks: base = Part.makeCompound(blocks) else: FreeCAD.Console.PrintWarning(translate("Arch","Cannot compute blocks for wall")+obj.Label+"\n") elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and (not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning(translate("Arch","This mesh is an invalid solid")+"\n") obj.Base.ViewObject.show() if not base: FreeCAD.Console.PrintError(translate("Arch","Error: Invalid base object")+"\n") return base = self.processSubShapes(obj,base,pl) self.applyShape(obj,base,pl) # count blocks if hasattr(obj,"MakeBlocks"): if obj.MakeBlocks: fvol = obj.BlockLength.Value * obj.BlockHeight.Value * obj.Width.Value if fvol: #print("base volume:",fvol) #for s in base.Solids: #print(abs(s.Volume - fvol)) ents = [s for s in base.Solids if abs(s.Volume - fvol) < 1] obj.CountEntire = len(ents) obj.CountBroken = len(base.Solids) - len(ents) else: obj.CountEntire = 0 obj.CountBroken = 0 # set the length property if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Edges: if not obj.Base.Shape.Faces: if hasattr(obj.Base.Shape,"Length"): l = obj.Base.Shape.Length if obj.Length.Value != l: obj.Length = l
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: 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 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 + obj.OffsetEnd) > size: return # all tests ok! pl = obj.Placement import Part circle = Part.makeCircle(obj.Diameter / 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: baseoffset = DraftVecUtils.scaleTo(axis, obj.OffsetStart) else: baseoffset = None interval = size - (obj.OffsetStart + obj.OffsetEnd) 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 getShape(self,obj): "computes a shape from a base shape and/or bounday faces" import Part shape = None faces = [] #print("starting compute") # 1: if we have a base shape, we use it if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: shape = obj.Base.Shape.copy() shape = shape.removeSplitter() # 2: if not, add all bounding boxes of considered objects and build a first shape if shape: #print("got shape from base object") bb = shape.BoundBox else: bb = None for b in obj.Boundaries: if b[0].isDerivedFrom("Part::Feature"): if not bb: bb = b[0].Shape.BoundBox else: bb.add(b[0].Shape.BoundBox) if not bb: return shape = Part.makeBox(bb.XLength,bb.YLength,bb.ZLength,FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin)) #print("created shape from boundbox") # 3: identifing boundary faces goodfaces = [] for b in obj.Boundaries: if b[0].isDerivedFrom("Part::Feature"): if "Face" in b[1]: fn = int(b[1][4:])-1 faces.append(b[0].Shape.Faces[fn]) #print("adding face ",fn," of object ",b[0].Name) #print("total: ", len(faces), " faces") # 4: get cutvolumes from faces cutvolumes = [] for f in faces: f = f.copy() f.reverse() cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(f,shape) if cutvolume: #print("generated 1 cutvolume") cutvolumes.append(cutvolume.copy()) #Part.show(cutvolume) for v in cutvolumes: #print("cutting") shape = shape.cut(v) # 5: get the final shape if shape: if shape.Solids: #print("setting objects shape") shape = shape.Solids[0] obj.Shape = shape return print("Arch: error computing space boundary")
def __init__(self, vobj): ArchComponent.ViewProviderComponent.__init__(self, vobj) self.setProperties(vobj) vobj.ShapeColor = ArchCommands.getDefaultColor("Rebar")
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 makeStirrup( l_cover, r_cover, t_cover, b_cover, f_cover, bentAngle, bentFactor, diameter, rounding, amount_spacing_check, amount_spacing_value, structure=None, facename=None, ): """makeStirrup(LeftCover, RightCover, TopCover, BottomCover, FrontCover, BentAngle, BentFactor, Diameter, Rounding, AmountSpacingCheck, AmountSpacingValue, Structure, Facename): Adds the Stirrup reinforcement bar to the selected structural object.""" if not structure and not facename: selected_obj = FreeCADGui.Selection.getSelectionEx()[0] structure = selected_obj.Object facename = selected_obj.SubElementNames[0] face = structure.Shape.Faces[getFaceNumber(facename) - 1] # StructurePRM = getTrueParametersOfStructure(structure) FacePRM = getParametersOfFace(structure, facename, False) FaceNormal = face.normalAt(0, 0) # FaceNormal = face.Placement.Rotation.inverted().multVec(FaceNormal) if not FacePRM: FreeCAD.Console.PrintError( "Cannot identify shape or from which base object structural " "element is derived\n") return # Calculate the coordinate values of Stirrup points = getpointsOfStirrup( FacePRM, l_cover, r_cover, t_cover, b_cover, bentAngle, bentFactor, diameter, rounding, FaceNormal, ) import Draft line = Draft.makeWire(points, closed=False, face=True, support=None) import Arch line.Support = [(structure, facename)] if amount_spacing_check: rebar = Arch.makeRebar( structure, line, diameter, amount_spacing_value, f_cover + diameter / 2, name="Stirrup", ) else: size = (ArchCommands.projectToVector(structure.Shape.copy(), face.normalAt(0, 0))).Length rebar = Arch.makeRebar( structure, line, diameter, get_rebar_amount_from_spacing(size, diameter, amount_spacing_value), f_cover + diameter / 2, name="Stirrup", ) rebar.Direction = FaceNormal.negative() rebar.Rounding = rounding # Adds properties to the rebar object rebar.addProperty( "App::PropertyEnumeration", "RebarShape", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar"), ).RebarShape = RebarTypes.tolist() rebar.RebarShape = "Stirrup" rebar.setEditorMode("RebarShape", 2) rebar.addProperty( "App::PropertyDistance", "LeftCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Left Side cover of rebar"), ).LeftCover = l_cover rebar.setEditorMode("LeftCover", 2) rebar.addProperty( "App::PropertyDistance", "RightCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Right Side cover of rebar"), ).RightCover = r_cover rebar.setEditorMode("RightCover", 2) rebar.addProperty( "App::PropertyDistance", "TopCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Top Side cover of rebar"), ).TopCover = t_cover rebar.setEditorMode("TopCover", 2) rebar.addProperty( "App::PropertyDistance", "BottomCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Bottom Side cover of rebar"), ).BottomCover = b_cover rebar.setEditorMode("BottomCover", 2) rebar.addProperty( "App::PropertyDistance", "FrontCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Top cover of rebar"), ).FrontCover = f_cover rebar.setEditorMode("FrontCover", 2) rebar.addProperty( "App::PropertyInteger", "BentAngle", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Bent angle between at the end of rebar"), ).BentAngle = bentAngle rebar.setEditorMode("BentAngle", 2) rebar.addProperty( "App::PropertyInteger", "BentFactor", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Bent Length is the equal to BentFactor * Diameter"), ).BentFactor = bentFactor rebar.setEditorMode("BentFactor", 2) rebar.addProperty( "App::PropertyBool", "AmountCheck", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Amount radio button is checked"), ) rebar.setEditorMode("AmountCheck", 2) rebar.addProperty( "App::PropertyDistance", "TrueSpacing", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Spacing between of rebars"), ).TrueSpacing = amount_spacing_value rebar.setEditorMode("TrueSpacing", 2) if amount_spacing_check: rebar.AmountCheck = True else: rebar.AmountCheck = False rebar.TrueSpacing = amount_spacing_value FreeCAD.ActiveDocument.recompute() return rebar
def editStirrup( Rebar, l_cover, r_cover, t_cover, b_cover, f_cover, bentAngle, bentFactor, diameter, rounding, amount_spacing_check, amount_spacing_value, structure=None, facename=None, ): sketch = Rebar.Base if structure and facename: sketch.Support = [(structure, facename)] # Check if sketch support is empty. if not sketch.Support: showWarning( "You have checked: 'Remove external geometry of base sketches when " "needed.'\nTo uncheck: Edit->Preferences->Arch.") return # Assigned values facename = sketch.Support[0][1][0] structure = sketch.Support[0][0] face = structure.Shape.Faces[getFaceNumber(facename) - 1] # StructurePRM = getTrueParametersOfStructure(structure) # Get parameters of the face where sketch of rebar is drawn FacePRM = getParametersOfFace(structure, facename, False) FaceNormal = face.normalAt(0, 0) # FaceNormal = face.Placement.Rotation.inverted().multVec(FaceNormal) # Calculate the coordinates value of Stirrup rebar points = getpointsOfStirrup( FacePRM, l_cover, r_cover, t_cover, b_cover, bentAngle, bentFactor, diameter, rounding, FaceNormal, ) Rebar.Base.Points = points FreeCAD.ActiveDocument.recompute() Rebar.Direction = FaceNormal.negative() Rebar.OffsetStart = f_cover + diameter / 2 Rebar.OffsetEnd = f_cover + diameter / 2 Rebar.BentAngle = bentAngle Rebar.BentFactor = bentFactor Rebar.Rounding = rounding Rebar.Diameter = diameter if amount_spacing_check: Rebar.Amount = amount_spacing_value FreeCAD.ActiveDocument.recompute() Rebar.AmountCheck = True else: size = (ArchCommands.projectToVector(structure.Shape.copy(), face.normalAt(0, 0))).Length Rebar.Amount = get_rebar_amount_from_spacing(size, diameter, amount_spacing_value) FreeCAD.ActiveDocument.recompute() Rebar.AmountCheck = False Rebar.FrontCover = f_cover Rebar.LeftCover = l_cover Rebar.RightCover = r_cover Rebar.TopCover = t_cover Rebar.BottomCover = b_cover Rebar.TrueSpacing = amount_spacing_value FreeCAD.ActiveDocument.recompute() return Rebar
def __init__(self, vobj): ArchComponent.ViewProviderComponent.__init__(self, vobj) vobj.ShapeColor = ArchCommands.getDefaultColor("Wall")
def execute(self,obj): tol = 1 # tolerance for alignment. This is only visual, we can keep it low... ptol = 0.001 # tolerance for coincident points import math,Part,DraftGeomUtils,ArchCommands if len(obj.Pipes) < 2: return if len(obj.Pipes) > 3: FreeCAD.Console.PrintWarning(translate("Arch","Only the 3 first wires will be connected")+"\n") if obj.Radius.Value == 0: return wires = [] order = [] for o in obj.Pipes: wires.append(o.Proxy.getWire(o)) if wires[0].Vertexes[0].Point.sub(wires[1].Vertexes[0].Point).Length <= ptol: order = ["start","start"] point = wires[0].Vertexes[0].Point elif wires[0].Vertexes[0].Point.sub(wires[1].Vertexes[-1].Point).Length <= ptol: order = ["start","end"] point = wires[0].Vertexes[0].Point elif wires[0].Vertexes[-1].Point.sub(wires[1].Vertexes[-1].Point).Length <= ptol: order = ["end","end"] point = wires[0].Vertexes[-1].Point elif wires[0].Vertexes[-1].Point.sub(wires[1].Vertexes[0].Point).Length <= ptol: order = ["end","start"] point = wires[0].Vertexes[-1].Point else: FreeCAD.Console.PrintError(translate("Arch","Common vertex not found")+"\n") return if order[0] == "start": v1 = wires[0].Vertexes[1].Point.sub(wires[0].Vertexes[0].Point).normalize() else: v1 = wires[0].Vertexes[-2].Point.sub(wires[0].Vertexes[-1].Point).normalize() if order[1] == "start": v2 = wires[1].Vertexes[1].Point.sub(wires[1].Vertexes[0].Point).normalize() else: v2 = wires[1].Vertexes[-2].Point.sub(wires[1].Vertexes[-1].Point).normalize() p = obj.Pipes[0].Proxy.getProfile(obj.Pipes[0]) p = Part.Face(p) if len(obj.Pipes) == 2: if obj.ConnectorType != "Corner": obj.ConnectorType = "Corner" if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]: FreeCAD.Console.PrintError(translate("Arch","Pipes are already aligned")+"\n") return normal = v2.cross(v1) offset = math.tan(math.pi/2-v1.getAngle(v2)/2)*obj.Radius.Value v1.multiply(offset) v2.multiply(offset) self.setOffset(obj.Pipes[0],order[0],offset) self.setOffset(obj.Pipes[1],order[1],offset) # find center perp = v1.cross(normal).normalize() perp.multiply(obj.Radius.Value) center = point.add(v1).add(perp) # move and rotate the profile to the first point delta = point.add(v1)-p.CenterOfMass p.translate(delta) vp = DraftGeomUtils.getNormal(p) rot = FreeCAD.Rotation(vp,v1) p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle)) sh = p.revolve(center,normal,math.degrees(math.pi-v1.getAngle(v2))) #sh = Part.makeCompound([sh]+[Part.Vertex(point),Part.Vertex(point.add(v1)),Part.Vertex(center),Part.Vertex(point.add(v2))]) else: if obj.ConnectorType != "Tee": obj.ConnectorType = "Tee" if wires[2].Vertexes[0].Point == point: order.append("start") elif wires[0].Vertexes[-1].Point == point: order.append("end") else: FreeCAD.Console.PrintError(translate("Arch","Common vertex not found")+"\n") if order[2] == "start": v3 = wires[2].Vertexes[1].Point.sub(wires[2].Vertexes[0].Point).normalize() else: v3 = wires[2].Vertexes[-2].Point.sub(wires[2].Vertexes[-1].Point).normalize() if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]: pair = [v1,v2,v3] elif round(v1.getAngle(v3),tol) in [0,round(math.pi,tol)]: pair = [v1,v3,v2] elif round(v2.getAngle(v3),tol) in [0,round(math.pi,tol)]: pair = [v2,v3,v1] else: FreeCAD.Console.PrintError(translate("Arch","At least 2 pipes must align")+"\n") return offset = obj.Radius.Value v1.multiply(offset) v2.multiply(offset) v3.multiply(offset) self.setOffset(obj.Pipes[0],order[0],offset) self.setOffset(obj.Pipes[1],order[1],offset) self.setOffset(obj.Pipes[2],order[2],offset) normal = pair[0].cross(pair[2]) # move and rotate the profile to the first point delta = point.add(pair[0])-p.CenterOfMass p.translate(delta) vp = DraftGeomUtils.getNormal(p) rot = FreeCAD.Rotation(vp,pair[0]) p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle)) t1 = p.extrude(pair[1].multiply(2)) # move and rotate the profile to the second point delta = point.add(pair[2])-p.CenterOfMass p.translate(delta) vp = DraftGeomUtils.getNormal(p) rot = FreeCAD.Rotation(vp,pair[2]) p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle)) t2 = p.extrude(pair[2].negative().multiply(2)) # create a cut plane cp = Part.makePolygon([point,point.add(pair[0]),point.add(normal),point]) cp = Part.Face(cp) if cp.normalAt(0,0).getAngle(pair[2]) < math.pi/2: cp.reverse() cf, cv, invcv = ArchCommands.getCutVolume(cp,t2) t2 = t2.cut(cv) sh = t1.fuse(t2) obj.Shape = sh
def execute(self,obj): if self.clone(obj): return if not obj.Base: # let pass without error so that object can receive a shape directly #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)
def execute(self, obj): "builds the wall shape" import Part, DraftGeomUtils pl = obj.Placement normal, length, width, height = self.getDefaultValues(obj) base = None # computing a shape from scratch if not obj.Base: if length and width and height: base = Part.makeBox(length, width, height) else: FreeCAD.Console.PrintError( str( translate("Arch", "Error: Unable to compute a base shape"))) return else: # computing a shape from a base object if obj.Base.isDerivedFrom("Part::Feature"): if not obj.Base.Shape.isNull(): if obj.Base.Shape.isValid(): base = obj.Base.Shape.copy() face = None if hasattr(obj, "Face"): if obj.Face: if len(base.Faces) >= obj.Face: face = base.Faces[obj.Face - 1] if face: # wall is based on a face 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) elif base.Solids: pass elif (len(base.Faces) == 1) and (not obj.ForceWire): if height: normal.multiply(height) base = base.extrude(normal) elif len(base.Wires) >= 1: temp = None for wire in obj.Base.Shape.Wires: sh = self.getBase(obj, wire, normal, width, height) if temp: temp = temp.fuse(sh) else: temp = sh base = temp elif base.Edges: wire = Part.Wire(base.Edges) if wire: sh = self.getBase(obj, wire, normal, width, height) if sh: base = sh else: base = None FreeCAD.Console.PrintError( str( translate("Arch", "Error: Invalid base object"))) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and ( not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning( str( translate( "Arch", "This mesh is an invalid solid"))) obj.Base.ViewObject.show() base = self.processSubShapes(obj, base, pl) if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( str( translate("Arch", "Couldn't compute the wall shape"))) return try: base = base.removeSplitter() except: FreeCAD.Console.PrintError( str( translate( "Arch", "Error removing splitter from wall shape")) ) obj.Shape = base if not pl.isNull(): obj.Placement = pl
def getRebarData(self,obj): #if not obj.Host: # return #if Draft.getType(obj.Host) != "Structure": # return #if not obj.Host.Shape: # return if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return if not obj.Diameter.Value: return if not obj.Amount: return father = None if obj.Host: father = obj.Host wire = obj.Base.Shape.Wires[0] axis = None if Draft.getType(obj.Base) == "Wire": # Draft Wires can have "wrong" placement import DraftGeomUtils axis = DraftGeomUtils.getNormal(obj.Base.Shape) if not axis: axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,0,-1)) size = 0 if father: size = (ArchCommands.projectToVector(father.Shape.copy(),axis)).Length if hasattr(obj,"Direction"): if not DraftVecUtils.isNull(obj.Direction): axis = FreeCAD.Vector(obj.Direction) axis.normalize() if hasattr(obj,"Distance"): if obj.Distance.Value: size = obj.Distance.Value if hasattr(obj,"Rounding"): if obj.Rounding: radius = obj.Rounding * obj.Diameter.Value import DraftGeomUtils wire = DraftGeomUtils.filletWire(wire,radius) wires = [] if obj.Amount == 1: if size and father: offset = DraftVecUtils.scaleTo(axis,size/2) else: offset = FreeCAD.Vector() wire.translate(offset) wires.append(wire) else: if obj.OffsetStart.Value: baseoffset = DraftVecUtils.scaleTo(axis,obj.OffsetStart.Value) else: baseoffset = None if hasattr(obj, "RebarShape") and obj.RebarShape == "Stirrup": interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value + obj.Diameter.Value) else: interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value) interval = interval / (obj.Amount - 1) vinterval = DraftVecUtils.scaleTo(axis,interval) for i in range(obj.Amount): if i == 0: if baseoffset: wire.translate(baseoffset) wires.append(wire) else: wire = wire.copy() wire.translate(vinterval) wires.append(wire) return [wires,obj.Diameter.Value/2]
def __init__(self,vobj): ArchComponent.ViewProviderComponent.__init__(self,vobj) vobj.addProperty("App::PropertyString","RebarShape","Arch",QT_TRANSLATE_NOOP("App::Property","Shape of rebar")).RebarShape vobj.ShapeColor = ArchCommands.getDefaultColor("Rebar") vobj.setEditorMode("RebarShape",2)
def editUShapeRebar( Rebar, f_cover, b_cover, r_cover, l_cover, diameter, t_cover, rounding, amount_spacing_check, amount_spacing_value, orientation, structure=None, facename=None, ): sketch = Rebar.Base if structure and facename: sketch.Support = [(structure, facename)] # Check if sketch support is empty. if not sketch.Support: showWarning( "You have checked: 'Remove external geometry of base sketches when " "needed.'\nTo uncheck: Edit->Preferences->Arch.") return # Assigned values facename = sketch.Support[0][1][0] structure = sketch.Support[0][0] face = structure.Shape.Faces[getFaceNumber(facename) - 1] # StructurePRM = getTrueParametersOfStructure(structure) # Get parameters of the face where sketch of rebar is drawn FacePRM = getParametersOfFace(structure, facename) # Get points of U-Shape rebar points = getpointsOfUShapeRebar( FacePRM, r_cover, l_cover, b_cover, t_cover, orientation, diameter, facenormalDirection(structure, facename), ) sketch.movePoint(0, 1, points[0], 0) FreeCAD.ActiveDocument.recompute() sketch.movePoint(0, 2, points[1], 0) FreeCAD.ActiveDocument.recompute() sketch.movePoint(1, 1, points[1], 0) FreeCAD.ActiveDocument.recompute() sketch.movePoint(1, 2, points[2], 0) FreeCAD.ActiveDocument.recompute() sketch.movePoint(2, 1, points[2], 0) FreeCAD.ActiveDocument.recompute() sketch.movePoint(2, 2, points[3], 0) FreeCAD.ActiveDocument.recompute() Rebar.OffsetStart = f_cover + diameter / 2 Rebar.OffsetEnd = f_cover + diameter / 2 if amount_spacing_check: Rebar.Amount = amount_spacing_value FreeCAD.ActiveDocument.recompute() Rebar.AmountCheck = True else: size = (ArchCommands.projectToVector(structure.Shape.copy(), face.normalAt(0, 0))).Length Rebar.Amount = get_rebar_amount_from_spacing(size, diameter, amount_spacing_value) FreeCAD.ActiveDocument.recompute() Rebar.AmountCheck = False Rebar.Diameter = diameter Rebar.FrontCover = f_cover Rebar.RightCover = r_cover Rebar.LeftCover = l_cover Rebar.BottomCover = b_cover Rebar.TopCover = t_cover Rebar.Rounding = rounding Rebar.TrueSpacing = amount_spacing_value Rebar.Orientation = orientation FreeCAD.ActiveDocument.recompute() return Rebar
def execute(self, obj): "creates the panel shape" if self.clone(obj): return import Part, DraftGeomUtils # base tests if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return elif obj.Base.isDerivedFrom("Mesh::Feature"): if not obj.Base.Mesh.isSolid(): return else: if obj.Length.Value: length = obj.Length.Value else: return if obj.Width.Value: width = obj.Width.Value else: return if obj.Thickness.Value: thickness = obj.Thickness.Value else: if not obj.Base: return elif obj.Base.isDerivedFrom("Part::Feature"): if not obj.Base.Shape.Solids: return # creating base shape pl = obj.Placement base = None normal = None baseprofile = None if obj.Base: base = obj.Base.Shape.copy() if not base.Solids: p = FreeCAD.Placement(obj.Base.Placement) if base.Faces: baseprofile = base normal = baseprofile.Faces[0].normalAt( 0, 0).multiply(thickness) base = base.extrude(normal) elif base.Wires: closed = True for w in base.Wires: if not w.isClosed(): closed = False if closed: baseprofile = ArchCommands.makeFace(base.Wires) normal = baseprofile.normalAt(0, 0).multiply(thickness) base = baseprofile.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: normal = Vector(0, 0, 1).multiply(thickness) l2 = length / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) base = Part.makePolygon([v1, v2, v3, v4, v1]) baseprofile = Part.Face(base) base = baseprofile.extrude(normal) if hasattr(obj, "Area"): if baseprofile: obj.Area = baseprofile.Area if hasattr(obj, "WaveLength"): if baseprofile and obj.WaveLength.Value and obj.WaveHeight.Value: # corrugated element bb = baseprofile.BoundBox bb.enlarge(bb.DiagonalLength) p1 = Vector(bb.getPoint(0).x, bb.getPoint(0).y, bb.Center.z) if obj.WaveType == "Curved": p2 = p1.add( Vector(obj.WaveLength.Value / 2, 0, obj.WaveHeight.Value)) p3 = p2.add( Vector(obj.WaveLength.Value / 2, 0, -obj.WaveHeight.Value)) e1 = Part.Arc(p1, p2, p3).toShape() p4 = p3.add( Vector(obj.WaveLength.Value / 2, 0, -obj.WaveHeight.Value)) p5 = p4.add( Vector(obj.WaveLength.Value / 2, 0, obj.WaveHeight.Value)) e2 = Part.Arc(p3, p4, p5).toShape() else: if obj.WaveHeight.Value < obj.WaveLength.Value: p2 = p1.add( Vector(obj.WaveHeight.Value, 0, obj.WaveHeight.Value)) p3 = p2.add( Vector( obj.WaveLength.Value - 2 * obj.WaveHeight.Value, 0, 0)) p4 = p3.add( Vector(obj.WaveHeight.Value, 0, -obj.WaveHeight.Value)) e1 = Part.makePolygon([p1, p2, p3, p4]) p5 = p4.add( Vector(obj.WaveHeight.Value, 0, -obj.WaveHeight.Value)) p6 = p5.add( Vector( obj.WaveLength.Value - 2 * obj.WaveHeight.Value, 0, 0)) p7 = p6.add( Vector(obj.WaveHeight.Value, 0, obj.WaveHeight.Value)) e2 = Part.makePolygon([p4, p5, p6, p7]) else: p2 = p1.add( Vector(obj.WaveLength.Value / 2, 0, obj.WaveHeight.Value)) p3 = p2.add( Vector(obj.WaveLength.Value / 2, 0, -obj.WaveHeight.Value)) e1 = Part.makePolygon([p1, p2, p3]) p4 = p3.add( Vector(obj.WaveLength.Value / 2, 0, -obj.WaveHeight.Value)) p5 = p4.add( Vector(obj.WaveLength.Value / 2, 0, obj.WaveHeight.Value)) e2 = Part.makePolygon([p3, p4, p5]) edges = [e1, e2] for i in range(int(bb.XLength / (obj.WaveLength.Value * 2))): e1 = e1.copy() e1.translate(Vector(obj.WaveLength.Value * 2, 0, 0)) e2 = e2.copy() e2.translate(Vector(obj.WaveLength.Value * 2, 0, 0)) edges.extend([e1, e2]) basewire = Part.Wire(edges) baseface = basewire.extrude(Vector(0, bb.YLength, 0)) base = baseface.extrude(Vector(0, 0, thickness)) rot = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), normal) base.rotate(bb.Center, rot.Axis, math.degrees(rot.Angle)) if obj.WaveDirection.Value: base.rotate(bb.Center, normal, obj.WaveDirection.Value) n1 = normal.negative().normalize().multiply( obj.WaveHeight.Value * 2) self.vol = baseprofile.copy() self.vol.translate(n1) self.vol = self.vol.extrude(n1.negative().multiply(2)) base = self.vol.common(base) base = base.removeSplitter() if not base: FreeCAD.Console.PrintError( transpate("Arch", "Error computing shape of ") + obj.Label + "\n") return False if base and (obj.Sheets > 1) and normal and thickness: bases = [base] for i in range(1, obj.Sheets): n = FreeCAD.Vector(normal).normalize().multiply(i * thickness) b = base.copy() b.translate(n) bases.append(b) base = Part.makeCompound(bases) if base and normal and hasattr(obj, "Offset"): if obj.Offset.Value: v = DraftVecUtils.scaleTo(normal, obj.Offset.Value) base.translate(v) # process subshapes base = self.processSubShapes(obj, base, pl) # applying if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( translate("Arch", "Couldn't compute a shape")) return base = base.removeSplitter() obj.Shape = base if not pl.isNull(): obj.Placement = pl
def makeUShapeRebar( f_cover, b_cover, r_cover, l_cover, diameter, t_cover, rounding, amount_spacing_check, amount_spacing_value, orientation="Bottom", structure=None, facename=None, ): """makeUShapeRebar(FrontCover, BottomCover, RightCover, LeftCover, Diameter, Topcover, Rounding, AmountSpacingCheck, AmountSpacingValue, Orientation, Structure, Facename): Adds the U-Shape reinforcement bar to the selected structural object. It takes four different types of orientations as input i.e 'Bottom', 'Top', 'Right', 'Left'. """ if not structure and not facename: selected_obj = FreeCADGui.Selection.getSelectionEx()[0] structure = selected_obj.Object facename = selected_obj.SubElementNames[0] face = structure.Shape.Faces[getFaceNumber(facename) - 1] # StructurePRM = getTrueParametersOfStructure(structure) FacePRM = getParametersOfFace(structure, facename) if not FacePRM: FreeCAD.Console.PrintError( "Cannot identify shape or from which base object structural " "element is derived\n") return # Get points of U-Shape rebar points = getpointsOfUShapeRebar( FacePRM, r_cover, l_cover, b_cover, t_cover, orientation, diameter, facenormalDirection(structure, facename), ) import Part import Arch sketch = FreeCAD.activeDocument().addObject("Sketcher::SketchObject", "Sketch") sketch.MapMode = "FlatFace" sketch.Support = [(structure, facename)] FreeCAD.ActiveDocument.recompute() sketch.addGeometry(Part.LineSegment(points[0], points[1]), False) sketch.addGeometry(Part.LineSegment(points[1], points[2]), False) sketch.addGeometry(Part.LineSegment(points[2], points[3]), False) if amount_spacing_check: rebar = Arch.makeRebar( structure, sketch, diameter, amount_spacing_value, f_cover + diameter / 2, name="UShapeRebar", ) FreeCAD.ActiveDocument.recompute() else: size = (ArchCommands.projectToVector(structure.Shape.copy(), face.normalAt(0, 0))).Length rebar = Arch.makeRebar( structure, sketch, diameter, get_rebar_amount_from_spacing(size, diameter, amount_spacing_value), f_cover + diameter / 2, name="UShapeRebar", ) rebar.Rounding = rounding # Adds properties to the rebar object rebar.addProperty( "App::PropertyEnumeration", "RebarShape", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar"), ).RebarShape = RebarTypes.tolist() rebar.RebarShape = "UShapeRebar" rebar.setEditorMode("RebarShape", 2) rebar.addProperty( "App::PropertyDistance", "FrontCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Front cover of rebar"), ).FrontCover = f_cover rebar.setEditorMode("FrontCover", 2) rebar.addProperty( "App::PropertyDistance", "RightCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Right Side cover of rebar"), ).RightCover = r_cover rebar.setEditorMode("RightCover", 2) rebar.addProperty( "App::PropertyDistance", "LeftCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Left Side cover of rebar"), ).LeftCover = l_cover rebar.setEditorMode("LeftCover", 2) rebar.addProperty( "App::PropertyDistance", "BottomCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Bottom cover of rebar"), ).BottomCover = b_cover rebar.setEditorMode("BottomCover", 2) rebar.addProperty( "App::PropertyBool", "AmountCheck", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Amount radio button is checked"), ) rebar.setEditorMode("AmountCheck", 2) rebar.addProperty( "App::PropertyDistance", "TopCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Top cover of rebar"), ).TopCover = t_cover rebar.setEditorMode("TopCover", 2) rebar.addProperty( "App::PropertyDistance", "TrueSpacing", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Spacing between of rebars"), ).TrueSpacing = amount_spacing_value rebar.setEditorMode("TrueSpacing", 2) rebar.addProperty( "App::PropertyString", "Orientation", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar"), ).Orientation = orientation rebar.setEditorMode("Orientation", 2) if amount_spacing_check: rebar.AmountCheck = True else: rebar.AmountCheck = False rebar.TrueSpacing = amount_spacing_value FreeCAD.ActiveDocument.recompute() return rebar
def execute(self, obj): "builds the wall shape" if self.clone(obj): return import Part, DraftGeomUtils base = None pl = obj.Placement extdata = self.getExtrusionData(obj) if extdata: base = extdata[0] extv = extdata[2].Rotation.multVec(extdata[1]) if isinstance(base, list): shps = [] for b in base: b.Placement = extdata[2].multiply(b.Placement) b = b.extrude(extv) shps.append(b) base = Part.makeCompound(shps) else: base.Placement = extdata[2].multiply(base.Placement) base = base.extrude(extv) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return elif obj.Base.Shape.Solids: base = obj.Base.Shape.copy() elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and ( not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning( translate("Arch", "This mesh is an invalid solid") + "\n") obj.Base.ViewObject.show() if not base: FreeCAD.Console.PrintError( translate("Arch", "Error: Invalid base object") + "\n") return base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl) # set the length property if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Edges: if not obj.Base.Shape.Faces: if hasattr(obj.Base.Shape, "Length"): l = obj.Base.Shape.Length if obj.Length.Value != l: obj.Length = l
def onChanged(self, obj, prop): if prop in ["Source", "RenderingMode", "ShowCut"]: import Part, DraftGeomUtils if hasattr(obj, "Source"): if obj.Source: if obj.Source.Objects: objs = Draft.getGroupContents(obj.Source.Objects, walls=True, addgroups=True) objs = Draft.removeHidden(objs) # separate spaces self.spaces = [] os = [] for o in objs: if Draft.getType(o) == "Space": self.spaces.append(o) else: os.append(o) objs = os self.svg = '' fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"' fillpattern += ' x="0" y="0" width="10" height="10">' fillpattern += '<g>' fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>' # generating SVG if obj.RenderingMode == "Solid": # render using the Arch Vector Renderer import ArchVRM, WorkingPlane wp = WorkingPlane.plane() wp.setFromPlacement(obj.Source.Placement) #wp.inverse() render = ArchVRM.Renderer() render.setWorkingPlane(wp) render.addObjects(objs) if hasattr(obj, "ShowCut"): render.cut(obj.Source.Shape, obj.ShowCut) else: render.cut(obj.Source.Shape) self.svg += '<g transform="scale(1,-1)">\n' self.svg += render.getViewSVG( linewidth="LWPlaceholder") self.svg += fillpattern self.svg += render.getSectionSVG( linewidth="SWPlaceholder", fillpattern="sectionfill") if hasattr(obj, "ShowCut"): if obj.ShowCut: self.svg += render.getHiddenSVG( linewidth="LWPlaceholder") self.svg += '</g>\n' # print render.info() else: # render using the Drawing module import Drawing, Part shapes = [] hshapes = [] sshapes = [] p = FreeCAD.Placement(obj.Source.Placement) self.direction = p.Rotation.multVec( FreeCAD.Vector(0, 0, 1)) for o in objs: if o.isDerivedFrom("Part::Feature"): if o.Shape.isNull(): pass #FreeCAD.Console.PrintWarning(translate("Arch","Skipping empty object: ")+o.Name) elif o.Shape.isValid(): if hasattr(obj.Source, "OnlySolids"): if obj.Source.OnlySolids: shapes.extend(o.Shape.Solids) else: shapes.append(o.Shape) else: shapes.extend(o.Shape.Solids) else: FreeCAD.Console.PrintWarning( translate( "Arch", "Skipping invalid object: ") + o.Name) cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume( obj.Source.Shape.copy(), shapes) if cutvolume: nsh = [] for sh in shapes: for sol in sh.Solids: if sol.Volume < 0: sol.reverse() c = sol.cut(cutvolume) s = sol.section(cutface) try: wires = DraftGeomUtils.findWires( s.Edges) for w in wires: f = Part.Face(w) sshapes.append(f) #s = Part.Wire(s.Edges) #s = Part.Face(s) except Part.OCCError: #print "ArchDrawingView: unable to get a face" sshapes.append(s) nsh.extend(c.Solids) #sshapes.append(s) if hasattr(obj, "ShowCut"): if obj.ShowCut: c = sol.cut(invcutvolume) hshapes.append(c) shapes = nsh if shapes: self.shapes = shapes self.baseshape = Part.makeCompound(shapes) svgf = Drawing.projectToSVG( self.baseshape, self.direction) if svgf: svgf = svgf.replace( 'stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace( 'stroke-width="1"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace( 'stroke-width:0.01', 'stroke-width:LWPlaceholder') self.svg += svgf if hshapes: hshapes = Part.makeCompound(hshapes) self.hiddenshape = hshapes svgh = Drawing.projectToSVG( hshapes, self.direction) if svgh: svgh = svgh.replace( 'stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace( 'stroke-width="1"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace( 'stroke-width:0.01', 'stroke-width:LWPlaceholder') svgh = svgh.replace( 'fill="none"', 'fill="none"\nstroke-dasharray="DAPlaceholder"' ) self.svg += svgh if sshapes: svgs = "" if hasattr(obj, "ShowFill"): if obj.ShowFill: svgs += fillpattern svgs += '<g transform="rotate(180)">\n' for s in sshapes: if s.Edges: f = Draft.getSVG( s, direction=self.direction. negative(), linewidth=0, fillstyle="sectionfill", color=(0, 0, 0)) svgs += f svgs += "</g>\n" sshapes = Part.makeCompound(sshapes) self.sectionshape = sshapes svgs += Drawing.projectToSVG( sshapes, self.direction) if svgs: svgs = svgs.replace( 'stroke-width="0.35"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace( 'stroke-width="1"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace( 'stroke-width:0.01', 'stroke-width:SWPlaceholder') svgs = svgs.replace( 'stroke-width="0.35 px"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace( 'stroke-width:0.35', 'stroke-width:SWPlaceholder') self.svg += svgs
def execute(self, obj): "creates the structure shape" import Part, DraftGeomUtils if self.clone(obj): return normal, length, width, height = self.getDefaultValues(obj) # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return if hasattr(obj, "Tool"): if obj.Tool: try: base = obj.Tool.Shape.copy().makePipe( obj.Base.Shape.copy()) except Part.OCCError: FreeCAD.Console.PrintError( translate( "Arch", "Error: The base shape couldn't be extruded along this tool object" )) return if not base: if not height: return if obj.Normal == Vector(0, 0, 0): p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(normal) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): try: base = Part.Face(base.Wires[0]) base = base.extrude(normal) except Part.OCCError: FreeCAD.Console.PrintError( obj.Label + " : " + str( translate( "Arch", "Unable to extrude the base shape\n" ))) return elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and ( not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning( str( translate( "Arch", "This mesh is an invalid solid"))) obj.Base.ViewObject.show() else: base = self.getProfiles(obj) if base: if length > height: normal = normal.multiply(length) else: normal = normal.multiply(height) base = Part.Face(base[0]) base = base.extrude(normal) base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl)
def getCutShapes(objs,section,showHidden,groupSshapesByObject=False): import Part,DraftGeomUtils shapes = [] hshapes = [] sshapes = [] objectShapes = [] objectSshapes = [] for o in objs: if o.isDerivedFrom("Part::Feature"): if o.Shape.isNull(): pass elif section.OnlySolids: if o.Shape.isValid(): solids = [] solids.extend(o.Shape.Solids) shapes.extend(solids) objectShapes.append((o, solids)) else: print(section.Label,": Skipping invalid object:",o.Label) else: shapes.append(o.Shape) objectShapes.append((o, [o.Shape])) cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes) if cutvolume: for o, shapeList in objectShapes: tmpSshapes = [] for sh in shapeList: for sol in sh.Solids: if sol.Volume < 0: sol.reverse() c = sol.cut(cutvolume) s = sol.section(cutface) try: wires = DraftGeomUtils.findWires(s.Edges) for w in wires: f = Part.Face(w) tmpSshapes.append(f) #s = Part.Wire(s.Edges) #s = Part.Face(s) except Part.OCCError: #print "ArchDrawingView: unable to get a face" tmpSshapes.append(s) shapes.extend(c.Solids) #sshapes.append(s) if showHidden: c = sol.cut(invcutvolume) hshapes.append(c) if len(tmpSshapes) > 0: sshapes.extend(tmpSshapes) if groupSshapesByObject: objectSshapes.append((o, tmpSshapes)) if groupSshapesByObject: return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume,objectSshapes else: return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume
def read(filename): "Parses an IFC file" # parsing the IFC file t1 = time.time() processedIds = [] if getIfcOpenShell() and not FORCE_PYTHON_PARSER: # use the IfcOpenShell parser # check for IFcOpenShellVersion global IOC_ADVANCED if hasattr(IfcImport,"IfcFile"): IOC_ADVANCED = True else: IOC_ADVANCED = False # preparing IfcOpenShell if DEBUG: global ifcObjects,ifcParents ifcObjects = {} # a table to relate ifc id with freecad object ifcParents = {} # a table to relate ifc id with parent id if SEPARATE_OPENINGS: if hasattr(IfcImport,"DISABLE_OPENING_SUBTRACTIONS"): IfcImport.Settings(IfcImport.DISABLE_OPENING_SUBTRACTIONS,True) else: SKIP.append("IfcOpeningElement") useShapes = False if IOC_ADVANCED: useShapes = True elif hasattr(IfcImport,"USE_BREP_DATA"): IfcImport.Settings(IfcImport.USE_BREP_DATA,True) useShapes = True else: if DEBUG: print "Warning: IfcOpenShell version very old, unable to handle Brep data" # opening file if IOC_ADVANCED: global ifc ifc = IfcImport.open(filename) objects = ifc.by_type("IfcProduct") num_lines = len(objects) relations = ifc.by_type("IfcRelAggregates") + ifc.by_type("IfcRelContainedInSpatialStructure") + ifc.by_type("IfcRelVoidsElement") if not objects: print "Error opening IFC file" return else: num_lines = sum(1 for line in pyopen(filename)) if not IfcImport.Init(filename): print "Error opening IFC file" return # processing geometry idx = 0 while True: if IOC_ADVANCED: obj = objects[idx] idx += 1 objid = int(str(obj).split("=")[0].strip("#")) objname = obj.get_argument(obj.get_argument_index("Name")) objtype = str(obj).split("=")[1].split("(")[0] objparentid = -1 for r in relations: if r.is_a("IfcRelAggregates"): for c in getAttr(r,"RelatedObjects"): if str(obj) == str(c): objparentid = int(str(getAttr(r,"RelatingObject")).split("=")[0].strip("#")) elif r.is_a("IfcRelContainedInSpatialStructure"): for c in getAttr(r,"RelatedElements"): if str(obj) == str(c): objparentid = int(str(getAttr(r,"RelatingStructure")).split("=")[0].strip("#")) elif r.is_a("IfcRelVoidsElement"): if str(obj) == str(getAttr(r,"RelatedOpeningElement")): objparentid = int(str(getAttr(r,"RelatingBuildingElement")).split("=")[0].strip("#")) else: if hasattr(IfcImport, 'GetBrepData'): obj = IfcImport.GetBrepData() else: obj = IfcImport.Get() objid = obj.id idx = objid objname = obj.name objtype = obj.type objparentid = obj.parent_id if DEBUG: print "["+str(int((float(idx)/num_lines)*100))+"%] parsing ",objid,": ",objname," of type ",objtype # retrieving name n = getCleanName(objname,objid,objtype) # skip types if objtype in SKIP: if DEBUG: print "skipping because type is in skip list" nobj = None # check if object was already processed, to workaround an ifcopenshell bug elif objid in processedIds: if DEBUG: print "skipping because this object was already processed" else: # build shape shape = None if useShapes: shape = getShape(obj,objid) # walls if objtype in ["IfcWallStandardCase","IfcWall"]: nobj = makeWall(objid,shape,n) # windows elif objtype in ["IfcWindow","IfcDoor"]: nobj = makeWindow(objid,shape,n) # structs elif objtype in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]: nobj = makeStructure(objid,shape,objtype,n) # roofs elif objtype in ["IfcRoof"]: nobj = makeRoof(objid,shape,n) # furniture elif objtype in ["IfcFurnishingElement"]: nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Shape = shape # sites elif objtype in ["IfcSite"]: nobj = makeSite(objid,shape,n) # floors elif objtype in ["IfcBuildingStorey"]: nobj = Arch.makeFloor(name=n) nobj.Label = n # floors elif objtype in ["IfcBuilding"]: nobj = Arch.makeBuilding(name=n) nobj.Label = n # spaces elif objtype in ["IfcSpace"]: nobj = makeSpace(objid,shape,n) elif shape: # treat as dumb parts #if DEBUG: print "Fixme: Shape-containing object not handled: ",obj.id, " ", obj.type nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Label = n nobj.Shape = shape else: # treat as meshes if DEBUG: print "Warning: Object without shape: ",objid, " ", objtype if hasattr(obj,"mesh"): if not hasattr(obj.mesh, 'verts'): obj = IfcImport.Get() # Get triangulated rep of same product me,pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n) nobj.Label = n nobj.Mesh = me nobj.Placement = pl else: if DEBUG: print "Error: Skipping object without mesh: ",objid, " ", objtype # registering object number and parent if objparentid > 0: ifcParents[objid] = [objparentid,not (objtype in subtractiveTypes)] ifcObjects[objid] = nobj processedIds.append(objid) if IOC_ADVANCED: if idx >= len(objects): break else: if not IfcImport.Next(): break # processing non-geometry and relationships parents_temp = dict(ifcParents) import ArchCommands #print parents_temp while parents_temp: id, c = parents_temp.popitem() parent_id = c[0] additive = c[1] if (id <= 0) or (parent_id <= 0): # root dummy object parent = None elif parent_id in ifcObjects: parent = ifcObjects[parent_id] # check if parent is a subtraction, if yes parent to grandparent if parent_id in ifcParents: if ifcParents[parent_id][1] == False: grandparent_id = ifcParents[parent_id][0] if grandparent_id in ifcObjects: parent = ifcObjects[grandparent_id] else: # creating parent if needed if IOC_ADVANCED: parent_ifcobj = ifc.by_id(parent_id) parentid = int(str(obj).split("=")[0].strip("#")) parentname = obj.get_argument(obj.get_argument_index("Name")) parenttype = str(obj).split("=")[1].split("(")[0] else: parent_ifcobj = IfcImport.GetObject(parent_id) parentid = obj.id parentname = obj.name parenttype = obj.type #if DEBUG: print "["+str(int((float(idx)/num_lines)*100))+"%] parsing ",parentid,": ",parentname," of type ",parenttype n = getCleanName(parentname,parentid,parenttype) if parentid <= 0: parent = None elif parenttype == "IfcBuildingStorey": parent = Arch.makeFloor(name=n) parent.Label = n elif parenttype == "IfcBuilding": parent = Arch.makeBuilding(name=n) parent.Label = n elif parenttype == "IfcSite": parent = Arch.makeSite(name=n) parent.Label = n elif parenttype == "IfcWindow": parent = Arch.makeWindow(name=n) parent.Label = n else: if DEBUG: print "Fixme: skipping unhandled parent: ", parentid, " ", parenttype parent = None # registering object number and parent if not IOC_ADVANCED: if parent_ifcobj.parent_id > 0: ifcParents[parentid] = [parent_ifcobj.parent_id,True] parents_temp[parentid] = [parent_ifcobj.parent_id,True] if parent and (not parentid in ifcObjects): ifcObjects[parentid] = parent # attributing parent if parent and (id in ifcObjects): if ifcObjects[id] and (ifcObjects[id].Name != parent.Name): if additive: if DEBUG: print "adding ",ifcObjects[id].Name, " to ",parent.Name ArchCommands.addComponents(ifcObjects[id],parent) else: if DEBUG: print "removing ",ifcObjects[id].Name, " from ",parent.Name ArchCommands.removeComponents(ifcObjects[id],parent) if not IOC_ADVANCED: IfcImport.CleanUp() else: # use only the internal python parser FreeCAD.Console.PrintWarning(translate("Arch","IfcOpenShell not found or disabled, falling back on internal parser.\n")) schema=getSchema() if schema: if DEBUG: print "opening",filename,"..." ifcReader.DEBUG = DEBUG ifc = ifcReader.IfcDocument(filename,schema=schema) else: FreeCAD.Console.PrintWarning(translate("Arch","IFC Schema not found, IFC import disabled.\n")) return None t2 = time.time() if DEBUG: print "Successfully loaded",ifc,"in %s s" % ((t2-t1)) # getting walls for w in ifc.getEnt("IfcWallStandardCase"): nobj = makeWall(w) # getting windows and doors for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")): nobj = makeWindow(w) # getting structs for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn") \ + ifc.getEnt("IfcFooting")): nobj = makeStructure(w) # getting floors for f in ifc.getEnt("IfcBuildingStorey"): group(f,ifc,"Floor") # getting buildings for b in ifc.getEnt("IfcBuilding"): group(b,ifc,"Building") # getting sites for s in ifc.getEnt("IfcSite"): group(s,ifc,"Site") if DEBUG: print "done parsing. Recomputing..." FreeCAD.ActiveDocument.recompute() t3 = time.time() if DEBUG: print "done processing IFC file in %s s" % ((t3-t1)) return None
def createGeometry(self, obj): import Part, DraftGeomUtils # getting default values height = width = length = 1 if hasattr(obj, "Length"): if obj.Length: length = obj.Length if hasattr(obj, "Width"): if obj.Width: width = obj.Width if hasattr(obj, "Height"): if obj.Height: height = obj.Height # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Normal == Vector(0, 0, 0): p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(Vector(0, 0, 1)) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): base = Part.Face(base.Wires[0]) base = base.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: if obj.Normal == Vector(0, 0, 0): normal = Vector(0, 0, 1) else: normal = Vector(obj.Normal) normal = normal.multiply(height) l2 = length / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) base = Part.makePolygon([v1, v2, v3, v4, v1]) base = Part.Face(base) base = base.extrude(normal) base = self.processSubShapes(obj, base) if base: # applying axes pts = self.getAxisPoints(obj) apl = self.getAxisPlacement(obj) if pts: fsh = [] for i in range(len(pts)): if hasattr(obj, "Exclude"): if i in obj.Exclude: continue sh = base.copy() if apl: sh.Placement.Rotation = apl.Rotation sh.translate(pts[i]) fsh.append(sh) obj.Shape = Part.makeCompound(fsh) # finalizing else: if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( str( translate( "Arch", "Couldn't compute the wall shape")) ) return base = base.removeSplitter() obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl
def execute(self, obj): "creates the panel shape" import Part, DraftGeomUtils # base tests if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return elif obj.Base.isDerivedFrom("Mesh::Feature"): if not obj.Base.Mesh.isSolid(): return else: if obj.Length.Value: length = obj.Length.Value else: return if obj.Width.Value: width = obj.Width.Value else: return if obj.Thickness.Value: thickness = obj.Thickness.Value else: if not obj.Base: return elif obj.Base.isDerivedFrom("Part::Feature"): if not obj.Base.Solids: return # creating base shape pl = obj.Placement base = None normal = None if obj.Base: p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(Vector(0, 0, 1)) normal = normal.multiply(thickness) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: self.BaseProfile = base self.ExtrusionVector = normal base = base.extrude(normal) elif base.Wires: closed = True for w in base.Wires: if not w.isClosed(): closed = False if closed: base = ArchCommands.makeFace(base.Wires) self.BaseProfile = base self.ExtrusionVector = normal base = base.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: normal = Vector(0, 0, 1).multiply(thickness) self.ExtrusionVector = normal l2 = length / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) base = Part.makePolygon([v1, v2, v3, v4, v1]) base = Part.Face(base) self.BaseProfile = base base = base.extrude(self.ExtrusionVector) if base and (obj.Sheets > 1) and normal and thickness: bases = [base] for i in range(1, obj.Sheets): n = FreeCAD.Vector(normal).normalize().multiply(i * thickness) b = base.copy() b.translate(n) bases.append(b) base = Part.makeCompound(bases) if base and normal and hasattr(obj, "Offset"): if obj.Offset.Value: v = DraftVecUtils.scaleTo(normal, obj.Offset.Value) base.translate(v) # process subshapes base = self.processSubShapes(obj, base, pl) # applying if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( translate("Arch", "Couldn't compute a shape")) return base = base.removeSplitter() obj.Shape = base if not pl.isNull(): obj.Placement = pl
def buildSVG(self, obj, join=False): "creates a svg representation" import Part, DraftGeomUtils if hasattr(obj, "Source"): if obj.Source: if obj.Source.Objects: objs = Draft.getGroupContents(obj.Source.Objects, walls=True) objs = Draft.removeHidden(objs) self.svg = '' # generating SVG if obj.RenderingMode == "Solid": # render using the Arch Vector Renderer import ArchVRM render = ArchVRM.Renderer() render.setWorkingPlane(obj.Source.Placement) render.addObjects(objs) if hasattr(obj, "ShowCut"): render.cut(obj.Source.Shape, obj.ShowCut) else: render.cut(obj.Source.Shape) self.svg += render.getViewSVG( linewidth="LWPlaceholder") self.svg += render.getSectionSVG( linewidth="SWPLaceholder") if hasattr(obj, "ShowCut"): if obj.ShowCut: self.svg += render.getHiddenSVG( linewidth="LWPlaceholder") # print render.info() else: # render using the Drawing module import Drawing, Part shapes = [] hshapes = [] sshapes = [] p = FreeCAD.Placement(obj.Source.Placement) self.direction = p.Rotation.multVec( FreeCAD.Vector(0, 0, 1)) for o in objs: if o.isDerivedFrom("Part::Feature"): if o.Shape.isNull(): pass #FreeCAD.Console.PrintWarning(translate("Arch","Skipping empty object: ")+o.Name) elif o.Shape.isValid(): shapes.extend(o.Shape.Solids) else: FreeCAD.Console.PrintWarning( translate("Arch", "Skipping invalid object: ") + o.Name) cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume( obj.Source.Shape.copy(), shapes) if cutvolume: nsh = [] for sh in shapes: for sol in sh.Solids: if sol.Volume < 0: sol.reverse() c = sol.cut(cutvolume) s = sol.section(cutface) nsh.extend(c.Solids) sshapes.append(s) if hasattr(obj, "ShowCut"): if obj.ShowCut: c = sol.cut(invcutvolume) hshapes.append(c) shapes = nsh if shapes: self.shapes = shapes self.baseshape = Part.makeCompound(shapes) svgf = Drawing.projectToSVG( self.baseshape, self.direction) if svgf: svgf = svgf.replace( 'stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace( 'stroke-width="1"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace( 'stroke-width:0.01', 'stroke-width:LWPlaceholder') self.svg += svgf if hshapes: hshapes = Part.makeCompound(hshapes) svgh = Drawing.projectToSVG( hshapes, self.direction) if svgh: svgh = svgh.replace( 'stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace( 'stroke-width="1"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace( 'stroke-width:0.01', 'stroke-width:LWPlaceholder') svgh = svgh.replace( 'fill="none"', 'fill="none"\nstroke-dasharray="0.09,0.05"' ) self.svg += svgh if sshapes: edges = [] for s in sshapes: edges.extend(s.Edges) wires = DraftGeomUtils.findWires(edges) faces = [] for w in wires: if (w.ShapeType == "Wire") and w.isClosed(): faces.append(Part.Face(w)) sshapes = Part.makeCompound(faces) svgs = Drawing.projectToSVG( sshapes, self.direction) if svgs: svgs = svgs.replace( 'stroke-width="0.35"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace( 'stroke-width="1"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace( 'stroke-width:0.01', 'stroke-width:SWPlaceholder') self.svg += svgs