-
Notifications
You must be signed in to change notification settings - Fork 131
SCL adoption in IfcOpenShell
aothms edited this page Dec 11, 2011
·
2 revisions
IfcOpenShell is a free open source LGPL IFC implementation. IFC is a soon-to-be ISO standard based on STEP, used to exchange building and construction data. IfcOpenShell works with a quick and dirty IFC-parser, but is now in the process of migrating to SCL in order to provide more robust STEP support.
- Lazy loading. IFC files can easily grow over 100mb in file size, the multidisciplinary nature of IFC makes that often only a subset of the file is relevant for a specific context, therefore the feasibility of bringing lazy loading to SCL could be investigated.
- Type checking. For the way IfcOpenShell works it is necessary to query for instances taking the inheritance graph into account that is defined in the EXPRESS schema.
- It seems STEPfile::ReadData1() and STEPfile::ReadData2() are already separate functions that are used to parse the p21 file. Perhaps it'd work to skip STEPfile::ReadData2(), but instead storing the istream::tellg() file offset in the Application_instance class and calling STEPfile::ReadInstance() after calling istream::seekg() when the Application_instance is requested.
- It'd be nice if InstMgr::GetApplication_instance() could be extended to also return subtypes of the requested keyword. The way this works now in IfcOpenShell is that when an entity is parsed it is stored in a std::map for each of its supertypes.
To get a little acquainted with SCL I have written a small application that prints some information on walls (IfcWallStandardCase) in an Ifc2x3 file. The goal in mind was to somewhat emulate the steps needed to extract geometry.
Hopefully the program can be used to test the feasibility of implementing lazy loading in SCL.
extern void SchemaInit( class Registry & );
#include "scl_version_string.h"
#include <STEPfile.h>
#include <sdai.h>
#include <STEPattribute.h>
#include <ExpDict.h>
#include <Registry.h>
#include <errordesc.h>
#include <algorithm>
#include <string>
#include <unistd.h>
#include "../../../build/IFC2X3_TC1/SdaiIFC2X3.h"
int main( int argc, char * argv[] ) {
if ( argc != 2 ) exit(1);
Registry registry( SchemaInit );
InstMgr instance_list;
STEPfile sfile( registry, instance_list, "", false );
sfile.ReadExchangeFile( argv[1] );
sfile.Error().PrintContents(cout);
Severity readSev = sfile.Error().severity(); //otherwise, errors from reading will be wiped out by sfile.WriteExchangeFile()
// Keeps track of the last processed wall id
int search_index = 0;
// Loop over the IfcWallStandardCases in the file
while ( true ) {
SdaiIfcwallstandardcase* wall = (SdaiIfcwallstandardcase*)
instance_list.GetApplication_instance("IfcWallStandardCase",search_index);
if ( wall == ENTITY_NULL ) break;
cout << "Wall #" << wall->StepFileId() << " " << wall->globalid_() << endl;
// Descend all the way to the corresponding IfcRepresentationItems
SdaiIfcproductrepresentation* repr = wall->representation_();
EntityAggregate* reps = repr->representations_();
const int rep_count = reps->EntryCount();
if ( rep_count ) {
EntityNode* node = (EntityNode*) reps->GetHead();
// Loop over the representations
do {
SdaiIfcrepresentation* r = (SdaiIfcrepresentation*) node->node;
const std::string rid = r->representationidentifier_();
// Only process the Body representation
if ( rid == "'Body'" ) {
EntityAggregate* rep_items = r->items_();
const int item_count = rep_items->EntryCount();
// Loop over representation items
if ( item_count ) {
EntityNode* item_node = (EntityNode*) rep_items->GetHead();
do {
SdaiIfcrepresentationitem* i = (SdaiIfcrepresentationitem*) item_node->node;
// If the representation is a simple extrusion, print the height
if ( i->IsA( ifc2x3::e_ifcextrudedareasolid ) ) {
SdaiIfcextrudedareasolid* ex = (SdaiIfcextrudedareasolid*) i;
float depth = ex->depth_();
cout << "Height: " << depth << endl;
}
} while ( item_node = (EntityNode*) item_node->NextNode() );
}
}
} while ( node = (EntityNode*) node->NextNode() );
}
// judging by the function name I would expect this to work too,
// but it returns the StepFileId() instead
// search_index = instance_list.GetIndex(wall)+1;
MgrNode* mnode = instance_list.FindFileId( wall->StepFileId() );
search_index = instance_list.GetIndex( mnode ) + 1;
}
}
#include "../ifcparse/IfcParse.h"
using namespace Ifc2x3;
int main(int argc, char** argv) {
if ( argc != 2 ) {
std::cout << "usage: IfcParseExamples <filename.ifc>" << std::endl;
return 1;
}
// Redirect the output (both progress and log) to stdout
Ifc::SetOutput(&std::cout,&std::cout);
// Parse the IFC file provided in argv[1]
if ( ! Ifc::Init(argv[1]) ) {
std::cout << "Unable to parse .ifc file" << std::endl;
return 1;
}
IfcWallStandardCase::list walls = Ifc::EntitiesByType<IfcWallStandardCase>();
for ( IfcWallStandardCase::it it = walls->begin(); it != walls->end(); ++ it ) {
const IfcWallStandardCase::ptr wall = *it;
std::cout << "Wall #" << wall->entity->id() << " " << wall->GlobalId() << std::endl;
IfcProductRepresentation::ptr product_rep = wall->Representation();
IfcRepresentation::list reps = product_rep->Representations();
for ( IfcRepresentation::it it2 = reps->begin(); it2 != reps->end(); ++it2 ) {
const IfcRepresentation::ptr rep = *it2;
const std::string rid = rep->RepresentationIdentifier();
if ( rid == "Body" ) {
IfcRepresentationItem::list rep_items = rep->Items();
for ( IfcRepresentationItem::it it3 = rep_items->begin(); it3 != rep_items->end(); ++ it3 ) {
const IfcRepresentationItem::ptr rep_item = *it3;
if ( rep_item->is(IfcExtrudedAreaSolid::Class()) ) {
const IfcExtrudedAreaSolid::ptr ex =
(IfcExtrudedAreaSolid::ptr) rep_item;
const float depth = ex->Depth();
std::cout << "Height: " << depth << std::endl;
}
}
}
}
}
}