Process IfcRelAggregates and IfcRelContainedInSpatialStructure to enable IfcBlender to build a parenting graph

This commit is contained in:
Thomas Krijnen
2011-10-08 13:06:57 +00:00
parent 69ad96df25
commit 87b668959b
5 changed files with 223 additions and 49 deletions
+81 -18
View File
@@ -46,9 +46,18 @@ if "bpy" in locals():
import bpy
import mathutils
from bpy.props import StringProperty
from bpy.props import StringProperty, IntProperty, BoolProperty
from bpy_extras.io_utils import ImportHelper
bpy.types.Object.ifc_id = IntProperty(name="IFC Entity ID",
description="The STEP entity instance name")
bpy.types.Object.ifc_guid = StringProperty(name="IFC Entity GUID",
description="The IFC Globally Unique Identifier")
bpy.types.Object.ifc_name = StringProperty(name="IFC Entity Name",
description="The optional name attribute")
bpy.types.Object.ifc_type = StringProperty(name="IFC Entity Type",
description="The STEP Datatype keyword")
class ImportIFC(bpy.types.Operator, ImportHelper):
bl_idname = "import_scene.ifc"
@@ -57,46 +66,100 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
filename_ext = ".ifc"
filter_glob = StringProperty(default="*.ifc", options={'HIDDEN'})
use_names = BoolProperty(name="Use entity names",
description="Use entity names rather than GlobalIds for objects",
default=True)
process_relations = BoolProperty(name="Process relations",
description="Convert containment and aggregation relations to parenting",
default=True)
def execute(self, context):
from . import IfcImport
if not IfcImport.Init(self.filepath):
return {'FINISHED'}
ids = {}
id_to_object = {}
id_to_parent = {}
while True:
ob = IfcImport.Get()
if not ob.type in ['IfcSpace', 'IfcOpeningElement']:
if ob.type != 'IfcOpeningElement':
f = ob.mesh.faces
v = ob.mesh.verts
m = ob.matrix
t = ob.type[0:21]
if ob.mesh.id in ids:
me = ids[ob.mesh.id]
nm = ob.name if len(ob.name) and self.use_names else ob.guid
verts = [[v[i], v[i + 1], v[i + 2]] \
for i in range(0, len(v), 3)]
faces = [[f[i], f[i + 1], f[i + 2]] \
for i in range(0, len(f), 3)]
me = bpy.data.meshes.new('mesh%d' % ob.mesh.id)
me.from_pydata(verts, [], faces)
if t in bpy.data.materials:
mat = bpy.data.materials[t]
mat.use_fake_user = True
else:
verts = [[v[i],v[i+1],v[i+2]] for i in range(0,len(v),3)]
faces = [[f[i],f[i+1],f[i+2]] for i in range(0,len(f),3)]
me = bpy.data.meshes.new('mesh%d' % ob.mesh.id)
me.from_pydata(verts, [], faces)
if t in bpy.data.materials:
mat = bpy.data.materials[t]
mat.use_fake_user = True
else:
mat = bpy.data.materials.new(t)
me.materials.append(mat)
ids[ob.mesh.id] = me
bob = bpy.data.objects.new(ob.name, me)
mat = bpy.data.materials.new(t)
me.materials.append(mat)
bob = bpy.data.objects.new(nm, me)
bob.matrix_world = mathutils.Matrix(([m[0], m[1], m[2], 0],
[m[3], m[4], m[5], 0],
[m[6], m[7], m[8], 0],
[m[9], m[10], m[11], 1]))
bpy.context.scene.objects.link(bob)
#me.update()
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_name(name=bob.name)
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.normals_make_consistent()
bpy.ops.object.mode_set(mode='OBJECT')
bob.ifc_id, bob.ifc_guid, bob.ifc_name, bob.ifc_type = \
ob.id, ob.guid, ob.name, ob.type
bob.hide = ob.type == 'IfcSpace'
id_to_object[ob.id] = bob
if ob.parent_id > 0:
id_to_parent[ob.id] = ob.parent_id
if not IfcImport.Next():
break
while len(id_to_parent) and self.process_relations:
id, parent_id = id_to_parent.popitem()
if parent_id in id_to_object:
bob = id_to_object[parent_id]
else:
parent_ob = IfcImport.GetObject(parent_id)
if parent_ob.id == -1:
bob = None
else:
m = parent_ob.matrix
nm = parent_ob.name if len(parent_ob.name) and self.use_names \
else parent_ob.guid
bob = bpy.data.objects.new(nm, None)
bob.matrix_world = mathutils.Matrix(([m[0], m[1], m[2], 0],
[m[3], m[4], m[5], 0],
[m[6], m[7], m[8], 0],
[m[9], m[10], m[11], 1]))
bpy.context.scene.objects.link(bob)
bob.ifc_id = parent_ob.id
bob.ifc_guid = parent_ob.guid
bob.ifc_name = parent_ob.name
bob.ifc_type = parent_ob.type
if parent_ob.parent_id > 0:
id_to_parent[parent_id] = parent_ob.parent_id
id_to_object[parent_id] = bob
if bob:
ob = id_to_object[id]
ob.matrix_world = bob.matrix_world.inverted() * ob.matrix_world
ob.parent = bob
IfcImport.CleanUp()
return {'FINISHED'}
+106 -14
View File
@@ -104,15 +104,33 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, TopoDS_Shape s) {
}
}
IfcGeomObjects::IfcGeomObject::IfcGeomObject(int my_id, const std::string& n, const std::string& t, gp_Trsf trsf, IfcMesh* m) {
IfcGeomObjects::IfcObject::IfcObject(int my_id,
int p_id,
const std::string& n,
const std::string& t,
const std::string& g,
const gp_Trsf& trsf) {
// Convert the gp_Trsf into a 4x3 Matrix
for( int i = 1; i < 5; ++ i )
for ( int j = 1; j < 4; ++ j )
matrix.push_back((float)trsf.Value(j,i));
id = my_id;
parent_id = p_id;
name = n;
type = t;
guid = g;
}
IfcGeomObjects::IfcGeomObject::IfcGeomObject(int my_id,
int p_id,
const std::string& n,
const std::string& t,
const std::string& g,
const gp_Trsf& trsf,
IfcMesh* m) : IfcObject(my_id,p_id,n,t,g,trsf) {
mesh = m;
}
@@ -194,7 +212,9 @@ IfcGeomObjects::IfcGeomObject* _get() {
}
}
Ifc2x3::IfcProduct::ptr ifc_product = *inner;
const std::string name = ifc_product->hasName() ? ifc_product->Name() : ifc_product->GlobalId();
int parent_id = -1;
const std::string name = ifc_product->hasName() ? ifc_product->Name() : "";
const std::string guid = ifc_product->GlobalId();
gp_Trsf trsf;
try {
@@ -220,13 +240,37 @@ IfcGeomObjects::IfcGeomObject* _get() {
}
}
if ( ifc_product->is(Ifc2x3::Type::IfcElement ) ) {
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
Ifc2x3::IfcRelContainedInSpatialStructure::list parents = element->ContainedInStructure();
if ( parents->Size() ) {
Ifc2x3::IfcRelContainedInSpatialStructure::ptr parent = *parents->begin();
parent_id = parent->RelatingStructure()->entity->id();
}
}
if ( parent_id == -1 ) {
Ifc2x3::IfcRelDecomposes::list decomposes = ifc_product->IsDecomposedBy();
// This is a bug in IfcParse IsDecomposedBy() and Decomposes() are mixed
for ( Ifc2x3::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
Ifc2x3::IfcRelDecomposes::ptr decompose = *it;
Ifc2x3::IfcObjectDefinition* ifc_objectdef = decompose->RelatingObject();
if ( ifc_product == ifc_objectdef ) continue;
parent_id = ifc_objectdef->entity->id();
}
}
if ( (openings && openings->Size()) || use_world_coords ) {
if ( shape ) delete shape;
TopoDS_Shape temp_shape = shapes.Moved(gp_Trsf());
try {
if (openings && openings->Size()) IfcGeom::convert_openings(ifc_product,openings,temp_shape,trsf);
} catch( IfcParse::IfcException& e ) {Ifc::LogMessage("Warning",e.what()); }
catch(...) { Ifc::LogMessage("Error","Error processing openings for:",ifc_product->entity); }
if (openings && openings->Size()) {
IfcGeom::convert_openings(ifc_product,openings,temp_shape,trsf);
}
} catch( IfcParse::IfcException& e ) {
Ifc::LogMessage("Warning",e.what());
} catch(...) {
Ifc::LogMessage("Error","Error processing openings for:",ifc_product->entity);
}
if ( use_world_coords ) {
shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),temp_shape.Moved(trsf));
trsf = gp_Trsf();
@@ -237,12 +281,13 @@ IfcGeomObjects::IfcGeomObject* _get() {
shape = new IfcGeomObjects::IfcMesh(shaperep->entity->id(),shapes);
}
return new IfcGeomObjects::IfcGeomObject(ifc_product->entity->id(), name, Ifc2x3::Type::ToString(ifc_product->type()), trsf, shape);
return new IfcGeomObjects::IfcGeomObject(ifc_product->entity->id(), parent_id, name,
Ifc2x3::Type::ToString(ifc_product->type()), guid, trsf, shape);
}
}
extern bool IfcGeomObjects::Next() {
bool IfcGeomObjects::Next() {
if ( entities ) {
++inner;
}
@@ -250,20 +295,67 @@ extern bool IfcGeomObjects::Next() {
currentGeomObj = _get();
if ( ! currentGeomObj ) {
delete shape;
Ifc::Dispose();
IfcGeom::Cache::Purge();
return false;
} else {
return true;
}
}
extern const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
std::vector<IfcGeomObjects::IfcObject*> returned_objects;
bool IfcGeomObjects::CleanUp() {
Ifc::Dispose();
IfcGeom::Cache::Purge();
for ( std::vector<IfcGeomObjects::IfcObject*>::const_iterator it = returned_objects.begin();
it != returned_objects.end();
++ it ) {
delete *it;
}
return true;
}
const IfcGeomObjects::IfcObject* IfcGeomObjects::GetObject(int id) {
IfcObject* ifc_object = 0;
try {
const IfcEntity& ifc_entity = Ifc::EntityById(id);
if ( ifc_entity->is(Ifc2x3::Type::IfcProduct) ) {
Ifc2x3::IfcProduct::ptr ifc_product = reinterpret_pointer_cast<IfcUtil::IfcBaseClass,Ifc2x3::IfcProduct>(ifc_entity);
int parent_id = -1;
if ( ifc_product->is(Ifc2x3::Type::IfcElement ) ) {
Ifc2x3::IfcElement::ptr element = reinterpret_pointer_cast<Ifc2x3::IfcProduct,Ifc2x3::IfcElement>(ifc_product);
Ifc2x3::IfcRelContainedInSpatialStructure::list parents = element->ContainedInStructure();
if ( parents->Size() ) {
Ifc2x3::IfcRelContainedInSpatialStructure::ptr parent = *parents->begin();
parent_id = parent->RelatingStructure()->entity->id();
}
}
if ( parent_id == -1 ) {
Ifc2x3::IfcRelDecomposes::list decomposes = ifc_product->IsDecomposedBy();
// This is a bug in IfcParse IsDecomposedBy() and Decomposes() are mixed
for ( Ifc2x3::IfcRelDecomposes::it it = decomposes->begin(); it != decomposes->end(); ++ it ) {
Ifc2x3::IfcRelDecomposes::ptr decompose = *it;
Ifc2x3::IfcObjectDefinition* ifc_objectdef = decompose->RelatingObject();
if ( ifc_product == ifc_objectdef ) continue;
parent_id = ifc_objectdef->entity->id();
}
}
const std::string name = ifc_product->hasName() ? ifc_product->Name() : "";
gp_Trsf trsf;
try {
IfcGeom::convert(ifc_product->ObjectPlacement(),trsf);
} catch (...) {}
ifc_object = new IfcObject(ifc_product->entity->id(),parent_id,name,
Ifc2x3::Type::ToString(ifc_product->type()),ifc_product->GlobalId(),trsf);
}
} catch(...) {}
if ( !ifc_object ) ifc_object = new IfcObject(-1,-1,"","","",gp_Trsf());
returned_objects.push_back(ifc_object);
return ifc_object;
}
const IfcGeomObjects::IfcGeomObject* IfcGeomObjects::Get() {
return currentGeomObj;
}
extern bool IfcGeomObjects::Init(const char* fn, bool world_coords) {
bool IfcGeomObjects::Init(const char* fn, bool world_coords) {
return IfcGeomObjects::Init(fn, world_coords, 0, 0);
}
extern bool IfcGeomObjects::Init(const char* fn, bool world_coords, std::ostream* log1, std::ostream* log2) {
bool IfcGeomObjects::Init(const char* fn, bool world_coords, std::ostream* log1, std::ostream* log2) {
if ( log1 || log2 ) Ifc::SetOutput(log1,log2);
use_world_coords = world_coords;
if ( !Ifc::Init(fn) ) return false;
@@ -281,7 +373,7 @@ extern bool IfcGeomObjects::Init(const char* fn, bool world_coords, std::ostream
total = shapereps->Size();
return true;
}
extern bool IfcGeomObjects::Init(std::istream& f, int len, bool world_coords, std::ostream* log1, std::ostream* log2) {
bool IfcGeomObjects::Init(std::istream& f, int len, bool world_coords, std::ostream* log1, std::ostream* log2) {
if ( log1 || log2 ) Ifc::SetOutput(log1,log2);
use_world_coords = world_coords;
if ( !Ifc::Init(f, len) ) return false;
@@ -299,6 +391,6 @@ extern bool IfcGeomObjects::Init(std::istream& f, int len, bool world_coords, st
total = shapereps->Size();
return true;
}
extern int IfcGeomObjects::Progress() {
int IfcGeomObjects::Progress() {
return 100 * done / total;
}
+18 -9
View File
@@ -88,22 +88,31 @@ namespace IfcGeomObjects {
}
};
class IfcGeomObject {
class IfcObject {
public:
int id;
int parent_id;
std::string name;
std::string type;
std::string guid;
std::vector<float> matrix;
IfcMesh* mesh;
IfcGeomObject(int i, const std::string& n, const std::string& t, gp_Trsf trsf, IfcMesh* m);
IfcObject(int my_id, int p_id, const std::string& n, const std::string& t, const std::string& g, const gp_Trsf& trsf);
};
extern bool Init(const char* fn, bool world_coords = false);
extern bool Init(const char* fn, bool world_coords = false, std::ostream* log1= 0, std::ostream* log2= 0);
extern bool Init(std::istream& f, int len, bool world_coords = false, std::ostream* log1= 0, std::ostream* log2= 0);
extern const IfcGeomObject* Get();
extern bool Next();
extern int Progress();
class IfcGeomObject : public IfcObject {
public:
IfcMesh* mesh;
IfcGeomObject(int my_id, int p_id, const std::string& n, const std::string& t, const std::string& g, const gp_Trsf& trsf, IfcMesh* m);
};
bool Init(const char* fn, bool world_coords = false);
bool Init(const char* fn, bool world_coords = false, std::ostream* log1= 0, std::ostream* log2= 0);
bool Init(std::istream& f, int len, bool world_coords = false, std::ostream* log1= 0, std::ostream* log2= 0);
bool CleanUp();
const IfcGeomObject* Get();
bool Next();
int Progress();
const IfcObject* GetObject(int id);
}
+5 -3
View File
@@ -27,7 +27,7 @@
#include "../ifcmax/IfcMax.h"
#include "../ifcmax/MaxMaterials.h"
#include "../ifcparse/IfcGeomObjects.h"
#include "../ifcgeom/IfcGeomObjects.h"
int controlsInit = false;
@@ -109,7 +109,7 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
itfc->ProgressStart("Importing file...", TRUE, fn, NULL);
if ( ! IfcGeomObjects::Init((char*)name) ) return false;
if ( ! IfcGeomObjects::Init((char*)name,false,0,0) ) return false;
std::map<int, TriObject*> dict;
MtlBaseLib* mats = itfc->GetSceneMtls();
@@ -158,7 +158,7 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
ImpNode* node = impitfc->CreateNode();
node->Reference(tri);
node->SetName(o->name.c_str());
node->SetName(o->guid.c_str());
node->GetINode()->SetMtl(m);
node->SetTransform(0,Matrix3 ( Point3(o->matrix[0],o->matrix[1],o->matrix[2]),Point3(o->matrix[3],o->matrix[4],o->matrix[5]),
Point3(o->matrix[6],o->matrix[7],o->matrix[8]),Point3(o->matrix[9],o->matrix[10],o->matrix[11]) ));
@@ -168,6 +168,8 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
} while ( IfcGeomObjects::Next() );
IfcGeomObjects::CleanUp();
itfc->ProgressEnd();
return true;
+13 -5
View File
@@ -26,17 +26,25 @@ namespace IfcGeomObjects {
std::vector<int> edges;
};
class IfcGeomObject {
class IfcObject {
public:
int id;
int parent_id;
std::string name;
std::string type;
std::string guid;
std::vector<float> matrix;
};
class IfcGeomObject : public IfcObject {
public:
IfcMesh* mesh;
};
extern bool Next();
extern const IfcGeomObject* Get();
extern bool Init(const char* fn, bool world_coords = false);
extern int Progress();
bool Next();
const IfcGeomObject* Get();
bool Init(const char* fn, bool world_coords = false);
int Progress();
const IfcObject* GetObject(int id);
bool CleanUp();
};