Arch: IFC importer can now recreate extrusions
By enabling the setting in IFC preferences, the IFC importer can now detect if an input shape is a normal extrusion, and create the object as a Part::Extrusion.
This commit is contained in:
parent
9967bbe297
commit
c692d6e136
|
@ -208,6 +208,10 @@ def makeComponent(baseobj=None,name="Component",delete=False):
|
|||
obj.Placement = baseobj.Placement
|
||||
if delete:
|
||||
FreeCAD.ActiveDocument.removeObject(baseobj.Name)
|
||||
else:
|
||||
obj.Base = baseobj
|
||||
if FreeCAD.GuiUp:
|
||||
baseobj.ViewObject.hide()
|
||||
elif isinstance(baseobj,Part.Shape):
|
||||
obj.Shape = baseobj
|
||||
return obj
|
||||
|
@ -897,7 +901,45 @@ def rebuildArchShape(objects=None):
|
|||
print "Failed"
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
def getExtrusionData(shape):
|
||||
"""getExtrusionData(shape): returns a base face and an extrusion vector
|
||||
if this shape can be described as a perpendicular extrusion, or None if not."""
|
||||
if shape.isNull():
|
||||
return None
|
||||
if not shape.Solids:
|
||||
return None
|
||||
if len(shape.Faces) < 5:
|
||||
return None
|
||||
# build faces list with normals
|
||||
faces = []
|
||||
for f in shape.Faces:
|
||||
faces.append([f,f.normalAt(0,0)])
|
||||
# find opposite normals pairs
|
||||
pairs = []
|
||||
for i1, f1 in enumerate(faces):
|
||||
for i2, f2 in enumerate(faces):
|
||||
if f1[0].hashCode() != f2[0].hashCode():
|
||||
if round(f1[1].getAngle(f2[1]),8) == 3.14159265:
|
||||
pairs.append([i1,i2])
|
||||
if not pairs:
|
||||
return None
|
||||
for p in pairs:
|
||||
hc = [faces[p[0]][0].hashCode(),faces[p[1]][0].hashCode()]
|
||||
ok = True
|
||||
# check if other normals are all at 90 degrees
|
||||
for f in faces:
|
||||
if f[0].hashCode() not in hc:
|
||||
if round(f[1].getAngle(faces[p[0]][1]),8) != 1.57079633:
|
||||
ok = False
|
||||
if ok:
|
||||
return [faces[p[0]][0],faces[p[1]][0].CenterOfMass.sub(faces[p[0]][0].CenterOfMass)]
|
||||
return None
|
||||
|
||||
|
||||
# command definitions ###############################################
|
||||
|
||||
|
||||
class _CommandAdd:
|
||||
"the Arch Add command definition"
|
||||
def GetResources(self):
|
||||
|
@ -1053,6 +1095,7 @@ class _CommandSelectNonSolidMeshes:
|
|||
for o in sel:
|
||||
FreeCADGui.Selection.addSelection(o)
|
||||
|
||||
|
||||
class _CommandRemoveShape:
|
||||
"the Arch RemoveShape command definition"
|
||||
def GetResources(self):
|
||||
|
@ -1067,6 +1110,7 @@ class _CommandRemoveShape:
|
|||
sel = FreeCADGui.Selection.getSelection()
|
||||
removeShape(sel)
|
||||
|
||||
|
||||
class _CommandCloseHoles:
|
||||
"the Arch CloseHoles command definition"
|
||||
def GetResources(self):
|
||||
|
@ -1083,6 +1127,7 @@ class _CommandCloseHoles:
|
|||
if s:
|
||||
o.Shape = s
|
||||
|
||||
|
||||
class _CommandCheck:
|
||||
"the Arch Check command definition"
|
||||
def GetResources(self):
|
||||
|
@ -1146,8 +1191,8 @@ class _ToggleIfcBrepFlag:
|
|||
def Activated(self):
|
||||
for o in FreeCADGui.Selection.getSelection():
|
||||
toggleIfcBrepFlag(o)
|
||||
|
||||
|
||||
|
||||
|
||||
class _CommandComponent:
|
||||
"the Arch Component command definition"
|
||||
def GetResources(self):
|
||||
|
|
|
@ -306,7 +306,8 @@ class Component:
|
|||
obj.Role = Roles
|
||||
|
||||
def execute(self,obj):
|
||||
return
|
||||
if obj.Base:
|
||||
obj.Shape = obj.Base.Shape
|
||||
|
||||
def __getstate__(self):
|
||||
return self.Type
|
||||
|
@ -378,7 +379,13 @@ class Component:
|
|||
wires = []
|
||||
n,l,w,h = self.getDefaultValues(obj)
|
||||
if obj.Base:
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if obj.Base.isDerivedFrom("Part::Extrusion"):
|
||||
if obj.Base.Base:
|
||||
base = obj.Base.Base.Shape.copy()
|
||||
if noplacement:
|
||||
base.Placement = FreeCAD.Placement()
|
||||
return [base]
|
||||
elif obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if obj.Base.Shape:
|
||||
base = obj.Base.Shape.copy()
|
||||
if noplacement:
|
||||
|
@ -469,6 +476,9 @@ class Component:
|
|||
def getExtrusionVector(self,obj,noplacement=False):
|
||||
"Returns an extrusion vector of this component, if applicable"
|
||||
n,l,w,h = self.getDefaultValues(obj)
|
||||
if obj.Base:
|
||||
if obj.Base.isDerivedFrom("Part::Extrusion"):
|
||||
return obj.Base.Dir
|
||||
if Draft.getType(obj) == "Structure":
|
||||
if l > h:
|
||||
v = n.multiply(l)
|
||||
|
|
|
@ -137,6 +137,26 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_2">
|
||||
<property name="toolTip">
|
||||
<string>If this is checked, the importer will try to detect extrusions. This might slow things down...</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Detect extrusions</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ifcGetExtrusions</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
|
|
|
@ -270,11 +270,13 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
SKIP = p.GetString("ifcSkip","").split(",")
|
||||
SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False)
|
||||
ROOT_ELEMENT = p.GetString("ifcRootElement","IfcProduct")
|
||||
GET_EXTRUSIONS = p.GetBool("ifcGetExtrusions",False)
|
||||
if root:
|
||||
ROOT_ELEMENT = root
|
||||
MERGE_MODE = p.GetInt("ifcImportMode",0)
|
||||
if MERGE_MODE > 0:
|
||||
SEPARATE_OPENINGS = False
|
||||
GET_EXTRUSIONS = False
|
||||
if not SEPARATE_OPENINGS:
|
||||
SKIP.append("IfcOpeningElement")
|
||||
|
||||
|
@ -418,13 +420,25 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
if DEBUG: print shape.Solids
|
||||
baseobj = shape
|
||||
else:
|
||||
baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
|
||||
baseobj.Shape = shape
|
||||
if GET_EXTRUSIONS:
|
||||
ex = Arch.getExtrusionData(shape)
|
||||
if ex:
|
||||
print "extrusion ",
|
||||
baseface = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_footprint")
|
||||
baseface.Shape = ex[0]
|
||||
baseobj = FreeCAD.ActiveDocument.addObject("Part::Extrusion",name+"_body")
|
||||
baseobj.Base = baseface
|
||||
baseobj.Dir = ex[1]
|
||||
if FreeCAD.GuiUp:
|
||||
baseface.ViewObject.hide()
|
||||
if not baseobj:
|
||||
baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
|
||||
baseobj.Shape = shape
|
||||
else:
|
||||
if DEBUG: print "null shape ",
|
||||
if not shape.isValid():
|
||||
if DEBUG: print "invalid shape. Skipping"
|
||||
continue
|
||||
if DEBUG: print "invalid shape ",
|
||||
#continue
|
||||
|
||||
else:
|
||||
if DEBUG: print " no brep ",
|
||||
|
@ -436,6 +450,8 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
if ptype in ifctypes:
|
||||
obj = getattr(Arch,"make"+freecadtype)(baseobj=baseobj,name=name)
|
||||
obj.Label = name
|
||||
if FreeCAD.GuiUp and baseobj:
|
||||
baseobj.ViewObject.hide()
|
||||
# setting role
|
||||
try:
|
||||
r = ptype[3:]
|
||||
|
@ -455,7 +471,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
obj.IfcAttributes = a
|
||||
break
|
||||
if not obj:
|
||||
obj = Arch.makeComponent(baseobj,name=name,delete=True)
|
||||
obj = Arch.makeComponent(baseobj,name=name)
|
||||
if obj:
|
||||
sols = str(obj.Shape.Solids) if hasattr(obj,"Shape") else "[]"
|
||||
if DEBUG: print sols
|
||||
|
@ -469,7 +485,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
if ptype in ifctypes:
|
||||
obj = getattr(Arch,"make"+freecadtype)(baseobj=None,name=name)
|
||||
elif baseobj:
|
||||
obj = Arch.makeComponent(baseobj,name=name)
|
||||
obj = Arch.makeComponent(baseobj,name=name,delete=True)
|
||||
|
||||
elif MERGE_MODE == 2:
|
||||
|
||||
|
@ -545,7 +561,7 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
if SEPARATE_OPENINGS:
|
||||
for subtraction in subtractions:
|
||||
if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
|
||||
if DEBUG: print "subtracting ",objects[subtraction[0]].Name, " from ", objects[subtraction[1]].Name
|
||||
if DEBUG: print "subtracting ",objects[subtraction[0]].Label, " from ", objects[subtraction[1]].Label
|
||||
Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
|
||||
if DEBUG: FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
@ -558,14 +574,12 @@ def insert(filename,docname,skip=[],only=[],root=None):
|
|||
# avoid huge fusions
|
||||
print "more than 10 shapes to add: skipping."
|
||||
else:
|
||||
if DEBUG: print "adding ",cobs, " to ", objects[host].Name
|
||||
if DEBUG: print "adding ",len(cobs), " object(s) to ", objects[host].Label
|
||||
Arch.addComponents(cobs,objects[host])
|
||||
if DEBUG: FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
if DEBUG: print "Cleaning..."
|
||||
|
||||
# cleaning bad shapes
|
||||
for obj in objects.values():
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
|
|
Loading…
Reference in New Issue
Block a user