Skip to content

Commit

Permalink
Arch: Added IFC pref option to automatically export IFC objects as St…
Browse files Browse the repository at this point in the history
…andard Cases when possible
  • Loading branch information
yorikvanhavre committed May 9, 2019
1 parent af0cb40 commit 2876e82
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/Mod/Arch/ArchComponent.py
Expand Up @@ -678,6 +678,56 @@ def computeAreas(self,obj):
if obj.PerimeterLength.Value != self.flatarea.Faces[0].OuterWire.Length:
obj.PerimeterLength = self.flatarea.Faces[0].OuterWire.Length

def isStandardCase(self,obj):

# Standard Case has been set manually by the user
if obj.IfcType.endswith("Standard Case"):
return True
# Try to guess
import ArchIFC
if obj.IfcType + " Standard Case" in ArchIFC.IfcTypes:
# this type has a standard case
if obj.Additions or obj.Subtractions:
return False
if obj.Placement.Rotation.Axis.getAngle(FreeCAD.Vector(0,0,1)) > 0.01:
# reject rotated objects
return False
if obj.CloneOf:
return obj.CloneOf.Proxy.isStandardCase(obj.CloneOf)
if obj.IfcType == "Wall":
# rules:
# - vertically extruded
# - single baseline or no baseline
if (not obj.Base) or (len(obj.Base.Shape.Edges) == 1):
if hasattr(obj,"Normal"):
if obj.Normal in [FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1)]:
return True
elif obj.IfcType in ["Beam","Column","Slab"]:
# rules:
# - have a single-wire profile or no profile
# - extrusion direction is perpendicular to the profile
if obj.Base and (len(obj.Base.Shape.Wires) != 1):
return False
if not hasattr(obj,"Normal"):
return False
if hasattr(obj,"Tool") and obj.Tool:
return False
if obj.Normal == FreeCAD.Vector(0,0,0):
return True
elif len(obj.Base.Shape.Wires) == 1:
import DraftGeomUtils
n = DraftGeomUtils.getNormal(obj.Base.Shape)
if n:
if (n.getAngle(obj.Normal) < 0.01) or (abs(n.getAngle(obj.Normal)-3.14159) < 0.01):
return True
# TODO: Support windows and doors
# rules:
# - must have a rectangular shape
# - must have a host
# - must be parallel to the host plane
# - must have an IfcWindowType and IfcRelFillsElement (to be implemented in IFC exporter)
return False


class ViewProviderComponent:

Expand Down
16 changes: 16 additions & 0 deletions src/Mod/Arch/Resources/ui/preferences-ifc.ui
Expand Up @@ -501,6 +501,22 @@
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="checkBox_17">
<property name="toolTip">
<string>Some IFC types such as IfcWall or IfcBeam have special standard versions like IfcWallStandardCase or IfcBeamStandardCase. If this option is turned on, FreeCAD will automatically export such objects as standard cases when the necessary conditions are met.</string>
</property>
<property name="text">
<string>Auto-detet and export as standard cases when applicable</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>getStandardCase</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Arch</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down
12 changes: 12 additions & 0 deletions src/Mod/Arch/importIFC.py
Expand Up @@ -1568,6 +1568,7 @@ def export(exportList,filename):
email = s[1].strip(">")
global template
template = ifctemplate.replace("$version",version[0]+"."+version[1]+" build "+version[2])
getstd = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("getStandardType",False)
if hasattr(ifcopenshell,"schema_identifier"):
schema = ifcopenshell.schema_identifier
elif hasattr(ifcopenshell,"version") and (float(ifcopenshell.version[:3]) >= 0.6):
Expand Down Expand Up @@ -1755,6 +1756,9 @@ def export(exportList,filename):
# getting the representation

representation,placement,shapetype = getRepresentation(ifcfile,context,obj,forcebrep=(brepflag or FORCE_BREP))
if getstd:
if isStandardCase(obj,ifctype):
ifctype += "StandardCase"

if DEBUG: print(str(count).ljust(3)," : ", ifctype, " (",shapetype,") : ",name)

Expand Down Expand Up @@ -2378,6 +2382,14 @@ def export(exportList,filename):
del ifcbin


def isStandardCase(obj,ifctype):

if ifctype.endswith("StandardCase"):
return False # type is already standard case, return False so "StandardCase" is not added twice
if hasattr(obj,"Proxy") and hasattr(obj.Proxy,"isStandardCase"):
return obj.Proxy.isStandardCase(obj)
return False

def getIfcTypeFromObj(obj):

if (Draft.getType(obj) == "BuildingPart") and hasattr(obj,"IfcType") and (obj.IfcType == "Undefined"):
Expand Down

0 comments on commit 2876e82

Please sign in to comment.