Skip to content

Instantly share code, notes, and snippets.

@stefkeB
Last active March 21, 2022 23:08
Show Gist options
  • Save stefkeB/e2b308e13d299328ecd1dc8db2d20cc5 to your computer and use it in GitHub Desktop.
Save stefkeB/e2b308e13d299328ecd1dc8db2d20cc5 to your computer and use it in GitHub Desktop.
IFC Print Hierarchy using IfcOpenShell
#include <string>
#include <iostream>
#include <fstream>
// ifcOpenShell
#ifdef USE_IFC4
#include <ifcparse/Ifc4.h>
#else
#include <ifcparse/Ifc2x3.h>
#endif
#include <ifcparse/IfcBaseClass.h>
#include <ifcparse/IfcHierarchyHelper.h>
using namespace IfcSchema;
// Recursive print function
void PrintEntity(IfcUtil::IfcBaseEntity * entity, int level = 0) {
// ------------------------------------------------
// Print basic stuff
std::string spacer = ". ";
for (int i = 0; i < level; i++)
std::cout << spacer;
// #ID
std::cout << "#" << entity->id() << " = ";
// Classname
std::cout << IfcSchema::Type::ToString(entity->type()) << " ";
// if IfcRoot > name & guid
if (entity->is(IfcRoot::Class())) {
const IfcRoot* root = (IfcRoot*)entity;
if (root->hasName())
std::cout << "'" << root->Name() << "' ";
std::cout << root->GlobalId();
}
// Case - Entity is Property or PhysicalQuantity
if (entity->is(IfcSchema::IfcProperty::Class())) {
std::cout << entity->getArgument(0)->toString() << " ";
std::cout << "= " << entity->getArgument(2)->toString();
}
if (entity->is(IfcSchema::IfcPhysicalQuantity::Class())) {
std::cout << entity->getArgument(0)->toString() << " ";
std::cout << "= " << entity->getArgument(3)->toString();
}
std::cout << std::endl;
// ------------------------------------------------
// Direct Attributes
bool loadAttributes = false;
std::vector<std::string> attNames = entity->getAttributeNames();
for (int i = 0; loadAttributes && (i < (int)attNames.size()); i++) {
for (int i = 0; i < level+1; i++) std::cout << spacer;
std::cout << "'" << attNames[i] << "' = ";
std::cout << entity->getArgument(i)->toString();
std::cout << std::endl;
}
// ------------------------------------------------
// Recursively follow relations
// Case - Entity is SpatialStructureElement
if (entity->is(IfcSpatialStructureElement::Class())) {
const IfcSpatialStructureElement* spatial = (IfcSpatialStructureElement*)entity;
IfcTemplatedEntityList< IfcRelContainedInSpatialStructure >::ptr containsElements = spatial->ContainsElements();
for (IfcTemplatedEntityList< IfcRelContainedInSpatialStructure >::it itContainsElements = containsElements->begin(); itContainsElements != containsElements->end(); ++itContainsElements)
{
IfcRelContainedInSpatialStructure * relContainedInSpatialStructure = (IfcRelContainedInSpatialStructure*)*itContainsElements;
IfcTemplatedEntityList< IfcProduct >::ptr listRelatedElements = relContainedInSpatialStructure->RelatedElements();
IfcTemplatedEntityList< IfcProduct >::it itListRelatedElements = listRelatedElements->begin();
while (itListRelatedElements != listRelatedElements->end()) {
IfcUtil::IfcBaseEntity * item = (IfcUtil::IfcBaseEntity*)(*itListRelatedElements++);
if (item) {
PrintEntity(item, level + 1);
}
}
}
} // end if spatial structure element
// Case - Entity is ObjectDefinition
if (entity->is(IfcObjectDefinition::Class())) {
const IfcObjectDefinition* objDef = (IfcObjectDefinition*)entity;
// Follow Associates relation
IfcTemplatedEntityList<IfcRelAssociates>::ptr hasAssociation = objDef->HasAssociations();
for (IfcTemplatedEntityList<IfcRelAssociates>::it itHasAssociation = hasAssociation->begin();
itHasAssociation != hasAssociation->end(); ++itHasAssociation) {
IfcRelAssociates * relAssociates = (IfcRelAssociates*)*itHasAssociation;
// TODO: do something
} // end if hasAssociation
}
// Case - Entity is Object
if (entity->is(IfcObject::Class())) {
const IfcObject* object = (IfcObject*)entity;
// Follow DecomposedBy relation
IfcTemplatedEntityList< IfcRelDecomposes >::ptr isDecomposedBy = object->IsDecomposedBy();
for (IfcTemplatedEntityList< IfcRelDecomposes >::it itDecomposedBy = isDecomposedBy->begin(); itDecomposedBy != isDecomposedBy->end(); ++itDecomposedBy)
{
IfcRelAggregates * relDecomposedBy = (IfcRelAggregates*)*itDecomposedBy;
IfcTemplatedEntityList< IfcObjectDefinition >::ptr listRelated = relDecomposedBy->RelatedObjects();
IfcTemplatedEntityList< IfcObjectDefinition >::it itListRelated = listRelated->begin();
while (itListRelated != listRelated->end()) {
IfcUtil::IfcBaseEntity * item = (IfcUtil::IfcBaseEntity*)(*itListRelated++);
if (item) {
PrintEntity(item, level + 1);
}
}
} // end if decomposes
// Follow IsDefinedBy relation (PropertySets & Types)
IfcTemplatedEntityList< IfcRelDefines >::ptr isDefinedBy = object->IsDefinedBy();
IfcTemplatedEntityList< IfcRelDefines >::it itIsDefinedBy = isDefinedBy->begin();
while (itIsDefinedBy != isDefinedBy->end()) {
IfcRelDefines * relDefines = (IfcRelDefines*)(*itIsDefinedBy++);
// Type definition
if (relDefines->is(IfcRelDefinesByType::Class())) {
const IfcRelDefinesByType* definesByType = (IfcRelDefinesByType*)relDefines;
const IfcTypeObject * typeObject = definesByType->RelatingType();
IfcUtil::IfcBaseEntity * item = (IfcUtil::IfcBaseEntity*)typeObject;
if (item) {
PrintEntity(item, level + 1);
}
}
// Property Definition
if (relDefines->is(IfcRelDefinesByProperties::Class())) {
const IfcRelDefinesByProperties* definesByProperties = (IfcRelDefinesByProperties*)relDefines;
const IfcPropertyDefinition * propDef = definesByProperties->RelatingPropertyDefinition();
IfcUtil::IfcBaseEntity * item = (IfcUtil::IfcBaseEntity*)propDef;
if (item) {
PrintEntity(item, level + 1);
}
}
} // end IsDefinedBy
} // end if IfcObject
// Case - Entity is PropertySet or ElementQuantity
if (entity->is(IfcPropertyDefinition::Class())) {
// Check Property Definitions
if (entity->is(IfcPropertySet::Class())) {
const IfcPropertySet * propSet = (IfcPropertySet*)entity;
IfcTemplatedEntityList<IfcProperty>::ptr listProperties = propSet->HasProperties();
IfcTemplatedEntityList<IfcProperty>::it itListProperties = listProperties->begin();
while (itListProperties != listProperties->end()) {
IfcUtil::IfcBaseEntity * item = (IfcUtil::IfcBaseEntity*)*itListProperties++;
if (item) {
PrintEntity(item, level + 1);
}
}
} // end if Property Set
// Check Base Quantities
if (entity->is(IfcElementQuantity::Class())) {
const IfcElementQuantity * qSet = (IfcElementQuantity*)entity;
IfcTemplatedEntityList<IfcPhysicalQuantity>::ptr listQuantities = qSet->Quantities();
IfcTemplatedEntityList<IfcPhysicalQuantity>::it itListQuantities = listQuantities->begin();
while (itListQuantities != listQuantities->end()) {
IfcUtil::IfcBaseEntity * item = (IfcUtil::IfcBaseEntity*)*itListQuantities++;
if (item) {
PrintEntity(item, level + 1);
}
}
} // end if Element Quantity
} // end if property definition
}
int main(int argc, char** argv) {
// Read the file
IfcParse::IfcFile file;
if (argc < 1) return 0;
if ( ! file.Init(argv[1]) ) {
std::cout << "Unable to parse .ifc file" << std::endl;
return 1;
}
// Read a list of entities
IfcEntityList::ptr entities(new IfcEntityList());
entities = file.entitiesByType("IfcProject");
for (IfcEntityList::it it = entities->begin(); it != entities->end(); ++it) {
IfcUtil::IfcBaseEntity * entity = (IfcUtil::IfcBaseEntity*)*it;
// Display information about the entity
PrintEntity(entity);
}
return 0;
}
./PrintHierarchy ../Models/IfcOpenHouse.ifc
#12 = IfcProject 'IfcOpenHouse' 1h6kzgF2fA8BQ5niopb7zB
. #18 = IfcSite 0JA17OO9LAV9bo12Oa92B9
. . #25 = IfcBuilding 15SI_NrofB1up99X9U7beo
. . . #32 = IfcBuildingStorey 1alUutlUH7lgQhe1Qj_tCw
. . . . #34 = IfcWallStandardCase 'South wall' 1YuHUfuqrE8wg5PsSQdDrl
. . . . #77 = IfcFooting 'Footing' 2i8H67IeD9IOU1gZO_ty_h
. . . . #187 = IfcRoof 'Roof' 36E1WAkln92OzjkUUsZ8jc
. . . . . #188 = IfcSlab 'South roof' 1MRdn1fY10jf_GACKdtpYF
. . . . . #189 = IfcSlab 'North roof' 3qwKFIswv1dPhYJKlAO2SN
. . . . #219 = IfcWallStandardCase 'North wall' 1KPqQr0Pb6qeClM$oN_Z3b
. . . . #292 = IfcWallStandardCase 'East wall' 3ZW12NntT7ivTZ$F5Qw5tW
. . . . #299 = IfcWallStandardCase 'West wall' 0NBI7eAdzDovnJGU_NnDOH
. . . . #2609 = IfcStairFlight 0gm$yeQRj1xxt0B_0lXzcM
. . . . #2687 = IfcDoor 3Ekq43r6bEoByFKAZ$aeyu
. . . . . #2697 = IfcDoorStyle 'Door type' 2Xk2fURwPBXAnV1gWjo9R6
. . . . #2756 = IfcWindow 3vl_GRpqHA$x$W4D2406Cb
. . . . . #2787 = IfcMember 3v11_y5RfFGfsNCxxYjaJo
. . . . . #2793 = IfcMember 0NB_dqdAD5x9sBPo12CTYg
. . . . . #2804 = IfcMember 342x4ivin36vH6VlAbwStw
. . . . . #2810 = IfcMember 3W3DHl5554Iug8Vs3EMHT9
. . . . . #2830 = IfcPlate 2vASEfqmr2jQRcyFzwSKDL
. . . . #2837 = IfcWindow 0XmWSDolr6jxgsOUPrD6cp
. . . . . #2863 = IfcMember 0Kmy_W8MTDYB0Or_Y1LirZ
. . . . . #2869 = IfcMember 3rzMkPWE9A2BQqA9RHhhDh
. . . . . #2875 = IfcMember 1S4j1NVdn5$Rgwmpq7OplQ
. . . . . #2881 = IfcMember 2MH68WATr9JQnd3o3ocGtQ
. . . . . #2901 = IfcPlate 0ePlx2tv12qPZHPPCZB7G4
. . . . #2908 = IfcWindow 079RXBBfL8Ae1sDpdNHas4
. . . . . #2934 = IfcMember 0zlM3W7qr5OOtGKvHpw5vi
. . . . . #2940 = IfcMember 1nkjoVu058kPUvoUhTi_6Z
. . . . . #2946 = IfcMember 27Ly7Y$GHD4f7Qyp9xnS3i
. . . . . #2952 = IfcMember 19DFw4For1vBB6ibn7IdNd
. . . . . #2972 = IfcPlate 0u12N$PF1EfftDWsWRIFCY
. . . . #2979 = IfcWindow 3$Xk82jXb6KeR0aYzIMPuV
. . . . . #3005 = IfcMember 3jgGlg3jbDdQ56XCrciMAN
. . . . . #3011 = IfcMember 32Myk4z9z6vvS$tcJPg3k8
. . . . . #3017 = IfcMember 2bYkyT22DEFwZAX2K9Uky5
. . . . . #3023 = IfcMember 1n1SamiGb3PORMo8xmdnlp
. . . . . #3043 = IfcPlate 31cdsB4nb4thXmRKmURy07
. . . . #3050 = IfcWindow 0Pqx$ypVv3SxG$K80aN8S9
. . . . . #3076 = IfcMember 3YW9$IZvj7lxRD8IfC3mEl
. . . . . #3082 = IfcMember 0pNcvVYkLCmub7vpcAR0JZ
. . . . . #3088 = IfcMember 1MWAO8n8nDxhKOF07_9oNa
. . . . . #3094 = IfcMember 2tTaYRsI15fejfAj_FQ$Yo
. . . . . #3114 = IfcPlate 3d5PIu9GnFcvO01eDR7s_I
. . #322 = IfcPropertySet 'Pset_SiteCommon' 1bEirXC2P98hf0CiUHc$ik
. . . #321 = IfcPropertySingleValue 'TotalArea' = IfcAreaMeasure(523.31397507897)
## -----------------------------------------------------------------
## qmake project file
##
## Usage: qmake -spec macx-xcode (to generate XCode project)
##
## e.g.
## >> mkdir build && cd build
## >> qmake -spec macx-xcode ../XYZ.pro
## >> open XYZ.xcodeproj/
## -----------------------------------------------------------------
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
OBJECTS_DIR = ./temp/obj
UI_DIR = ./temp/ui
MOC_DIR = ./temp/moc
## IFC 4 Support (instead of Ifc2x3)
# DEFINES += USE_IFC4
INCLUDEPATH += /usr/local/include
LIBS += -L/usr/local/lib
## -----------------------------------------------------------------
## Qt5 (GUI, Application, Integration)
## -----------------------------------------------------------------
QT -= core gui widgets # no Qt Libraries to link
## Enforce debug modus (especially for XCode debug sessions!)
CONFIG += debug # debug_and_release
# This is an unsupported configuration. You may experience build issues, and by using
# the 10.13.4 SDK you are opting in to new features that Qt has not been prepared for.
# Please downgrade the SDK you use to build your app to version 10.13, or configure
# with CONFIG+=sdk_no_version_check when running qmake to silence this warning.
CONFIG+=sdk_no_version_check
# remove ld:warning ... was built for newer OSX version (10.13) than being linked (10.11)
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.13
## -----------------------------------------------------------------
## OpenCASCADE (3D Geometry Support)
## (Not required for this example - no geometry support)
## -----------------------------------------------------------------
# DEFINES += USE_OCC
# INCLUDEPATH += /usr/local/include/oce /usr/local/include/opencascade
# LIBS += -lTKernel -lTKMath -lTKService -lTKV3d -lTKOpenGl \
# -lTKBRep -lTKIGES -lTKSTL -lTKVRML -lTKSTEP -lTKSTEPAttr -lTKSTEP209 \
# -lTKSTEPBase -lTKGeomBase -lTKGeomAlgo -lTKG3d -lTKG2d \
# -lTKXSBase -lTKShHealing -lTKHLR -lTKTopAlgo -lTKMesh -lTKPrim \
# -lTKCDF -lTKBool -lTKBO -lTKFillet -lTKOffset
## -----------------------------------------------------------------
## IfcOpenShell (IFC File Support)
## -----------------------------------------------------------------
LIBS += -lIfcParse # -lIfcGeom
# NEEDS ICU libraries for Unicode Support
LIBS += -L/usr/local/opt/icu4c/lib
LIBS += -licuuc -licudata #-licutu -licuio
INCLUDEPATH += /usr/local/opt/icu4c/include
## -----------------------------------------------------------------
## Application
## -----------------------------------------------------------------
SOURCES += main.cpp
##HEADERS +=
## -----------------------------------------------------------------
## Resources & Images & Icon
## -----------------------------------------------------------------
@stefkeB
Copy link
Author

stefkeB commented Mar 20, 2019

A minimal example, to show parsing of an IFC file from Project down to individual entities and attributes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment