mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 01:41:57 +00:00
IfcBlender: updated to Blender 2.58 (Patch by Yorik van Havre)
IfcParse: lazy loading of entities IfcGeom: caching of binary entities
This commit is contained in:
@@ -23,11 +23,10 @@ bl_info = {
|
||||
"description": "Import files in the "\
|
||||
"Industry Foundation Classes (.ifc) file format",
|
||||
"author": "Thomas Krijnen, IfcOpenShell",
|
||||
"blender": (2, 5, 6),
|
||||
"api": 32738,
|
||||
"blender": (2, 5, 8),
|
||||
"api": 37702,
|
||||
"location": "File > Import",
|
||||
"warning": "This addon requires several "\
|
||||
"Open CASCADE libraries to be installed",
|
||||
"warning": "",
|
||||
"wiki_url": "http://sourceforge.net/apps/"\
|
||||
"mediawiki/ifcopenshell/index.php",
|
||||
"tracker_url": "http://sourceforge.net/tracker/?group_id=543113",
|
||||
@@ -37,8 +36,7 @@ bl_info = {
|
||||
import bpy
|
||||
import mathutils
|
||||
from bpy.props import *
|
||||
from io_utils import ImportHelper
|
||||
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
|
||||
class ImportIFC(bpy.types.Operator, ImportHelper):
|
||||
bl_idname = "import_scene.ifc"
|
||||
@@ -54,7 +52,7 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
|
||||
ids = {}
|
||||
while True:
|
||||
ob = IfcImport.Get()
|
||||
if not ob.type in ['IFCSPACE', 'IFCOPENINGELEMENT']:
|
||||
if not ob.type in ['IfcSpace', 'IfcOpeningElement']:
|
||||
f = ob.mesh.faces
|
||||
v = ob.mesh.verts
|
||||
m = ob.matrix
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <time.h>
|
||||
|
||||
#include "../ifcparse/IfcGeomObjects.h"
|
||||
#include "../ifcobj/ObjMaterials.h"
|
||||
@@ -56,12 +57,15 @@ int main ( int argc, char** argv ) {
|
||||
fObj << "mtllib " << fnMtl << std::endl;
|
||||
std::set<std::string> materials;
|
||||
|
||||
time_t start,end;
|
||||
time(&start);
|
||||
|
||||
// The functions IfcGeomObjects::Get() and IfcGeomObjects::Next() wrap an iterator of all geometrical entities in the Ifc file.
|
||||
// IfcGeomObjects::Get() returns an IfcGeomObjects::IfcGeomObject (see IfcObjects.h for definition)
|
||||
// IfcGeomObjects::Next() is used to poll whether more geometrical entities are available
|
||||
do {
|
||||
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
|
||||
if ( o->type == "IFCSPACE" || o->type == "IFCOPENINGELEMENT" ) continue;
|
||||
if ( o->type == "IfcSpace" || o->type == "IfcOpeningElement" ) continue;
|
||||
fObj << "o " << o->name << std::endl;
|
||||
fObj << "usemtl " << o->type << std::endl;
|
||||
materials.insert(o->type);
|
||||
@@ -85,4 +89,8 @@ int main ( int argc, char** argv ) {
|
||||
for( std::set<std::string>::iterator it = materials.begin(); it != materials.end(); ++ it ) {
|
||||
fMtl << GetMaterial(*it);
|
||||
}
|
||||
|
||||
time(&end);
|
||||
int dif = (int) difftime (end,start);
|
||||
printf ("Conversion took %d seconds\n", dif );
|
||||
}
|
||||
|
||||
@@ -50,14 +50,15 @@ public:
|
||||
};
|
||||
|
||||
ObjMaterial GetMaterial(const std::string& s) {
|
||||
if ( s == "IFCSITE" ) { return ObjMaterial("IFCSITE",0.75f,0.8f,0.65f); }
|
||||
if ( s == "IFCSLAB" ) { return ObjMaterial("IFCSLAB",0.4f,0.4f,0.4f); }
|
||||
if ( s == "IFCWALLSTANDARDCASE" ) { return ObjMaterial("IFCWALLSTANDARDCASE",0.9f,0.9f,0.9f); }
|
||||
if ( s == "IFCWALL" ) { return ObjMaterial("IFCWALL",0.9f,0.9f,0.9f); }
|
||||
if ( s == "IFCWINDOW" ) { return ObjMaterial("IFCWINDOW",0.75f,0.8f,0.75f,1.0f,1.0f,1.0f,0.0f,0.0f,0.0f,500.0f,0.3f); }
|
||||
if ( s == "IFCDOOR" ) { return ObjMaterial("IFCDOOR",0.55f,0.3f,0.15f); }
|
||||
if ( s == "IFCBEAM" ) { return ObjMaterial("IFCBEAM",0.75f,0.7f,0.7f); }
|
||||
if ( s == "IFCRAILING" ) { return ObjMaterial("IFCRAILING",0.75f,0.7f,0.7f); }
|
||||
if ( s == "IFCMEMBER" ) { return ObjMaterial("IFCRAILING",0.75f,0.7f,0.7f); }
|
||||
if ( s == "IfcSite" ) { return ObjMaterial("IfcSite",0.75f,0.8f,0.65f); }
|
||||
if ( s == "IfcSlab" ) { return ObjMaterial("IfcSlab",0.4f,0.4f,0.4f); }
|
||||
if ( s == "IfcWallStandardCase" ) { return ObjMaterial("IfcWallStandardCase",0.9f,0.9f,0.9f); }
|
||||
if ( s == "IfcWall" ) { return ObjMaterial("IfcWall",0.9f,0.9f,0.9f); }
|
||||
if ( s == "IfcWindow" ) { return ObjMaterial("IfcWindow",0.75f,0.8f,0.75f,1.0f,1.0f,1.0f,0.0f,0.0f,0.0f,500.0f,0.3f); }
|
||||
if ( s == "IfcDoor" ) { return ObjMaterial("IfcDoor",0.55f,0.3f,0.15f); }
|
||||
if ( s == "IfcBeam" ) { return ObjMaterial("IfcBeam",0.75f,0.7f,0.7f); }
|
||||
if ( s == "IfcRailing" ) { return ObjMaterial("IfcRailing",0.65f,0.6f,0.6f); }
|
||||
if ( s == "IfcMember" ) { return ObjMaterial("IfcMember",0.65f,0.6f,0.6f); }
|
||||
if ( s == "IfcPlate" ) { return ObjMaterial("IfcPlate",0.8f,0.8f,0.8f); }
|
||||
return ObjMaterial(s);
|
||||
}
|
||||
@@ -38,5 +38,13 @@ std::string IfcSchema::Enum::ToString(IfcTypes t) {
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_PARSE_ENUM_STR
|
||||
|
||||
return "";
|
||||
return "IfcUnknown";
|
||||
}
|
||||
|
||||
bool IfcSchema::Enum::ShouldRender(IfcTypes t) {
|
||||
if ( t == IfcUnknown ) return false;
|
||||
#define IFC_PARSE_RENDER
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_PARSE_RENDER
|
||||
else return false;
|
||||
}
|
||||
@@ -42,6 +42,7 @@ namespace IfcSchema {
|
||||
};
|
||||
IfcTypes FromString(const std::string& a);
|
||||
std::string ToString(IfcTypes t);
|
||||
bool ShouldRender(IfcTypes t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+92
-41
@@ -31,8 +31,10 @@
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <gp_Mat.hxx>
|
||||
@@ -76,6 +78,17 @@
|
||||
|
||||
#include <TopLoc_Location.hxx>
|
||||
|
||||
namespace IfcGeom {
|
||||
namespace Cache {
|
||||
#define IFC_GEOM_CACHE
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_GEOM_CACHE
|
||||
}
|
||||
}
|
||||
#define IN_CACHE(T,E,t,e) std::map<int,t *>::const_iterator it = Cache::T.find(E->id);\
|
||||
if ( it != Cache::T.end() ) { e = *(it->second); return true; }
|
||||
#define CACHE(T,E,e) Cache::T[E->id] = e;
|
||||
|
||||
bool IfcGeom::convert(IfcSchema::ExtrudedAreaSolid* IfcExtrudedAreaSolid, TopoDS_Shape& shape) {
|
||||
TopoDS_Face face;
|
||||
if ( ! IfcGeom::convert_face(IfcExtrudedAreaSolid->Profile(),face) ) return false;
|
||||
@@ -83,12 +96,10 @@ bool IfcGeom::convert(IfcSchema::ExtrudedAreaSolid* IfcExtrudedAreaSolid, TopoDS
|
||||
gp_Trsf trsf;
|
||||
convert((IfcSchema::Axis2Placement3D*) IfcExtrudedAreaSolid->Placement().get(),trsf);
|
||||
|
||||
gp_Vec dir3;
|
||||
convert((IfcSchema::Direction*) IfcExtrudedAreaSolid->Dir().get(),dir3);
|
||||
|
||||
gp_Vec extrude = dir3.Scaled(height);
|
||||
gp_Dir dir;
|
||||
convert((IfcSchema::Direction*) IfcExtrudedAreaSolid->Dir().get(),dir);
|
||||
|
||||
shape = BRepPrimAPI_MakePrism(face,extrude);
|
||||
shape = BRepPrimAPI_MakePrism(face,height*dir);
|
||||
shape.Move(trsf);
|
||||
return ! shape.IsNull();
|
||||
}
|
||||
@@ -100,13 +111,15 @@ bool IfcGeom::convert(IfcSchema::FaceBasedSurfaceModel* IfcFaceBasedSurfaceModel
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::HalfSpaceSolid* IfcHalfSpaceSolid, TopoDS_Shape& shape) {
|
||||
IfcEntity surf = IfcHalfSpaceSolid->Surface();
|
||||
if ( surf->dt != IfcSchema::Enum::IfcPlane ) return false;
|
||||
if ( surf->type != IfcSchema::Enum::IfcPlane ) return false;
|
||||
IfcSchema::Plane* IfcPlane = (IfcSchema::Plane*)surf.get();
|
||||
gp_Pln pln;
|
||||
IfcGeom::convert(IfcPlane,pln);
|
||||
gp_Pnt pnt = pln.Location();
|
||||
if ( !IfcHalfSpaceSolid->Flag() != (IfcHalfSpaceSolid->dt == IfcSchema::Enum::IfcPolygonalBoundedHalfSpace) ) pnt.Translate(pln.Axis().Direction());
|
||||
else pnt.Translate(-pln.Axis().Direction());
|
||||
bool reverse = IfcHalfSpaceSolid->Flag();
|
||||
if ( IfcHalfSpaceSolid->type == IfcSchema::Enum::IfcPolygonalBoundedHalfSpace ) reverse = !reverse;
|
||||
if ( reverse ) pnt.Translate(-pln.Axis().Direction());
|
||||
else pnt.Translate(pln.Axis().Direction());
|
||||
shape = BRepPrimAPI_MakeHalfSpace(BRepBuilderAPI_MakeFace(pln),pnt).Solid();
|
||||
return true;
|
||||
}
|
||||
@@ -119,8 +132,8 @@ bool IfcGeom::convert(IfcSchema::PolygonalBoundedHalfSpace* IfcPolygonalBoundedH
|
||||
convert((IfcSchema::Axis2Placement3D*) IfcPolygonalBoundedHalfSpace->Placement().get(),trsf);
|
||||
TopoDS_Shape extrusion = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(wire),gp_Vec(0,0,20000.0));
|
||||
gp_Trsf down; down.SetTranslation(gp_Vec(0,0,-10000.0));
|
||||
extrusion.Move(down);
|
||||
extrusion.Move(trsf);
|
||||
extrusion.Move(down);
|
||||
shape = BRepAlgoAPI_Cut(extrusion,halfspace);
|
||||
return true;
|
||||
}
|
||||
@@ -189,7 +202,7 @@ bool IfcGeom::convert(IfcSchema::Face* IfcFace, TopoDS_Face& face) {
|
||||
BRepBuilderAPI_MakeFace mf(wire, false);
|
||||
BRepBuilderAPI_FaceError er = mf.Error();
|
||||
if ( er == BRepBuilderAPI_NotPlanar ) {
|
||||
std::cout << "[Notice] Trying to fix non-planar face:" << std::endl << IfcFace->toString() << std::endl;
|
||||
//std::cout << "[Notice] Trying to fix non-planar face:" << std::endl << IfcFace->toString() << std::endl;
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, 0.01, TopAbs_WIRE);
|
||||
mf = BRepBuilderAPI_MakeFace(wire, false);
|
||||
@@ -197,7 +210,7 @@ bool IfcGeom::convert(IfcSchema::Face* IfcFace, TopoDS_Face& face) {
|
||||
}
|
||||
if ( er != BRepBuilderAPI_FaceDone ) return false;
|
||||
|
||||
if ( bounds->size == 1 ) {
|
||||
if ( bounds->Size() == 1 ) {
|
||||
face = mf.Face();
|
||||
return true;
|
||||
}
|
||||
@@ -243,23 +256,32 @@ bool IfcGeom::convert(IfcSchema::CircleHollowProfileDef* IfcCircleHollowProfileD
|
||||
face = TopoDS::Face(sfs.Shape());
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::CartesianPoint* IfcCartesianPoint, gp_Pnt& p) {
|
||||
if ( IfcCartesianPoint->arg(0)->count() == 3 )
|
||||
p = gp_Pnt(IfcCartesianPoint->X() * Ifc::LengthUnit,IfcCartesianPoint->Y() * Ifc::LengthUnit,IfcCartesianPoint->Z() * Ifc::LengthUnit);
|
||||
else
|
||||
p = gp_Pnt(IfcCartesianPoint->X() * Ifc::LengthUnit,IfcCartesianPoint->Y() * Ifc::LengthUnit,0.0f);
|
||||
bool IfcGeom::convert(IfcSchema::CartesianPoint* IfcCartesianPoint, gp_Pnt& point) {
|
||||
IN_CACHE(CartesianPoint,IfcCartesianPoint,gp_Pnt,point)
|
||||
gp_Pnt* p = new gp_Pnt(
|
||||
IfcCartesianPoint->X() * Ifc::LengthUnit,
|
||||
IfcCartesianPoint->Y() * Ifc::LengthUnit,
|
||||
((*IfcCartesianPoint)[0]->Size() == 3) ? (IfcCartesianPoint->Z() * Ifc::LengthUnit) : 0.0f
|
||||
);
|
||||
CACHE(CartesianPoint,IfcCartesianPoint,p)
|
||||
point = *p;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::Direction* IfcDirection, gp_Vec& v) {
|
||||
if ( IfcDirection->arg(0)->count() == 3 )
|
||||
v = gp_Vec(IfcDirection->X(),IfcDirection->Y(),IfcDirection->Z());
|
||||
else
|
||||
v = gp_Vec(IfcDirection->X(),IfcDirection->Y(),0.0f);
|
||||
bool IfcGeom::convert(IfcSchema::Direction* IfcDirection, gp_Dir& dir) {
|
||||
IN_CACHE(Direction,IfcDirection,gp_Dir,dir);
|
||||
gp_Dir* d = new gp_Dir(
|
||||
IfcDirection->X(),
|
||||
IfcDirection->Y(),
|
||||
((*IfcDirection)[0]->Size() == 3) ? IfcDirection->Z() : 0.0f
|
||||
);
|
||||
CACHE(Direction,IfcDirection,d);
|
||||
dir = *d;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::Vector* IfcVector, gp_Vec& v) {
|
||||
IfcGeom::convert((IfcSchema::Direction*)IfcVector->Orientation().get(),v);
|
||||
v.Scale(IfcVector->Magnitude());
|
||||
gp_Dir d;
|
||||
IfcGeom::convert((IfcSchema::Direction*)IfcVector->Orientation().get(),d);
|
||||
v = IfcVector->Magnitude() * Ifc::LengthUnit * d;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::ArbitraryClosedProfileDef* IfcArbitraryClosedProfileDef, TopoDS_Wire& wire) {
|
||||
@@ -434,7 +456,7 @@ bool IfcGeom::convert(IfcSchema::CompositeCurve* IfcCompositeCurve, class TopoDS
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::TrimmedCurve* IfcTrimmedCurve, class TopoDS_Wire& wire) {
|
||||
IfcEntity basis = IfcTrimmedCurve->BasisCurve();
|
||||
bool isConic = basis->dt == IfcSchema::Enum::IfcCircle || basis->dt == IfcSchema::Enum::IfcEllipse;
|
||||
bool isConic = basis->type == IfcSchema::Enum::IfcCircle || basis->type == IfcSchema::Enum::IfcEllipse;
|
||||
float parameterFactor = isConic ? Ifc::PlaneAngleUnit : Ifc::LengthUnit;
|
||||
Handle(Geom_Curve) curve;
|
||||
if ( ! IfcGeom::convert_curve(basis,curve) ) return false;
|
||||
@@ -448,23 +470,23 @@ bool IfcGeom::convert(IfcSchema::TrimmedCurve* IfcTrimmedCurve, class TopoDS_Wir
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
for ( IfcParse::Entities::it it = trims1->begin(); it != trims1->end(); it ++ ) {
|
||||
const IfcEntity i = *it;
|
||||
if ( i->dt == IfcSchema::Enum::IfcCartesianPoint && cartesian ) {
|
||||
if ( i->type == IfcSchema::Enum::IfcCartesianPoint && cartesian ) {
|
||||
IfcGeom::convert( (IfcSchema::CartesianPoint*) i.get(), pnt1 );
|
||||
trimmed1 = true;
|
||||
} else if ( i->dt == IfcSchema::Enum::IfcParameterValue ) {
|
||||
} else if ( i->type == IfcSchema::Enum::IfcParameterValue ) {
|
||||
flt1 = ((IfcSchema::ParameterValue*)i.get())->Value() * parameterFactor;
|
||||
trimmed1 = true;
|
||||
}
|
||||
}
|
||||
for ( IfcParse::Entities::it it = trims2->begin(); it != trims2->end(); it ++ ) {
|
||||
const IfcEntity i = *it;
|
||||
if ( i->dt == IfcSchema::Enum::IfcCartesianPoint && cartesian && trimmed1 ) {
|
||||
if ( i->type == IfcSchema::Enum::IfcCartesianPoint && cartesian && trimmed1 ) {
|
||||
gp_Pnt pnt2;
|
||||
IfcGeom::convert( (IfcSchema::CartesianPoint*) i.get(), pnt2 );
|
||||
BRepBuilderAPI_MakeEdge e (curve,pnt1,pnt2);
|
||||
w.Add(e.Edge());
|
||||
trimmed2 = true;
|
||||
} else if ( i->dt == IfcSchema::Enum::IfcParameterValue && trimmed1 ) {
|
||||
} else if ( i->type == IfcSchema::Enum::IfcParameterValue && trimmed1 ) {
|
||||
float flt2 = ((IfcSchema::ParameterValue*)i.get())->Value() * parameterFactor;
|
||||
BRepBuilderAPI_MakeEdge e (curve,flt1,flt2);
|
||||
w.Add(e.Edge());
|
||||
@@ -507,18 +529,27 @@ bool IfcGeom::convert(IfcSchema::Polyline* IfcPolyline, TopoDS_Wire& result) {
|
||||
IfcEntities points = IfcPolyline->Points();
|
||||
|
||||
BRepBuilderAPI_MakeWire w;
|
||||
int count = 0;
|
||||
for( IfcParse::Entities::it it = points->begin(); it != points->end(); ++ it ) {
|
||||
gp_Pnt P1;gp_Pnt P2;
|
||||
IfcGeom::convert((IfcSchema::CartesianPoint*)(*it).get(),P1);
|
||||
IfcParse::Entities::it next = it + 1;
|
||||
if ( next == points->end() ) {
|
||||
if ( IfcPolyline->dt == IfcSchema::Enum::IfcPolyloop ) next = points->begin();
|
||||
if ( IfcPolyline->type == IfcSchema::Enum::IfcPolyloop ) next = points->begin();
|
||||
else break;
|
||||
}
|
||||
IfcGeom::convert((IfcSchema::CartesianPoint*)(*next).get(),P2);
|
||||
if ( P1.X() == P2.X() && P1.Y() == P2.Y() && P1.Z() == P2.Z() ) continue;
|
||||
//std::cout << P1.X() << "," << P1.Y() << "," << P1.Z() << " -> " << P2.X() << "," <<P2.Y() << "," << P2.Z() << std::endl;
|
||||
TopoDS_Edge e = BRepBuilderAPI_MakeEdge(P1,P2);
|
||||
w.Add(e);
|
||||
count ++;
|
||||
}
|
||||
|
||||
//std::cout << std::endl;
|
||||
if ( (count < 3) && IfcPolyline->type == IfcSchema::Enum::IfcPolyloop ) {
|
||||
std::cout << "[Notice] Skipping loop with " << count << " edges:" << std::endl << IfcPolyline->toString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = w.Wire();
|
||||
@@ -528,25 +559,29 @@ bool IfcGeom::convert(IfcSchema::Polyloop* IfcPolyloop, TopoDS_Wire& result) {
|
||||
return IfcGeom::convert((IfcSchema::Polyline*)IfcPolyloop,result);
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::Axis2Placement3D* IfcAxis2Placement3D, gp_Trsf& trsf) {
|
||||
gp_Pnt o;gp_Vec axis = gp_Vec(0,0,1);gp_Vec refDirection; bool hasRef = false;
|
||||
IN_CACHE(Axis2Placement3D,IfcAxis2Placement3D,gp_Trsf,trsf);
|
||||
|
||||
gp_Trsf* t = new gp_Trsf();
|
||||
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection; bool hasRef = false;
|
||||
IfcGeom::convert((IfcSchema::CartesianPoint*) IfcAxis2Placement3D->Origin().get(),o);
|
||||
try {
|
||||
IfcGeom::convert((IfcSchema::Direction*) IfcAxis2Placement3D->Axis().get(),axis);
|
||||
IfcGeom::convert((IfcSchema::Direction*) IfcAxis2Placement3D->RefDirection().get(),refDirection);
|
||||
hasRef = true;
|
||||
} catch( IfcParse::IfcException& ) {}
|
||||
|
||||
gp_Ax3 ax3;
|
||||
if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection);
|
||||
else ax3 = gp_Ax3(o,axis);
|
||||
t->SetTransformation(ax3, gp_Ax3(gp_Pnt(),gp_Dir(0,0,1),gp_Dir(1,0,0)));
|
||||
|
||||
trsf.SetTransformation(ax3, gp_Ax3(gp_Pnt(),gp_Dir(0,0,1),gp_Dir(1,0,0)));
|
||||
CACHE(Axis2Placement3D,IfcAxis2Placement3D,t);
|
||||
trsf = *t;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::Plane* IfcPlane, gp_Pln& plane) {
|
||||
IN_CACHE(Plane,IfcPlane,gp_Pln,plane)
|
||||
IfcSchema::Axis2Placement3D* IfcAxis2Placement3D = (IfcSchema::Axis2Placement3D*) IfcPlane->Placement().get();
|
||||
gp_Pnt o;gp_Vec axis = gp_Vec(0,0,1);gp_Vec refDirection; bool hasRef = false;
|
||||
gp_Pnt o;gp_Dir axis = gp_Dir(0,0,1);gp_Dir refDirection; bool hasRef = false;
|
||||
|
||||
IfcGeom::convert((IfcSchema::CartesianPoint*) IfcAxis2Placement3D->Origin().get(),o);
|
||||
try {
|
||||
@@ -559,30 +594,41 @@ bool IfcGeom::convert(IfcSchema::Plane* IfcPlane, gp_Pln& plane) {
|
||||
if ( hasRef ) ax3 = gp_Ax3(o,axis,refDirection);
|
||||
else ax3 = gp_Ax3(o,axis);
|
||||
|
||||
plane = gp_Pln(ax3);
|
||||
gp_Pln* ppln = new gp_Pln(ax3);
|
||||
CACHE(Plane,IfcPlane,ppln);
|
||||
plane = *ppln;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::Axis2Placement2D* IfcAxis2Placement2D, gp_Trsf2d& trsf) {
|
||||
gp_Pnt P; gp_Vec V (1,0,0);
|
||||
IN_CACHE(Axis2Placement2D,IfcAxis2Placement2D,gp_Trsf2d,trsf)
|
||||
gp_Pnt P; gp_Dir V (1,0,0);
|
||||
|
||||
gp_Trsf2d* ptrsf = new gp_Trsf2d();
|
||||
IfcGeom::convert((IfcSchema::CartesianPoint*) IfcAxis2Placement2D->Origin().get(),P);
|
||||
try {
|
||||
IfcGeom::convert((IfcSchema::Direction*) IfcAxis2Placement2D->Axis().get(),V);
|
||||
} catch( IfcParse::IfcException& ) {}
|
||||
|
||||
gp_Ax2d axis(gp_Pnt2d(P.X(),P.Y()),gp_Vec2d(V.X(),V.Y()));
|
||||
trsf.SetTransformation(axis,gp_Ax2d());
|
||||
gp_Ax2d axis(gp_Pnt2d(P.X(),P.Y()),gp_Dir2d(V.X(),V.Y()));
|
||||
ptrsf->SetTransformation(axis,gp_Ax2d());
|
||||
|
||||
CACHE(Axis2Placement2D,IfcAxis2Placement2D,ptrsf);
|
||||
trsf = *ptrsf;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert(IfcSchema::LocalPlacement* IfcLocalPlacement, gp_Trsf& trsf) {
|
||||
IN_CACHE(LocalPlacement,IfcLocalPlacement,gp_Trsf,trsf)
|
||||
gp_Trsf* ptrsf = new gp_Trsf();
|
||||
while (1) {
|
||||
gp_Trsf trsf2;
|
||||
IfcGeom::convert((IfcSchema::Axis2Placement3D*) IfcLocalPlacement->Placement().get(),trsf2);
|
||||
trsf.PreMultiply(trsf2);
|
||||
ptrsf->PreMultiply(trsf2);
|
||||
try {
|
||||
IfcLocalPlacement = (IfcSchema::LocalPlacement*) IfcLocalPlacement->Parent().get();
|
||||
} catch ( IfcParse::IfcException ) { break; }
|
||||
}
|
||||
CACHE(LocalPlacement,IfcLocalPlacement,ptrsf);
|
||||
trsf = *ptrsf;
|
||||
return true;
|
||||
}
|
||||
bool IfcGeom::convert_openings(const IfcSchema::BuildingElement* IfcBuildingElement,
|
||||
@@ -592,7 +638,7 @@ bool IfcGeom::convert_openings(const IfcSchema::BuildingElement* IfcBuildingElem
|
||||
IfcSchema::BuildingElement* IfcOpeningElement = (IfcSchema::BuildingElement*) IfcRelVoidsElement->Opening().get();
|
||||
gp_Trsf trsf;
|
||||
IfcGeom::convert((IfcSchema::LocalPlacement*) IfcOpeningElement->Placement().get(),trsf);
|
||||
gp_Trsf trsf3 = trsf2.Inverted();
|
||||
trsf.PreMultiply(trsf2.Inverted());
|
||||
IfcSchema::ProductDefinitionShape* IfcProductDefinitionShape = (IfcSchema::ProductDefinitionShape*) IfcOpeningElement->Shape().get();
|
||||
IfcEntities IfcShapeReps = IfcProductDefinitionShape->ShapeReps();
|
||||
for ( IfcParse::Entities::it shaperep = IfcShapeReps->begin(); shaperep != IfcShapeReps->end(); ++shaperep ) {
|
||||
@@ -602,7 +648,6 @@ bool IfcGeom::convert_openings(const IfcSchema::BuildingElement* IfcBuildingElem
|
||||
TopoDS_Shape s;
|
||||
if ( ! IfcGeom::convert_shape(*shape,s)) continue;
|
||||
s.Move(trsf);
|
||||
s.Move(trsf3);
|
||||
result = BRepAlgoAPI_Cut(result,s);
|
||||
}
|
||||
}
|
||||
@@ -613,7 +658,7 @@ bool IfcGeom::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
|
||||
BRepBuilderAPI_MakeFace mf(wire, false);
|
||||
BRepBuilderAPI_FaceError er = mf.Error();
|
||||
if ( er == BRepBuilderAPI_NotPlanar ) {
|
||||
std::cout << "[Notice] Trying to fix non-planar face" << std::endl;
|
||||
//std::cout << "[Notice] Trying to fix non-planar face" << std::endl;
|
||||
ShapeFix_ShapeTolerance FTol;
|
||||
FTol.SetTolerance(wire, 0.01, TopAbs_WIRE);
|
||||
mf = BRepBuilderAPI_MakeFace(wire, false);
|
||||
@@ -651,4 +696,10 @@ bool IfcGeom::profile_helper(int numVerts, float* verts, int numFillets, int* fi
|
||||
|
||||
delete[] vertices;
|
||||
return true;
|
||||
}
|
||||
void IfcGeom::Cache::Purge() {
|
||||
#define IFC_GEOM_CACHE_PURGE
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_GEOM_CACHE_PURGE
|
||||
PurgeShapeCache();
|
||||
}
|
||||
@@ -40,17 +40,15 @@
|
||||
|
||||
// Welds vertices that belong to different faces
|
||||
int IfcGeomObjects::IfcMesh::addvert(gp_Pnt p) {
|
||||
int i = 0; const float X = (float)p.X();const float Y = (float)p.Y();const float Z = (float)p.Z();
|
||||
for ( std::vector<float>::const_iterator it = verts.begin(); it != verts.end(); ) {
|
||||
const float x = *it; ++it;
|
||||
const float y = *it; ++it;
|
||||
const float z = *it; ++it;
|
||||
if ( X == x && Y == y && Z == z ) return i;
|
||||
++i;
|
||||
}
|
||||
const float X = (float)p.X();const float Y = (float)p.Y();const float Z = (float)p.Z();
|
||||
const VertKey key = VertKey(X,std::pair<float,float>(Y,Z));
|
||||
VertKeyMap::const_iterator it = welds.find(key);
|
||||
if ( it != welds.end() ) return it->second;
|
||||
verts.push_back(X);
|
||||
verts.push_back(Y);
|
||||
verts.push_back(Z);
|
||||
int i = welds.size();
|
||||
welds[key] = i;
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -159,7 +157,8 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
}
|
||||
shaperep = *outer;
|
||||
if ( ! entities ) {
|
||||
if ( shaperep->arg(1)->s() != "Body" ) {
|
||||
const std::string arg1 = *(*shaperep)[1];
|
||||
if ( arg1 != "Body" ) {
|
||||
_nextShape();
|
||||
continue;
|
||||
}
|
||||
@@ -168,12 +167,12 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
#endif
|
||||
// Find the IfcBuildingElements that refer to the current IfcShapeRepresentation
|
||||
entities = shaperep->parents(IfcSchema::Enum::IfcProductDefinitionShape)->parents();
|
||||
entities->pushs(shaperep->parents(IfcSchema::Enum::IfcProductRepresentation)->parents()); // 2x2 compatibility
|
||||
entities->pushs(shaperep->parents(IfcSchema::Enum::IfcRepresentationMap)->parents(IfcSchema::Enum::IfcMappedItem)
|
||||
entities->push(shaperep->parents(IfcSchema::Enum::IfcProductRepresentation)->parents()); // 2x2 compatibility
|
||||
entities->push(shaperep->parents(IfcSchema::Enum::IfcRepresentationMap)->parents(IfcSchema::Enum::IfcMappedItem)
|
||||
->parents(IfcSchema::Enum::IfcShapeRepresentation,1,"Body")->parents(IfcSchema::Enum::IfcProductDefinitionShape)->parents());
|
||||
entities->pushs(shaperep->parents(IfcSchema::Enum::IfcRepresentationMap)->parents(IfcSchema::Enum::IfcMappedItem)
|
||||
entities->push(shaperep->parents(IfcSchema::Enum::IfcRepresentationMap)->parents(IfcSchema::Enum::IfcMappedItem)
|
||||
->parents(IfcSchema::Enum::IfcShapeRepresentation,1,"Body")->parents(IfcSchema::Enum::IfcProductRepresentation)->parents());
|
||||
if ( ! entities->size ) {
|
||||
if ( ! entities->Size() ) {
|
||||
_nextShape();
|
||||
continue;
|
||||
}
|
||||
@@ -191,7 +190,7 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
IfcEntities l = ((IfcSchema::ShapeRepresentation*)shaperep.get())->Shapes();
|
||||
for( IfcParse::Entities::it it = l->begin(); it != l->end(); ++ it ) {
|
||||
const IfcEntity ifcshape = *it;
|
||||
if ( ifcshape->dt == IfcSchema::Enum::IfcMappedItem ) continue;
|
||||
if ( ifcshape->type == IfcSchema::Enum::IfcMappedItem ) continue;
|
||||
TopoDS_Shape ss;
|
||||
if ( IfcGeom::convert_shape(ifcshape,ss) && ! ss.IsNull() ) {
|
||||
builder.Add(shapes,ss);
|
||||
@@ -217,15 +216,15 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
IfcGeom::convert((IfcSchema::LocalPlacement*)(entity->Placement().get()),trsf);
|
||||
} catch( IfcParse::IfcException& e ) {std::cout << "[Error] " << e.what() << std::endl; _nextShape(); }
|
||||
IfcEntities openings = IfcEntities();
|
||||
if ( entity->dt != IfcSchema::Enum::IfcOpeningElement ) {
|
||||
if ( entity->type != IfcSchema::Enum::IfcOpeningElement ) {
|
||||
openings = entity->parents(IfcSchema::Enum::IfcRelVoidsElement);
|
||||
}
|
||||
|
||||
if ( (openings && openings->size) || use_world_coords ) {
|
||||
if ( (openings && openings->Size()) || use_world_coords ) {
|
||||
if ( shape ) delete shape;
|
||||
TopoDS_Shape temp_shape (shapes);
|
||||
try {
|
||||
if (openings && openings->size) IfcGeom::convert_openings(entity,openings,temp_shape,trsf);
|
||||
if (openings && openings->Size()) IfcGeom::convert_openings(entity,openings,temp_shape,trsf);
|
||||
} catch( IfcParse::IfcException& e ) {std::cout << "[Warning] " << e.what() << std::endl; }
|
||||
catch(StdFail_NotDone&) { std::cout << "[Error] Unknown modelling processing openings for:" << std::endl << entity->toString() << std::endl; }
|
||||
if ( use_world_coords ) {
|
||||
@@ -237,7 +236,7 @@ IfcGeomObjects::IfcGeomObject* _get() {
|
||||
} else if ( ! shape ) {
|
||||
shape = new IfcGeomObjects::IfcMesh(shaperep->id,shapes);
|
||||
}
|
||||
return new IfcGeomObjects::IfcGeomObject(guid, entity->datatype(), trsf, shape);
|
||||
return new IfcGeomObjects::IfcGeomObject(guid, entity->Datatype(), trsf, shape);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +271,7 @@ extern bool IfcGeomObjects::Init(char* fn, bool world_coords) {
|
||||
if ( ! currentGeomObj ) return false;
|
||||
|
||||
done = 0;
|
||||
total = shapereps->size;
|
||||
total = shapereps->Size();
|
||||
return 1;
|
||||
}
|
||||
extern int IfcGeomObjects::Progress() {
|
||||
|
||||
@@ -33,20 +33,20 @@
|
||||
* *
|
||||
* IfcGeomObject represents the actual IfcBuildingElements. *
|
||||
* IfcGeomObject.name is the GUID of the element *
|
||||
* IfcGeomObject.type is the datatype of the element e.g. IFCWINDOW *
|
||||
* IfcGeomObject.type is the datatype of the element e.g. IfcWindow *
|
||||
* IfcGeomObject.mesh is a pointer to an IfcMesh *
|
||||
* IfcGeomObject.matrix is a 4x3 matrix that defines the orientation and *
|
||||
* translation of the mesh in relation to the world origin *
|
||||
* *
|
||||
* Init(char* fn, bool world_coords) parses the IFC file in fn, returns true
|
||||
* on succes, world_coords = true will result in all IfcGeomObject.matrix
|
||||
* being an identity matrix and IfcMesh.verts containing global positions
|
||||
* Init(char* fn, bool world_coords) parses the IFC file in fn, returns true *
|
||||
* on succes, world_coords = true will result in all IfcGeomObject.matrix *
|
||||
* being an identity matrix and IfcMesh.verts containing global positions *
|
||||
* *
|
||||
* Get() returns a pointer to the current IfcGeomObject
|
||||
* Get() returns a pointer to the current IfcGeomObject *
|
||||
* *
|
||||
* Next() returns true if there is an entity yet available
|
||||
* Next() returns true if there is an entity yet available *
|
||||
* *
|
||||
* Progress() returns an int in [0..100] that indicates the overall progress
|
||||
* Progress() returns an int in [0..100] that indicates the overall progress *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
@@ -64,6 +65,9 @@ namespace IfcGeomObjects {
|
||||
|
||||
typedef std::vector<int>::const_iterator IntIt;
|
||||
typedef std::vector<float>::const_iterator FltIt;
|
||||
typedef std::pair< float,std::pair<float,float> > VertKey;
|
||||
typedef std::map<VertKey,int> VertKeyMap;
|
||||
typedef std::pair<int,int> Edge;
|
||||
|
||||
class IfcMesh {
|
||||
public:
|
||||
@@ -71,15 +75,16 @@ namespace IfcGeomObjects {
|
||||
std::vector<float> verts;
|
||||
std::vector<int> faces;
|
||||
std::vector<int> edges;
|
||||
VertKeyMap welds;
|
||||
|
||||
IfcMesh(int i, TopoDS_Shape s);
|
||||
private:
|
||||
int addvert(gp_Pnt p);
|
||||
inline void addedge(int n1, int n2, std::map<std::pair<int,int>,int>& edgecount, std::vector<std::pair<int,int> >& edges_temp) {
|
||||
if ( edgecount.find(std::pair<int,int>((std::min)(n1,n2),(std::max)(n1,n2))) == edgecount.end() )
|
||||
edgecount[std::pair<int,int>((std::min)(n1,n2),(std::max)(n1,n2))] = 0;
|
||||
edgecount[std::pair<int,int>((std::min)(n1,n2),(std::max)(n1,n2))] ++;
|
||||
edges_temp.push_back(std::pair<int,int>((std::min)(n1,n2),(std::max)(n1,n2)));
|
||||
const Edge e = Edge( (std::min)(n1,n2),(std::max)(n1,n2) );
|
||||
if ( edgecount.find(e) == edgecount.end() ) edgecount[e] = 1;
|
||||
else edgecount[e] ++;
|
||||
edges_temp.push_back(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+78
-112
@@ -31,6 +31,7 @@
|
||||
#undef IFC_WIRE_CLASS
|
||||
#undef IFC_CURVE_CLASS
|
||||
#undef IFC_HELPER_CLASS
|
||||
#undef IFC_RENDER_CLASS
|
||||
#undef IFC_END_CLASS
|
||||
#undef IFC_REF
|
||||
#undef IFC_REFS
|
||||
@@ -47,7 +48,7 @@
|
||||
#define IFC_WIRE_CLASS(N) IFC_CLASS(N,"")
|
||||
#define IFC_CURVE_CLASS(N) IFC_CLASS(N,"")
|
||||
#define IFC_HELPER_CLASS(N) IFC_CLASS(N,"")
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_RENDER_CLASS(N) IFC_CLASS(N,"")
|
||||
#define IFC_END_CLASS };
|
||||
#define IFC_REF(C,N,I) IfcEntity N();
|
||||
#define IFC_REFS(C,N,I) IfcEntities N();
|
||||
@@ -59,21 +60,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef IFC_PARSE_SOURCE
|
||||
#define IFC_CLASS(N,T)
|
||||
#define IFC_SHAPE_CLASS(N)
|
||||
#define IFC_FACE_CLASS(N)
|
||||
#define IFC_WIRE_CLASS(N)
|
||||
#define IFC_CURVE_CLASS(N)
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I) IfcEntity C::N() { return this->arg(I)->ref(); }
|
||||
#define IFC_REFS(C,N,I) IfcEntities C::N() { return this->arg(I)->refs(); }
|
||||
#define IFC_FLT(C,N,I) float C::N() { return this->arg(I)->f(); }
|
||||
#define IFC_FLT_SUB(C,N,I,J) float C::N() { return this->arg(I)->arg(J)->f(); }
|
||||
#define IFC_INT(C,N,I) int C::N() { return this->arg(I)->i(); }
|
||||
#define IFC_STR(C,N,I) std::string C::N() { return this->arg(I)->s(); }
|
||||
#define IFC_BOOL(C,N,I) bool C::N() { return this->arg(I)->b(); }
|
||||
#define IFC_REF(C,N,I) IfcEntity C::N() { return *(*this)[I]; }
|
||||
#define IFC_REFS(C,N,I) IfcEntities C::N() { return *(*this)[I]; }
|
||||
#define IFC_FLT(C,N,I) float C::N() { return *(*this)[I]; }
|
||||
#define IFC_FLT_SUB(C,N,I,J) float C::N() { return *(*(*this)[I])[J]; }
|
||||
#define IFC_INT(C,N,I) int C::N() { return *(*this)[I]; }
|
||||
#define IFC_STR(C,N,I) std::string C::N() { return *(*this)[I]; }
|
||||
#define IFC_BOOL(C,N,I) bool C::N() { return *(*this)[I]; }
|
||||
#endif
|
||||
|
||||
#ifdef IFC_PARSE_ENUM
|
||||
@@ -83,15 +76,7 @@
|
||||
#define IFC_FACE_CLASS(N) Ifc##N,
|
||||
#define IFC_CLASS(N,T) Ifc##N,
|
||||
#define IFC_HELPER_CLASS(N) Ifc##N,
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#define IFC_RENDER_CLASS(N) Ifc##N,
|
||||
#endif
|
||||
|
||||
#ifdef IFC_PARSE_STR_ENUM
|
||||
@@ -101,15 +86,8 @@
|
||||
#define IFC_CURVE_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_HELPER_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_CLASS(N,T) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_RENDER_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_SKIP_CLASS(N) if ( strcasecmp(a.c_str()+3,#N) == 0 ) { return IfcSchema::Enum::IfcDontCare; }
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#endif
|
||||
|
||||
#ifdef IFC_PARSE_ENUM_STR
|
||||
@@ -118,16 +96,12 @@
|
||||
#define IFC_WIRE_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_CURVE_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_HELPER_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_RENDER_CLASS(N) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_CLASS(N,T) IFC_SHAPE_CLASS(N)
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#endif
|
||||
|
||||
#ifdef IFC_PARSE_RENDER
|
||||
#define IFC_RENDER_CLASS(N) if ( t == IfcSchema::Enum::Ifc##N ) return true;
|
||||
#endif
|
||||
|
||||
#ifdef IFC_GEOM_HEADER
|
||||
@@ -135,87 +109,79 @@
|
||||
#define IFC_FACE_CLASS(N) bool convert(IfcSchema::N* Ifc##N,TopoDS_Face& result);
|
||||
#define IFC_WIRE_CLASS(N) bool convert(IfcSchema::N* Ifc##N,TopoDS_Wire& result);
|
||||
#define IFC_CURVE_CLASS(N) bool convert(IfcSchema::N* Ifc##N,Handle(Geom_Curve)& result);
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#define IFC_CLASS(N,T) bool convert(IfcSchema::N* Ifc##N,T& result);
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#endif
|
||||
|
||||
#ifdef IFC_SHAPE_SRC
|
||||
#define IFC_SHAPE_CLASS(N) if ( L->dt == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); bool b = false; try { b = IfcGeom::convert(x,result); } catch(IfcParse::IfcException& e) { std::cout << "[Error] " << e.what() << std::endl;} catch(StdFail_NotDone&) { std::cout << "[Error] Unknown modelling error" << std::endl; } if (!b) std::cout << "[Error] Failed to convert:" << std::endl << x->toString() << std::endl; return b; }
|
||||
#define IFC_FACE_CLASS(N)
|
||||
#define IFC_WIRE_CLASS(N)
|
||||
#define IFC_CURVE_CLASS(N)
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#define IFC_CLASS(N,T)
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#define IFC_SHAPE_CLASS(N) else if ( L->type == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); try { r = IfcGeom::convert(x,result); } catch(IfcParse::IfcException& e) { std::cout << "[Error] " << e.what() << std::endl;} catch(StdFail_NotDone&) { std::cout << "[Error] Unknown modelling error" << std::endl; } }
|
||||
#endif
|
||||
|
||||
#ifdef IFC_WIRE_SRC
|
||||
#define IFC_SHAPE_CLASS(N)
|
||||
#define IFC_FACE_CLASS(N)
|
||||
#define IFC_WIRE_CLASS(N) if ( L->dt == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); return IfcGeom::convert(x,result); }
|
||||
#define IFC_CURVE_CLASS(N)
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#define IFC_CLASS(N,T)
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#define IFC_WIRE_CLASS(N) else if ( L->type == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); r = IfcGeom::convert(x,result); }
|
||||
#endif
|
||||
|
||||
#ifdef IFC_FACE_SRC
|
||||
#define IFC_SHAPE_CLASS(N)
|
||||
#define IFC_FACE_CLASS(N) if ( L->dt == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); return IfcGeom::convert(x,result); }
|
||||
#define IFC_WIRE_CLASS(N) if ( L->dt == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); if ( ! IfcGeom::convert(x,wire) ) return false; return IfcGeom::convert_wire_to_face(wire,result); }
|
||||
#define IFC_CURVE_CLASS(N)
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#define IFC_CLASS(N,T)
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#define IFC_FACE_CLASS(N) else if ( L->type == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); r = IfcGeom::convert(x,result); }
|
||||
#define IFC_WIRE_CLASS(N) else if ( L->type == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); TopoDS_Wire wire; if ( ! IfcGeom::convert(x,wire) ) r = false; r = IfcGeom::convert_wire_to_face(wire,result); }
|
||||
#endif
|
||||
|
||||
#ifdef IFC_CURVE_SRC
|
||||
#define IFC_SHAPE_CLASS(N)
|
||||
#define IFC_FACE_CLASS(N)
|
||||
#define IFC_WIRE_CLASS(N)
|
||||
#define IFC_CURVE_CLASS(N) if ( L->dt == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); return IfcGeom::convert(x,result); }
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#define IFC_CLASS(N,T)
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#define IFC_END_CLASS
|
||||
#define IFC_REF(C,N,I)
|
||||
#define IFC_REFS(C,N,I)
|
||||
#define IFC_FLT(C,N,I)
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#define IFC_INT(C,N,I)
|
||||
#define IFC_STR(C,N,I)
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#define IFC_CURVE_CLASS(N) if ( L->type == IfcSchema::Enum::Ifc##N ) { IfcSchema::N* x = (IfcSchema::N*) L.get(); return IfcGeom::convert(x,result); }
|
||||
#endif
|
||||
|
||||
#ifdef IFC_GEOM_CACHE
|
||||
#define IFC_CLASS(N,T) std::map<int,T*> N;
|
||||
#endif
|
||||
|
||||
#ifdef IFC_GEOM_CACHE_PURGE
|
||||
#define IFC_CLASS(N,T) for(std::map<int,T*>::const_iterator it = N.begin(); it != N.end(); it ++ ) delete it->second; N.clear();
|
||||
#endif
|
||||
|
||||
#ifndef IFC_CLASS
|
||||
#define IFC_CLASS(N,T)
|
||||
#endif
|
||||
#ifndef IFC_SHAPE_CLASS
|
||||
#define IFC_SHAPE_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_FACE_CLASS
|
||||
#define IFC_FACE_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_SKIP_CLASS
|
||||
#define IFC_SKIP_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_WIRE_CLASS
|
||||
#define IFC_WIRE_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_CURVE_CLASS
|
||||
#define IFC_CURVE_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_HELPER_CLASS
|
||||
#define IFC_HELPER_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_RENDER_CLASS
|
||||
#define IFC_RENDER_CLASS(N)
|
||||
#endif
|
||||
#ifndef IFC_END_CLASS
|
||||
#define IFC_END_CLASS
|
||||
#endif
|
||||
#ifndef IFC_REF
|
||||
#define IFC_REF(C,N,I)
|
||||
#endif
|
||||
#ifndef IFC_REFS
|
||||
#define IFC_REFS(C,N,I)
|
||||
#endif
|
||||
#ifndef IFC_FLT
|
||||
#define IFC_FLT(C,N,I)
|
||||
#endif
|
||||
#ifndef IFC_FLT_SUB
|
||||
#define IFC_FLT_SUB(C,N,I,J)
|
||||
#endif
|
||||
#ifndef IFC_INT
|
||||
#define IFC_INT(C,N,I)
|
||||
#endif
|
||||
#ifndef IFC_STR
|
||||
#define IFC_STR(C,N,I)
|
||||
#endif
|
||||
#ifndef IFC_BOOL
|
||||
#define IFC_BOOL(C,N,I)
|
||||
#endif
|
||||
+521
-356
@@ -1,21 +1,21 @@
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
#include "../ifcparse/IfcEnum.h"
|
||||
@@ -23,261 +23,409 @@
|
||||
|
||||
using namespace IfcParse;
|
||||
|
||||
Argument::Argument(const std::string& s) {
|
||||
const char first = s[0];
|
||||
const int strlen = s.size();
|
||||
const char last = s[strlen-1];
|
||||
if ( first == '#' ) {
|
||||
type = IDENTIFIER;
|
||||
std::istringstream iss(s.substr(1));
|
||||
iss >> _data;
|
||||
} else if ( first == '(' || first == ')' || first == '=' || first == '$' || first == '*' || first == ';' || first == ',' ) {
|
||||
type = OPERATOR;
|
||||
_data = first;
|
||||
} else if ( first == '\'' && last == '\'' ) {
|
||||
type = STRING;
|
||||
_data = -1;
|
||||
std::string t = s.substr(1,s.size()-2);
|
||||
for ( int i = 0; i < (int)argstrings.size(); ++ i ) if ( argstrings[i] == t ) { _data = i; break; }
|
||||
if ( _data == -1 ) { _data = argstrings.size(); argstrings.push_back(t); }
|
||||
} else if ( first == '.' && last == '.' ) {
|
||||
type = ENUMERATION;
|
||||
_data = -1;
|
||||
std::string t = s.substr(1,s.size()-2);
|
||||
for ( int i = 0; i < (int)enumstrings.size(); ++ i ) if ( enumstrings[i] == t ) { _data = i; break; }
|
||||
if ( _data == -1 ) { _data = enumstrings.size(); enumstrings.push_back(t); }
|
||||
} else if ( ( first >= 48 && first <= 57 ) || first == '-' || first == '.' ) {
|
||||
type = NUMBER;
|
||||
std::istringstream iss(s);
|
||||
iss >> _number;
|
||||
//
|
||||
// Opens the file, gets the filesize and reads a chunk in memory
|
||||
//
|
||||
File::File(const std::string& fn) {
|
||||
eof = false;
|
||||
stream.open(fn.c_str(),std::ios_base::binary);
|
||||
stream.seekg(0,std::ios_base::end);
|
||||
size = stream.tellg();
|
||||
stream.seekg(0,std::ios_base::beg);
|
||||
buffer = new char[size < BUF_SIZE ? size : BUF_SIZE];
|
||||
ptr = 0;
|
||||
len = 0;
|
||||
offset = 0;
|
||||
ReadBuffer(false);
|
||||
}
|
||||
|
||||
void File::Close() {
|
||||
stream.close();
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
//
|
||||
// Reads a chunk of BUF_SIZE in memory and increments cursor if requested
|
||||
//
|
||||
void File::ReadBuffer(bool inc) {
|
||||
if ( inc ) {
|
||||
offset += len;
|
||||
stream.seekg(offset,std::ios_base::beg);
|
||||
}
|
||||
eof = stream.eof();
|
||||
if ( eof ) return;
|
||||
stream.read(buffer,size < BUF_SIZE ? size : BUF_SIZE);
|
||||
len = stream.gcount();
|
||||
eof = len == 0;
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Seeks an arbitrary position in the file
|
||||
//
|
||||
void File::Seek(unsigned int o) {
|
||||
if ( o >= offset && (o < (offset+len)) ) {
|
||||
ptr = o - offset;
|
||||
} else {
|
||||
type = DATATYPE;
|
||||
_data = -1;
|
||||
for ( int i = 0; i < (int)datatypes.size(); ++ i ) if ( datatypes[i] == s ) { _data = i; break; }
|
||||
if ( _data == -1 ) { _data = datatypes.size(); datatypes.push_back(s); }
|
||||
offset = o;
|
||||
stream.clear();
|
||||
stream.seekg(o,std::ios_base::beg);
|
||||
ReadBuffer(false);
|
||||
}
|
||||
}
|
||||
Argument::Argument(const EntityPtr e) {
|
||||
type = SUB_ENTITY;
|
||||
_entity = e;
|
||||
}
|
||||
std::string Argument::s() const {
|
||||
if ( type == OPERATOR ) { std::string r; r.push_back((char)_data); return r; }
|
||||
if ( type == DATATYPE ) return datatypes[_data];
|
||||
if ( type == STRING ) return argstrings[_data];
|
||||
if ( type == ENUMERATION ) return enumstrings[_data];
|
||||
throw IfcException();
|
||||
}
|
||||
float Argument::f() const {
|
||||
if ( type != NUMBER ) throw IfcException();
|
||||
return _number;
|
||||
}
|
||||
int Argument::i() const {
|
||||
if ( type != IDENTIFIER ) throw IfcException();
|
||||
return _data;
|
||||
}
|
||||
bool Argument::b() const {
|
||||
if ( type != ENUMERATION ) throw IfcException();
|
||||
return s() == "T";
|
||||
}
|
||||
EntityPtr Argument::r() const {
|
||||
if ( type != SUB_ENTITY ) throw IfcException();
|
||||
return _entity;
|
||||
}
|
||||
bool Argument::isOp(char op) const {
|
||||
return type == OPERATOR && ( op == 0 || op == ((char)_data) );
|
||||
}
|
||||
std::string Argument::toString() const {
|
||||
if ( type == DATATYPE ) return s();
|
||||
else if ( type == OPERATOR ) return s();
|
||||
std::stringstream ss;
|
||||
if ( type == NUMBER ) ss << f();
|
||||
else if ( type == STRING ) ss << "'" << s() << "'";
|
||||
else if ( type == ENUMERATION ) ss << "." << s() << ".";
|
||||
else if ( type == IDENTIFIER ) ss << "#" << i();
|
||||
else if ( type == SUB_ENTITY ) ss << _entity->toString();
|
||||
return ss.str();
|
||||
}
|
||||
std::vector<std::string> Argument::datatypes;
|
||||
std::vector<std::string> Argument::argstrings;
|
||||
std::vector<std::string> Argument::enumstrings;
|
||||
|
||||
ArgumentList::ArgumentList() {
|
||||
_levels.push_back(this);
|
||||
_current = this;
|
||||
_arg = 0;
|
||||
}
|
||||
void ArgumentList::_push() {
|
||||
ArgumentList* a = new ArgumentList();
|
||||
_levels.push_back(a);
|
||||
_args.push_back(a);
|
||||
_current = a;
|
||||
}
|
||||
bool ArgumentList::_pop() {
|
||||
_levels.pop_back();
|
||||
if ( _levels.empty() ) return true;
|
||||
_current = _levels.back();
|
||||
return _levels.empty();
|
||||
}
|
||||
void ArgumentList::_append(const Argument* v) {
|
||||
ArgumentList* a = new ArgumentList();
|
||||
a->_arg = v;
|
||||
_current->_args.push_back(a);
|
||||
//
|
||||
// Returns the character at the cursor
|
||||
//
|
||||
char File::Peek() {
|
||||
return buffer[ptr];
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the character at specified offset
|
||||
//
|
||||
char File::Read(unsigned int o) {
|
||||
if ( o >= offset && (o < (offset+len)) ) {
|
||||
return buffer[o-offset];
|
||||
} else {
|
||||
stream.clear();
|
||||
stream.seekg(o,std::ios_base::beg);
|
||||
return stream.peek();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the cursor position
|
||||
//
|
||||
unsigned int File::Tell() {
|
||||
return offset + ptr;
|
||||
}
|
||||
|
||||
//
|
||||
// Increments cursor and reads new chunk if necessary
|
||||
//
|
||||
void File::Inc() {
|
||||
if ( ++ptr == len ) { ReadBuffer(); }
|
||||
}
|
||||
|
||||
Tokens::Tokens(IfcParse::File *f) {
|
||||
file = f;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the offset of the current Token and moves cursor to next
|
||||
//
|
||||
Token Tokens::Next() {
|
||||
|
||||
if ( file->eof ) return TokenPtr();
|
||||
|
||||
char c;
|
||||
|
||||
// Trim whitespace
|
||||
while ( !file->eof ) {
|
||||
c = file->Peek();
|
||||
if ( (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) file->Inc();
|
||||
else break;
|
||||
}
|
||||
|
||||
if ( file->eof ) return TokenPtr();
|
||||
unsigned int pos = file->Tell();
|
||||
|
||||
bool inString = false;
|
||||
bool inComment = false;
|
||||
|
||||
// If the cursor is at [()=,;$*] we know token consists of single char
|
||||
if ( c == '(' || c == ')' || c == '=' || c == ',' || c == ';' || c == '$' || c == '*' ) {
|
||||
file->Inc();
|
||||
return TokenPtr(c);
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
|
||||
char p = 0;
|
||||
while ( ! file->eof ) {
|
||||
|
||||
// Read character and increment pointer if not starting a new token
|
||||
char c = file->Peek();
|
||||
if ( len && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
||||
file->Inc();
|
||||
|
||||
// Skip whitespace if not in comment or string
|
||||
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
||||
|
||||
len ++;
|
||||
|
||||
// Keep track of whether cursor is inside a string or comment
|
||||
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
||||
else if ( !inString && !inComment && p == '/' && c == '*' ) inComment = true;
|
||||
else if ( !inComment && c == '\'' ) inString = ! inString;
|
||||
|
||||
p = c;
|
||||
}
|
||||
if ( len ) return TokenPtr(pos);
|
||||
else return TokenPtr();
|
||||
}
|
||||
|
||||
//
|
||||
// Reads a std::string from the file at specified offset
|
||||
// Omits whitespace and comments
|
||||
//
|
||||
std::string Tokens::TokenString(unsigned int offset) {
|
||||
unsigned int old_offset = file->Tell();
|
||||
file->Seek(offset);
|
||||
bool inString = false;
|
||||
bool inComment = false;
|
||||
std::string buffer;
|
||||
buffer.reserve(128);
|
||||
char p = 0;
|
||||
while ( ! file->eof ) {
|
||||
char c = file->Peek();
|
||||
if ( buffer.size() && (!inString || inComment) && (c == '(' || c == ')' || c == '=' || c == ',' || c == ';' ) ) break;
|
||||
file->Inc();
|
||||
if ( !inComment && !inString && (c == ' ' || c == '\r' || c == '\n' || c == '\t' ) ) continue;
|
||||
if ( !inComment ) buffer.push_back(c);
|
||||
if ( inComment && p == '*' && c == '/' ) inComment = false;
|
||||
else if ( !inString && !inComment && p == '/' && c == '*' ) inComment = true;
|
||||
else if ( !inComment && c == '\'' ) inString = ! inString;
|
||||
p = c;
|
||||
}
|
||||
file->Seek(old_offset);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//
|
||||
// Functions for creating Tokens from an arbitary file offset.
|
||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||
//
|
||||
Token IfcParse::TokenPtr(unsigned int offset) { return offset + 128; }
|
||||
Token IfcParse::TokenPtr(char c) { return c; }
|
||||
Token IfcParse::TokenPtr() { return 0; }
|
||||
|
||||
//
|
||||
// Functions to convert Tokens to binary data
|
||||
//
|
||||
unsigned int TokenFunc::Offset(Token t) { return t - 128; }
|
||||
bool TokenFunc::startsWith(Token t, char c) {
|
||||
return Ifc::file->Read(Offset(t)) == c;
|
||||
}
|
||||
bool TokenFunc::isOperator(Token t, char op) {
|
||||
return (t < 128) && (!op || op == t);
|
||||
}
|
||||
bool TokenFunc::isIdentifier(Token t) {
|
||||
return ! isOperator(t) && startsWith(t, '#');
|
||||
}
|
||||
bool TokenFunc::isString(Token t) {
|
||||
return ! isOperator(t) && startsWith(t, '\'');
|
||||
}
|
||||
bool TokenFunc::isEnumeration(Token t) {
|
||||
return ! isOperator(t) && startsWith(t, '.');
|
||||
}
|
||||
bool TokenFunc::isDatatype(Token t) {
|
||||
return ! isOperator(t) && startsWith(t, 'I');
|
||||
}
|
||||
int TokenFunc::asInt(Token t) {
|
||||
if ( ! isIdentifier(t) ) throw IfcException("Token is not an identifier");
|
||||
const std::string str = asString(t);
|
||||
return atoi(str.c_str()+1);
|
||||
}
|
||||
bool TokenFunc::asBool(Token t) {
|
||||
const std::string str = asString(t);
|
||||
return str == "T";
|
||||
}
|
||||
float TokenFunc::asFloat(Token t) {
|
||||
const std::string str = asString(t);
|
||||
return (float) atof(str.c_str());
|
||||
}
|
||||
std::string TokenFunc::asString(Token t) {
|
||||
if ( isOperator(t,'$') ) return "";
|
||||
else if ( isOperator(t) ) throw IfcException("Token is not a string");
|
||||
std::string str = Ifc::tokens->TokenString(t - 128);
|
||||
return isString(t) || isEnumeration(t) ? str.substr(1,str.size()-2) : str;
|
||||
}
|
||||
std::string TokenFunc::toString(Token t) {
|
||||
if ( isOperator(t) ) return std::string ( (char*) &t, 1 );
|
||||
else return asString(t);
|
||||
}
|
||||
|
||||
|
||||
TokenArgument::TokenArgument(Token t) {
|
||||
token = t;
|
||||
}
|
||||
|
||||
EntityArgument::EntityArgument(EntityPtr e) {
|
||||
entity = e;
|
||||
}
|
||||
|
||||
//
|
||||
// Reads the arguments from a list of token
|
||||
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
||||
//
|
||||
ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
||||
while( Token next = t->Next() ) {
|
||||
if ( TokenFunc::isOperator(next,',') ) continue;
|
||||
if ( TokenFunc::isOperator(next,')') ) break;
|
||||
if ( TokenFunc::isOperator(next,'(') ) Push( ArgumentPtr(new ArgumentList(t,ids)) );
|
||||
else {
|
||||
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
||||
if ( TokenFunc::isDatatype(next) ) {
|
||||
Ifc::file->Seek(TokenFunc::Offset(next));
|
||||
EntityPtr entity = EntityPtr(new Entity(0,t,ids,true));
|
||||
Push ( ArgumentPtr(new EntityArgument(entity)) );
|
||||
} else {
|
||||
Push ( ArgumentPtr(new TokenArgument(next)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArgumentList::Push(ArgumentPtr l) {
|
||||
list.push_back(l);
|
||||
}
|
||||
|
||||
//
|
||||
// Functions for casting the ArgumentList to other types
|
||||
//
|
||||
ArgumentList::operator int() const { throw IfcException("Argument is not an integer"); }
|
||||
ArgumentList::operator bool() const { throw IfcException("Argument is not a boolean"); }
|
||||
ArgumentList::operator float() const { throw IfcException("Argument is not a number"); }
|
||||
ArgumentList::operator std::string() const { throw IfcException("Argument is not a string"); }
|
||||
ArgumentList::operator EntityPtr() const { throw IfcException("Argument is not an IFC type"); }
|
||||
ArgumentList::operator EntitiesPtr() const {
|
||||
EntitiesPtr l (new Entities());
|
||||
std::vector<ArgumentPtr>::const_iterator it;
|
||||
for ( it = list.begin(); it != list.end(); ++ it ) {
|
||||
// FIXME: account for $
|
||||
const EntityPtr entity = **it;
|
||||
l->push(entity);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
unsigned int ArgumentList::Size() const { return list.size(); }
|
||||
ArgumentPtr ArgumentList::operator [] (unsigned int i) const {
|
||||
if ( i >= list.size() )
|
||||
throw IfcException("Argument index out of range");
|
||||
return list[i];
|
||||
}
|
||||
std::string ArgumentList::toString() const {
|
||||
if ( _arg ) return _arg->toString();
|
||||
std::stringstream ss; ss << "(";
|
||||
std::vector<ArgumentList*>::const_iterator it;
|
||||
for ( it = _args.begin() ; it != _args.end(); ++ it ) {
|
||||
if ( it != _args.begin() ) ss << ",";
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
for( std::vector<ArgumentPtr>::const_iterator it = list.begin(); it != list.end(); it ++ ) {
|
||||
if ( it != list.begin() ) ss << ",";
|
||||
ss << (*it)->toString();
|
||||
}
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
float ArgumentList::f() const { return _arg->f(); }
|
||||
bool ArgumentList::b() const { return _arg->b(); }
|
||||
int ArgumentList::i() const { return _arg->i(); }
|
||||
std::string ArgumentList::s() const { return _arg->s(); }
|
||||
int ArgumentList::count() const { return _arg ? 1 : _args.size(); }
|
||||
ArgumentList* ArgumentList::arg(int i) const {
|
||||
if ( i >= count() ) {
|
||||
throw IfcException();
|
||||
} else {
|
||||
return _args[i];
|
||||
}
|
||||
//
|
||||
// Functions for casting the TokenArgument to other types
|
||||
//
|
||||
TokenArgument::operator int() const { return TokenFunc::asInt(token); }
|
||||
TokenArgument::operator bool() const { return TokenFunc::asBool(token); }
|
||||
TokenArgument::operator float() const { return TokenFunc::asFloat(token); }
|
||||
TokenArgument::operator std::string() const { return TokenFunc::asString(token); }
|
||||
TokenArgument::operator EntityPtr() const { return Ifc::EntityById(TokenFunc::asInt(token)); }
|
||||
TokenArgument::operator EntitiesPtr() const { throw IfcException("Argument is not a list of entities"); }
|
||||
unsigned int TokenArgument::Size() const { return 1; }
|
||||
ArgumentPtr TokenArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
||||
std::string TokenArgument::toString() const { return TokenFunc::asString(token); }
|
||||
|
||||
//
|
||||
// Functions for casting the EntityArgument to other types
|
||||
//
|
||||
EntityArgument::operator int() const { throw IfcException("Argument is not an integer"); }
|
||||
EntityArgument::operator bool() const { throw IfcException("Argument is not a boolean"); }
|
||||
EntityArgument::operator float() const { throw IfcException("Argument is not a number"); }
|
||||
EntityArgument::operator std::string() const { throw IfcException("Argument is not a string"); }
|
||||
EntityArgument::operator EntityPtr() const { return entity; }
|
||||
EntityArgument::operator EntitiesPtr() const { throw IfcException("Argument is not a list of entities"); }
|
||||
unsigned int EntityArgument::Size() const { return 1; }
|
||||
ArgumentPtr EntityArgument::operator [] (unsigned int i) const { throw IfcException("Argument is not a list of arguments"); }
|
||||
std::string EntityArgument::toString() const { return entity->toString(); }
|
||||
|
||||
//
|
||||
// Reads an Entity from the list of Tokens
|
||||
// If the type of the Entity is not known, the ArgumentList is not loaded
|
||||
//
|
||||
Entity::Entity(unsigned int i, Tokens* t, std::vector<unsigned int>& ids, bool parse) {
|
||||
Token datatype = t->Next();
|
||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||
type = IfcSchema::Enum::FromString(TokenFunc::asString(datatype));
|
||||
id = i;
|
||||
args = ArgumentPtr();
|
||||
offset = TokenFunc::Offset(datatype);
|
||||
if ( (type != IfcSchema::Enum::IfcDontCare && type != IfcSchema::Enum::IfcUnknown) || parse )
|
||||
Load(ids, false);
|
||||
}
|
||||
|
||||
EntityPtr ArgumentList::ref() const {
|
||||
if ( _arg->type == Argument::IDENTIFIER ) {
|
||||
return Ifc::EntityById(_arg->i());
|
||||
} else {
|
||||
return _arg->r();
|
||||
//
|
||||
// Reads an Entity from the list of Tokens at the specified offset in the file
|
||||
//
|
||||
Entity::Entity(unsigned int i, Tokens* t, unsigned int o) {
|
||||
std::vector<unsigned int> ids;
|
||||
id = i;
|
||||
offset = o;
|
||||
Load(ids, true);
|
||||
}
|
||||
|
||||
//
|
||||
// Access the Nth argument from the ArgumentList
|
||||
//
|
||||
ArgumentPtr Entity::operator [] (unsigned int i) {
|
||||
if ( ! args ) {
|
||||
std::vector<unsigned int> ids;
|
||||
Load(ids, true);
|
||||
}
|
||||
return (*args)[i];
|
||||
}
|
||||
EntitiesPtr ArgumentList::refs() const {
|
||||
EntitiesPtr l (new Entities());
|
||||
std::vector<ArgumentList*>::const_iterator it;
|
||||
for ( it = _args.begin(); it != _args.end(); ++ it ) {
|
||||
ArgumentList* a = *it;
|
||||
if ( a->_arg && a->_arg->type == Argument::IDENTIFIER ) {
|
||||
l->push(Ifc::EntityById(a->_arg->i()));
|
||||
} else if ( a->_arg && a->_arg->type == Argument::SUB_ENTITY ) {
|
||||
l->push(a->_arg->r());
|
||||
}
|
||||
|
||||
//
|
||||
// Load the ArgumentList
|
||||
//
|
||||
void Entity::Load(std::vector<unsigned int>& ids, bool seek) {
|
||||
if ( seek ) {
|
||||
Ifc::file->Seek(offset);
|
||||
Token datatype = Ifc::tokens->Next();
|
||||
if ( ! TokenFunc::isDatatype(datatype) ) throw IfcException("Unexpected token while parsing entity");
|
||||
type = IfcSchema::Enum::FromString(TokenFunc::asString(datatype));
|
||||
}
|
||||
return l;
|
||||
Token open = Ifc::tokens->Next();
|
||||
args = ArgumentPtr(new ArgumentList(Ifc::tokens, ids));
|
||||
unsigned int old_offset = Ifc::file->Tell();
|
||||
Token semilocon = Ifc::tokens->Next();
|
||||
if ( ! TokenFunc::isOperator(semilocon,';') ) Ifc::file->Seek(old_offset);
|
||||
}
|
||||
ArgumentList::~ArgumentList() {
|
||||
if ( _arg ) delete _arg;
|
||||
else {
|
||||
while( ! _args.empty() ) {
|
||||
delete _args.back(); _args.pop_back();
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a CamelCase string representation of the datatype as it is defined in IfcSchema.h
|
||||
//
|
||||
std::string Entity::Datatype() const {
|
||||
return IfcSchema::Enum::ToString(type);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a string representation of the entity
|
||||
// Note that this initializes the entity if it is not initialized
|
||||
//
|
||||
std::string Entity::toString() {
|
||||
if ( ! args ) {
|
||||
std::vector<unsigned int> ids;
|
||||
Load(ids, true);
|
||||
}
|
||||
}
|
||||
inline bool Entity::term(char last) {
|
||||
return last == '(' || last == ')' || last == '=' || last == ',' || last == ';';
|
||||
}
|
||||
Entity::Entity(std::istream* ss, std::vector<int>& refs, bool sub) {
|
||||
std::string curvar;
|
||||
curvar.reserve(64);
|
||||
bool inStr = false;
|
||||
bool inComment = false;
|
||||
char c[1] = "";
|
||||
char p[1] = "";
|
||||
int state = -1;
|
||||
int previousPos = -1;
|
||||
args = 0;
|
||||
_dt = 0;
|
||||
id = -1;
|
||||
do {
|
||||
ss->read(c,1);
|
||||
if ( !inComment && !inStr && ((*c) == ' ' || (*c) == '\r' || (*c) == '\n' || (*c) == '\t') ) continue;
|
||||
if ( curvar.size() && !inComment && !inStr && ( term(*c) || term(*curvar.rbegin())) ) {
|
||||
Argument* v = new Argument(curvar);
|
||||
curvar.clear();
|
||||
curvar.push_back(*c);
|
||||
if ( state < 10 ) state ++;
|
||||
if ( !sub && !state ) {
|
||||
if ( v->type == Argument::IDENTIFIER ) {
|
||||
id = v->i();
|
||||
} else {
|
||||
state = -1;
|
||||
}
|
||||
} else if ( ! sub && (state == 1) ) {
|
||||
if ( ! v->isOp('=') ) state = -1;
|
||||
} else if ( (sub && !state) || (!sub && state == 2) ) {
|
||||
if ( v->type == Argument::DATATYPE ) {
|
||||
dt = IfcSchema::Enum::FromString(v->s());
|
||||
_dt = v;
|
||||
continue;
|
||||
}
|
||||
} else if ( args ) {
|
||||
if ( v->isOp('(') )
|
||||
args->_push();
|
||||
else if ( v->isOp(')') ) {
|
||||
bool closed = args->_pop();
|
||||
if ( closed && sub ) {
|
||||
delete v;
|
||||
return;
|
||||
}
|
||||
} else if ( ! v->isOp(',') && !v->isOp(';') ) {
|
||||
if ( v->type == Argument::DATATYPE ) {
|
||||
ss->seekg(previousPos-1,std::ios_base::beg);
|
||||
Argument* a = new Argument(EntityPtr(new Entity(ss,refs,true)));
|
||||
ss->seekg(-1,std::ios_base::cur);
|
||||
curvar.clear();
|
||||
args->_append(a);
|
||||
} else {
|
||||
args->_append(v);
|
||||
if ( v->type == Argument::IDENTIFIER ) refs.push_back(v->i());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if ( v->isOp('(') ) {
|
||||
args = new ArgumentList();
|
||||
}
|
||||
previousPos = ss->tellg();
|
||||
delete v;
|
||||
}
|
||||
else if ( ! inComment ) curvar.push_back(*c);
|
||||
if ( !inComment && *c == '\'' ) inStr = !inStr;
|
||||
else if ( !inStr && *p == '/' && *c == '*' ) { inComment = true; curvar.clear(); }
|
||||
else if ( !inStr && *p == '*' && *c == '/' ) inComment = false;
|
||||
p[0] = c[0];
|
||||
} while ( !ss->eof() && (*c != ';' || inStr) );
|
||||
}
|
||||
Entity::~Entity() {
|
||||
delete args;
|
||||
delete _dt;
|
||||
}
|
||||
bool Entity::isAssignment() const {
|
||||
return args > 0;
|
||||
}
|
||||
std::string Entity::datatype() const {
|
||||
if ( _dt ) return _dt->s();
|
||||
else return IfcSchema::Enum::ToString(dt);
|
||||
}
|
||||
ArgumentList* Entity::arg(int i) const {
|
||||
return this->args->arg(i);
|
||||
}
|
||||
std::string Entity::toString() const {
|
||||
std::stringstream ss;
|
||||
if ( isAssignment() ) {
|
||||
if ( id > 0 ) ss << "#" << id << "=";
|
||||
ss << datatype() << args->toString();
|
||||
}
|
||||
ss << "#" << id << "=" << Datatype() << args->toString();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the entities of type c that have this entity in their ArgumentList
|
||||
//
|
||||
EntitiesPtr Entity::parents(IfcSchema::Enum::IfcTypes c) {
|
||||
EntitiesPtr l = EntitiesPtr(new Entities());
|
||||
EntitiesPtr all = Ifc::EntitiesByReference(id);
|
||||
if ( ! all ) return l;
|
||||
for( Entities::it it = all->begin(); it != all->end();++ it ) {
|
||||
if ( c == IfcSchema::Enum::ALL || (*it)->dt == c ) {
|
||||
if ( c == IfcSchema::Enum::ALL || (*it)->type == c ) {
|
||||
l->push(*it);
|
||||
}
|
||||
}
|
||||
@@ -287,163 +435,169 @@ EntitiesPtr Entity::parents(IfcSchema::Enum::IfcTypes c, int i, const std::strin
|
||||
EntitiesPtr l = EntitiesPtr(new Entities());
|
||||
EntitiesPtr all = parents(c);
|
||||
for( Entities::it it = all->begin(); it != all->end();++ it ) {
|
||||
if ( (*it)->arg(i)->s() == a ) {
|
||||
const std::string s = *((**it)[i]);
|
||||
if ( s == a ) {
|
||||
l->push(*it);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
void Entities::push(EntityPtr l) {
|
||||
if ( l ) {
|
||||
ls.push_back(l);
|
||||
size = ls.size();
|
||||
}
|
||||
if ( l ) ls.push_back(l);
|
||||
}
|
||||
void Entities::pushs(EntitiesPtr l) {
|
||||
void Entities::push(EntitiesPtr l) {
|
||||
for( it i = l->begin(); i != l->end(); ++i ) {
|
||||
if ( *i ) ls.push_back(*i);
|
||||
}
|
||||
size = ls.size();
|
||||
}
|
||||
int Entities::Size() const { return ls.size(); }
|
||||
Entities::it Entities::begin() { return ls.begin(); }
|
||||
Entities::it Entities::end() { return ls.end(); }
|
||||
|
||||
//
|
||||
// Returns the entities of type c that have one of these entities in their ArgumentList
|
||||
//
|
||||
EntitiesPtr Entities::parents(IfcSchema::Enum::IfcTypes c) {
|
||||
EntitiesPtr l = EntitiesPtr(new Entities());
|
||||
for( it i = begin(); i != end(); ++i ) {
|
||||
l->pushs((*i)->parents(c));
|
||||
l->push((*i)->parents(c));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
EntitiesPtr Entities::parents(IfcSchema::Enum::IfcTypes c, int ar, const std::string& a) {
|
||||
EntitiesPtr l = EntitiesPtr(new Entities());
|
||||
for( it i = begin(); i != end(); ++i ) {
|
||||
l->pushs((*i)->parents(c,ar,a));
|
||||
l->push((*i)->parents(c,ar,a));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
EntityPtr Entities::operator[] (int i) {
|
||||
return ls[i];
|
||||
}
|
||||
Entities::Entities() {
|
||||
size = 0;
|
||||
}
|
||||
File::File(const std::string& fn, bool debug) {
|
||||
valid = false;
|
||||
std::ifstream f(fn.c_str());
|
||||
if ( ! f.is_open() ) return;
|
||||
valid = true;
|
||||
std::istream *pf = (std::istream*) &f;
|
||||
while( !pf->eof() ) {
|
||||
std::vector<int> refs;
|
||||
EntityPtr il (new Entity(pf,refs));
|
||||
if ( il->isAssignment() ) {
|
||||
if ( debug )
|
||||
std::cout << il->toString() << std::endl;
|
||||
if ( il->dt == IfcSchema::Enum::IfcDontCare ) {
|
||||
continue;
|
||||
}
|
||||
EntitiesPtr l = EntitiesByType(il->dt);
|
||||
if ( l == 0 ) {
|
||||
l = EntitiesPtr(new Entities());
|
||||
bytype[il->dt] = l;
|
||||
}
|
||||
l->push(il);
|
||||
byid[il->id] = il;
|
||||
|
||||
std::vector<int>::const_iterator it;
|
||||
for( it = refs.begin(); it != refs.end();++ it ) {
|
||||
const int _id = *it;
|
||||
EntitiesPtr L = EntitiesByReference(_id);
|
||||
|
||||
//
|
||||
// Parses the IFC file in fn
|
||||
// Creates the maps
|
||||
// Gets the unit definitins from the file
|
||||
//
|
||||
bool Ifc::Init(const std::string& fn) {
|
||||
file = new File (fn);
|
||||
tokens = new Tokens (file);
|
||||
Token token = 0;
|
||||
Token previous = 0;
|
||||
unsigned int currentId = 0;
|
||||
lastId = 0;
|
||||
int x = 0;
|
||||
EntityPtr entity;
|
||||
std::cout << "Scanning file..." << std::endl;
|
||||
while ( true ) {
|
||||
if ( currentId ) {
|
||||
std::vector<unsigned int> ids;
|
||||
entity = EntityPtr(new Entity(currentId,tokens,ids));
|
||||
if ( !((++x)%1000) ) std::cout << "\r#" << currentId << " ";
|
||||
if ( entity->type != IfcSchema::Enum::IfcDontCare && entity->type != IfcSchema::Enum::IfcUnknown) {
|
||||
byid[currentId] = entity;
|
||||
EntitiesPtr L = EntitiesByType(entity->type);
|
||||
if ( L == 0 ) {
|
||||
L = EntitiesPtr(new Entities());
|
||||
byref[_id] = L;
|
||||
bytype[entity->type] = L;
|
||||
}
|
||||
L->push(il);
|
||||
L->push(entity);
|
||||
for( std::vector<unsigned int>::const_iterator it = ids.begin(); it != ids.end(); ++it ) {
|
||||
const int arg_id = *it;
|
||||
EntitiesPtr L = EntitiesByReference(arg_id);
|
||||
if ( L == 0 ) {
|
||||
L = EntitiesPtr(new Entities());
|
||||
byref[arg_id] = L;
|
||||
}
|
||||
L->push(entity);
|
||||
}
|
||||
} else {
|
||||
offsets[currentId] = entity->offset;
|
||||
}
|
||||
currentId = 0;
|
||||
} else token = tokens->Next();
|
||||
if ( ! token ) break;
|
||||
if ( previous && TokenFunc::isIdentifier(previous) ) {
|
||||
int id = TokenFunc::asInt(previous);
|
||||
if ( TokenFunc::isOperator(token,'=') ) {
|
||||
currentId = id;
|
||||
} else {
|
||||
EntitiesPtr L = EntitiesByReference(id);
|
||||
if ( L == 0 ) {
|
||||
L = EntitiesPtr(new Entities());
|
||||
byref[id] = L;
|
||||
}
|
||||
L->push(entity);
|
||||
}
|
||||
}
|
||||
previous = token;
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
EntitiesPtr File::EntitiesByType(IfcSchema::Enum::IfcTypes t) {
|
||||
std::map<IfcSchema::Enum::IfcTypes,EntitiesPtr>::const_iterator it;
|
||||
it = bytype.find(t);
|
||||
return (it == bytype.end()) ? EntitiesPtr() : (*it).second;
|
||||
}
|
||||
EntitiesPtr File::EntitiesByReference(int t) {
|
||||
std::map<int,EntitiesPtr>::const_iterator it;
|
||||
it = byref.find(t);
|
||||
return (it == byref.end()) ? EntitiesPtr() : (*it).second;
|
||||
}
|
||||
EntityPtr File::EntityById(int id) {
|
||||
std::map<int,EntityPtr>::const_iterator it;
|
||||
it = byid.find(id);
|
||||
if ( it == byid.end() ) throw IfcException(id);
|
||||
return (*it).second;
|
||||
}
|
||||
IfcException::IfcException(int id) {
|
||||
std::stringstream ss;
|
||||
ss << "Unable to find IFC Entity #" << id;
|
||||
w = ss.str();
|
||||
}
|
||||
|
||||
IfcException::IfcException() {
|
||||
w = "Unexpected argument supplied";
|
||||
}
|
||||
std::cout << "\rDone! " << std::endl;
|
||||
|
||||
const char* IfcException::what() const throw(){ return w.c_str(); }
|
||||
IfcException::~IfcException() throw(){ }
|
||||
|
||||
EntitiesPtr Ifc::EntitiesByType(IfcSchema::Enum::IfcTypes t) {
|
||||
return f->EntitiesByType(t);
|
||||
}
|
||||
EntitiesPtr Ifc::EntitiesByReference(int t) {
|
||||
return f->EntitiesByReference(t);
|
||||
}
|
||||
EntityPtr Ifc::EntityById(int id) {
|
||||
return f->EntityById(id);
|
||||
}
|
||||
bool Ifc::Init(const std::string& fn) {
|
||||
f = new File(fn, false);
|
||||
IfcEntity IfcUnitAssigment = *EntitiesByType(IfcSchema::Enum::IfcUnitAssignment)->begin();
|
||||
IfcEntities units = ((IfcSchema::UnitAssignment*)IfcUnitAssigment.get())->Units();
|
||||
Ifc::LengthUnit = 1.0f;
|
||||
if ( units )
|
||||
for ( IfcParse::Entities::it it = units->begin(); it != units->end(); it ++ ) {
|
||||
IfcEntity unit = *it;
|
||||
float value = 1.0f;
|
||||
std::string UnitType = "";
|
||||
if ( unit->dt == IfcSchema::Enum::IfcConversionBasedUnit ) {
|
||||
IfcSchema::ConversionBasedUnit* IfcConversionBasedUnit = (IfcSchema::ConversionBasedUnit*)(*it).get();
|
||||
IfcSchema::MeasureWithUnit* IfcMeasureWithUnit = (IfcSchema::MeasureWithUnit*)IfcConversionBasedUnit->ConversionFactor().get();
|
||||
try {
|
||||
unit = IfcMeasureWithUnit->Unit();
|
||||
value = IfcMeasureWithUnit->Value()->arg(0)->f();
|
||||
} catch (... ) {}
|
||||
}
|
||||
if ( unit->dt == IfcSchema::Enum::IfcSIUnit ) {
|
||||
IfcSchema::SIUnit* IfcSIUnit = (IfcSchema::SIUnit*)(*it).get();
|
||||
value *= UnitPrefixToValue(IfcSIUnit->UnitPrefix());
|
||||
UnitType = IfcSIUnit->UnitType();
|
||||
}
|
||||
if ( UnitType == "LENGTHUNIT" ) {
|
||||
Ifc::LengthUnit = value;
|
||||
} else if ( UnitType == "PLANEANGLEUNIT" ) {
|
||||
Ifc::PlaneAngleUnit = value;
|
||||
for ( IfcParse::Entities::it it = units->begin(); it != units->end(); it ++ ) {
|
||||
IfcEntity unit = *it;
|
||||
float value = 1.0f;
|
||||
std::string UnitType = "";
|
||||
if ( unit->type == IfcSchema::Enum::IfcConversionBasedUnit ) {
|
||||
IfcSchema::ConversionBasedUnit* IfcConversionBasedUnit = (IfcSchema::ConversionBasedUnit*)(*it).get();
|
||||
IfcSchema::MeasureWithUnit* IfcMeasureWithUnit = (IfcSchema::MeasureWithUnit*)IfcConversionBasedUnit->ConversionFactor().get();
|
||||
try {
|
||||
unit = IfcMeasureWithUnit->Unit();
|
||||
value = *((*IfcMeasureWithUnit->Value())[0]);
|
||||
} catch (...) {}
|
||||
}
|
||||
if ( unit->type == IfcSchema::Enum::IfcSIUnit ) {
|
||||
IfcSchema::SIUnit* IfcSIUnit = (IfcSchema::SIUnit*)(*it).get();
|
||||
value *= UnitPrefixToValue(IfcSIUnit->UnitPrefix());
|
||||
UnitType = IfcSIUnit->UnitType();
|
||||
}
|
||||
if ( UnitType == "LENGTHUNIT" ) {
|
||||
Ifc::LengthUnit = value;
|
||||
} else if ( UnitType == "PLANEANGLEUNIT" ) {
|
||||
Ifc::PlaneAngleUnit = value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EntitiesPtr Ifc::EntitiesByType(IfcSchema::Enum::IfcTypes t) {
|
||||
MapEntitiesByType::const_iterator it = bytype.find(t);
|
||||
return (it == bytype.end()) ? EntitiesPtr() : it->second;
|
||||
}
|
||||
EntitiesPtr Ifc::EntitiesByReference(int t) {
|
||||
MapEntitiesByRef::const_iterator it = byref.find(t);
|
||||
return (it == byref.end()) ? EntitiesPtr() : it->second;
|
||||
}
|
||||
EntityPtr Ifc::EntityById(int id) {
|
||||
MapEntityById::const_iterator it = byid.find(id);
|
||||
if ( it == byid.end() ) {
|
||||
MapOffsetById::const_iterator it2 = offsets.find(id);
|
||||
if ( it2 == offsets.end() ) throw IfcException("Entity not found");
|
||||
const unsigned int offset = (*it2).second;
|
||||
EntityPtr entity = EntityPtr(new Entity(id,Ifc::tokens,offset));
|
||||
byid[id] = entity;
|
||||
return entity;
|
||||
}
|
||||
return f->valid;
|
||||
return it->second;
|
||||
}
|
||||
IfcException::IfcException(std::string e) { error = e; }
|
||||
const char* IfcException::what() const { return error.c_str(); }
|
||||
void Ifc::Dispose() {
|
||||
delete f;
|
||||
Argument::datatypes.clear();
|
||||
Argument::argstrings.clear();
|
||||
Argument::enumstrings.clear();
|
||||
file->Close();
|
||||
delete file;
|
||||
delete tokens;
|
||||
offsets.clear();
|
||||
bytype.clear();
|
||||
byid.clear();
|
||||
byref.clear();
|
||||
IfcGeom::Cache::Purge();
|
||||
}
|
||||
File* Ifc::f = 0;
|
||||
float Ifc::LengthUnit = 1.0f;
|
||||
float Ifc::PlaneAngleUnit = 1.0f;
|
||||
int Ifc::CircleSegments = 32;
|
||||
|
||||
float UnitPrefixToValue( const std::string& s ) {
|
||||
if ( s == "EXA" ) return (float) 1e18;
|
||||
@@ -464,3 +618,14 @@ float UnitPrefixToValue( const std::string& s ) {
|
||||
else if ( s == "ATTO" ) return (float) 1e-18;
|
||||
else return 1.0f;
|
||||
}
|
||||
|
||||
File* Ifc::file = 0;
|
||||
unsigned int Ifc::lastId = 0;
|
||||
Tokens* Ifc::tokens = 0;
|
||||
float Ifc::LengthUnit = 1.0f;
|
||||
float Ifc::PlaneAngleUnit = 1.0f;
|
||||
int Ifc::CircleSegments = 32;
|
||||
MapEntitiesByType Ifc::bytype;
|
||||
MapEntityById Ifc::byid;
|
||||
MapEntitiesByRef Ifc::byref;
|
||||
MapOffsetById Ifc::offsets;
|
||||
|
||||
+200
-101
@@ -17,6 +17,13 @@
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file provides functions for loading an IFC file into memory and access *
|
||||
* its entities either by ID, by an IfcSchema::Enum::IfcType or by reference *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCPARSE_H
|
||||
#define IFCPARSE_H
|
||||
|
||||
@@ -31,21 +38,21 @@
|
||||
|
||||
// Pick a shared pointer implementation
|
||||
#ifdef __GNUC__
|
||||
#include <tr1/memory>
|
||||
#define SHARED_PTR std::tr1::shared_ptr
|
||||
#include <tr1/memory>
|
||||
#define SHARED_PTR std::tr1::shared_ptr
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#include <memory>
|
||||
#define SHARED_PTR std::tr1::shared_ptr
|
||||
#else
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#define SHARED_PTR boost::shared_ptr
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#include <memory>
|
||||
#define SHARED_PTR std::tr1::shared_ptr
|
||||
#else
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#define SHARED_PTR boost::shared_ptr
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../ifcparse/IfcEnum.h"
|
||||
|
||||
class Ifc;
|
||||
const int BUF_SIZE = (32 * 1024 * 1024);
|
||||
|
||||
namespace IfcParse {
|
||||
|
||||
@@ -54,135 +61,225 @@ namespace IfcParse {
|
||||
typedef SHARED_PTR<Entity> EntityPtr;
|
||||
typedef SHARED_PTR<Entities> EntitiesPtr;
|
||||
|
||||
class Argument {
|
||||
//
|
||||
// Reads a file in chunks of BUF_SIZE and provides
|
||||
// functions to randomly access its contents
|
||||
//
|
||||
class File {
|
||||
private:
|
||||
static std::vector<std::string> datatypes;
|
||||
static std::vector<std::string> enumstrings;
|
||||
static std::vector<std::string> argstrings;
|
||||
|
||||
int _data;
|
||||
float _number;
|
||||
EntityPtr _entity;
|
||||
std::ifstream stream;
|
||||
char* buffer;
|
||||
unsigned int ptr;
|
||||
unsigned int len;
|
||||
unsigned int offset;
|
||||
void ReadBuffer(bool inc=true);
|
||||
public:
|
||||
enum vartype { IDENTIFIER, STRING, NUMBER, OPERATOR, ENUMERATION, DATATYPE, SUB_ENTITY };
|
||||
vartype type;
|
||||
|
||||
Argument(const std::string& s);
|
||||
Argument(const EntityPtr e);
|
||||
|
||||
bool isOp(char op = 0) const;
|
||||
|
||||
float f() const;
|
||||
int i() const;
|
||||
std::string s() const;
|
||||
bool b() const;
|
||||
EntityPtr r() const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
std::string typeString() const;
|
||||
|
||||
friend class ::Ifc;
|
||||
bool eof;
|
||||
unsigned int size;
|
||||
File(const std::string& fn);
|
||||
char Peek();
|
||||
char Read(unsigned int offset);
|
||||
void Inc();
|
||||
void Close();
|
||||
void Seek(unsigned int offset);
|
||||
unsigned int Tell();
|
||||
};
|
||||
|
||||
class ArgumentList {
|
||||
typedef unsigned int Token;
|
||||
|
||||
//
|
||||
// Provides functions to convert Tokens to binary data
|
||||
// Tokens are merely offsets to where they can be read in the file
|
||||
//
|
||||
class TokenFunc {
|
||||
private:
|
||||
std::vector<ArgumentList*> _levels;
|
||||
std::vector<ArgumentList*> _args;
|
||||
ArgumentList* _current;
|
||||
const Argument* _arg;
|
||||
void _push();
|
||||
bool _pop();
|
||||
void _append(const Argument* v);
|
||||
public:
|
||||
ArgumentList();
|
||||
~ArgumentList();
|
||||
|
||||
float f() const;
|
||||
int i() const;
|
||||
std::string s() const;
|
||||
bool b() const;
|
||||
EntityPtr ref() const;
|
||||
EntitiesPtr refs() const;
|
||||
ArgumentList* arg(int i) const;
|
||||
|
||||
int count() const;
|
||||
std::string toString() const;
|
||||
|
||||
friend class Entity;
|
||||
static bool startsWith(Token t, char c);
|
||||
public:
|
||||
static unsigned int Offset(Token t);
|
||||
static bool isString(Token t);
|
||||
static bool isIdentifier(Token t);
|
||||
static bool isOperator(Token t, char op = 0);
|
||||
static bool isEnumeration(Token t);
|
||||
static bool isDatatype(Token t);
|
||||
static int asInt(Token t);
|
||||
static bool asBool(Token t);
|
||||
static float asFloat(Token t);
|
||||
static std::string asString(Token t);
|
||||
static std::string toString(Token t);
|
||||
};
|
||||
|
||||
//
|
||||
// Functions for creating Tokens from an arbitary file offset
|
||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||
//
|
||||
Token TokenPtr(unsigned int offset);
|
||||
Token TokenPtr(char c);
|
||||
Token TokenPtr();
|
||||
|
||||
//
|
||||
// Interprets a file as a sequential stream of Tokens
|
||||
//
|
||||
class Tokens {
|
||||
private:
|
||||
File* file;
|
||||
public:
|
||||
Tokens(File* f);
|
||||
Token Next();
|
||||
std::string TokenString(unsigned int offset);
|
||||
};
|
||||
|
||||
class Argument;
|
||||
typedef SHARED_PTR<Argument> ArgumentPtr;
|
||||
|
||||
//
|
||||
// Base class of all kind of Arguments used in IFC entity defintions
|
||||
//
|
||||
class Argument {
|
||||
protected:
|
||||
public:
|
||||
virtual operator int() const = 0;
|
||||
virtual operator bool() const = 0;
|
||||
virtual operator float() const = 0;
|
||||
virtual operator std::string() const = 0;
|
||||
virtual operator EntityPtr() const = 0;
|
||||
virtual operator EntitiesPtr() const = 0;
|
||||
virtual unsigned int Size() const = 0;
|
||||
virtual ArgumentPtr operator [] (unsigned int i) const = 0;
|
||||
virtual std::string toString() const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// Argument of type list, e.g.
|
||||
// #1=IfcDirection((1.,0.,0.));
|
||||
// ==========
|
||||
//
|
||||
class ArgumentList: public Argument {
|
||||
private:
|
||||
std::vector<ArgumentPtr> list;
|
||||
void Push(ArgumentPtr l);
|
||||
public:
|
||||
ArgumentList(Tokens* t, std::vector<unsigned int>& ids);
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator float() const;
|
||||
operator std::string() const;
|
||||
operator EntityPtr() const;
|
||||
operator EntitiesPtr() const;
|
||||
unsigned int Size() const;
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
//
|
||||
// Argument of type scalar or string, e.g.
|
||||
// #1=IfcVector(#2,1.0);
|
||||
// == ===
|
||||
//
|
||||
class TokenArgument : public Argument {
|
||||
private:
|
||||
Token token;
|
||||
public:
|
||||
TokenArgument(Token t);
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator float() const;
|
||||
operator std::string() const;
|
||||
operator EntityPtr() const;
|
||||
operator EntitiesPtr() const;
|
||||
unsigned int Size() const;
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
//
|
||||
// Argument of an IFC type
|
||||
// #1=IfcTrimmedCurve(#2,(IFCPARAMETERVALUE(0.)),(IFCPARAMETERVALUE(1.)),.T.,.PARAMETER.);
|
||||
// ===================== =====================
|
||||
//
|
||||
class EntityArgument : public Argument {
|
||||
private:
|
||||
EntityPtr entity;
|
||||
public:
|
||||
EntityArgument(EntityPtr e);
|
||||
operator int() const;
|
||||
operator bool() const;
|
||||
operator float() const;
|
||||
operator std::string() const;
|
||||
operator EntityPtr() const;
|
||||
operator EntitiesPtr() const;
|
||||
unsigned int Size() const;
|
||||
ArgumentPtr operator [] (unsigned int i) const;
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
//
|
||||
// Entity defined in an IFC file, e.g.
|
||||
// #1=IfcDirection((1.,0.,0.));
|
||||
// ============================
|
||||
//
|
||||
class Entity {
|
||||
private:
|
||||
inline bool term(char last);
|
||||
ArgumentPtr args;
|
||||
void Load(std::vector<unsigned int>& ids, bool seek);
|
||||
public:
|
||||
int id;
|
||||
IfcSchema::Enum::IfcTypes dt;
|
||||
ArgumentList* args;
|
||||
Argument* _dt;
|
||||
|
||||
Entity(std::istream* ss, std::vector<int>& refs, bool sub = false);
|
||||
~Entity();
|
||||
|
||||
ArgumentList* arg(int i) const;
|
||||
std::string toString() const;
|
||||
|
||||
unsigned int id;
|
||||
unsigned int offset;
|
||||
IfcSchema::Enum::IfcTypes type;
|
||||
Entity(unsigned int i, Tokens* t, std::vector<unsigned int>& ids, bool parse = false);
|
||||
Entity(unsigned int i, Tokens* t, unsigned int o);
|
||||
EntitiesPtr parents(IfcSchema::Enum::IfcTypes c = IfcSchema::Enum::ALL);
|
||||
EntitiesPtr parents(IfcSchema::Enum::IfcTypes c, int i, const std::string& a);
|
||||
bool isAssignment() const;
|
||||
std::string datatype() const;
|
||||
ArgumentPtr operator[] (unsigned int i);
|
||||
std::string toString();
|
||||
std::string Datatype() const;
|
||||
};
|
||||
|
||||
//
|
||||
// A list of IFC entities
|
||||
//
|
||||
class Entities {
|
||||
private:
|
||||
std::vector<EntityPtr> ls;
|
||||
public:
|
||||
int size;
|
||||
typedef std::vector<EntityPtr>::const_iterator it;
|
||||
void push(EntityPtr l);
|
||||
void pushs(EntitiesPtr l);
|
||||
void push(EntitiesPtr l);
|
||||
it begin();
|
||||
it end();
|
||||
EntitiesPtr parents(IfcSchema::Enum::IfcTypes c = IfcSchema::Enum::ALL);
|
||||
EntitiesPtr parents(IfcSchema::Enum::IfcTypes c, int i, const std::string& a);
|
||||
Entities();
|
||||
EntityPtr operator[] (int i);
|
||||
};
|
||||
|
||||
class File {
|
||||
public:
|
||||
std::map<IfcSchema::Enum::IfcTypes,EntitiesPtr> bytype;
|
||||
std::map<int,EntityPtr> byid;
|
||||
std::map<int,EntitiesPtr> byref;
|
||||
bool valid;
|
||||
|
||||
File(const std::string& fn, bool debug = false);
|
||||
EntitiesPtr EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
||||
EntitiesPtr EntitiesByReference(int id);
|
||||
EntityPtr EntityById(int id);
|
||||
int Size() const;
|
||||
};
|
||||
|
||||
class IfcException : public std::exception {
|
||||
private:
|
||||
std::string w;
|
||||
std::string error;
|
||||
public:
|
||||
IfcException(int id);
|
||||
IfcException();
|
||||
~IfcException() throw();
|
||||
virtual const char* what() const throw();
|
||||
IfcException(std::string e);
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
typedef IfcParse::EntityPtr IfcEntity;
|
||||
typedef IfcParse::EntitiesPtr IfcEntities;
|
||||
typedef std::map<IfcSchema::Enum::IfcTypes,IfcEntities> MapEntitiesByType;
|
||||
typedef std::map<unsigned int,IfcEntity> MapEntityById;
|
||||
typedef std::map<unsigned int,IfcEntities> MapEntitiesByRef;
|
||||
typedef std::map<unsigned int,unsigned int> MapOffsetById;
|
||||
|
||||
float UnitPrefixToValue(const std::string& s);
|
||||
|
||||
//
|
||||
// Several static convenience functions and variables
|
||||
//
|
||||
class Ifc {
|
||||
private:
|
||||
static IfcParse::File* f;
|
||||
static MapEntitiesByType bytype;
|
||||
static MapEntityById byid;
|
||||
static MapEntitiesByRef byref;
|
||||
static MapOffsetById offsets;
|
||||
static unsigned int lastId;
|
||||
public:
|
||||
static IfcParse::File* file;
|
||||
static IfcParse::Tokens* tokens;
|
||||
static IfcEntities EntitiesByType(IfcSchema::Enum::IfcTypes t);
|
||||
static IfcEntities EntitiesByReference(int id);
|
||||
static IfcEntity EntityById(int id);
|
||||
@@ -193,4 +290,6 @@ public:
|
||||
static int CircleSegments;
|
||||
};
|
||||
|
||||
float UnitPrefixToValue(const std::string& s);
|
||||
|
||||
#endif
|
||||
|
||||
+80
-10
@@ -92,7 +92,7 @@ IFC_REF(BooleanClippingResult,First,1)
|
||||
IFC_REF(BooleanClippingResult,Second,2)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_CLASS(Face,TopoDS_Face)
|
||||
IFC_FACE_CLASS(Face)
|
||||
IFC_REFS(Face,Bounds,0)
|
||||
IFC_END_CLASS
|
||||
|
||||
@@ -181,7 +181,7 @@ IFC_FLT_SUB(CartesianPoint,Y,0,1)
|
||||
IFC_FLT_SUB(CartesianPoint,Z,0,2)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_CLASS(Direction,gp_Vec)
|
||||
IFC_CLASS(Direction,gp_Dir)
|
||||
IFC_FLT_SUB(Direction,X,0,0)
|
||||
IFC_FLT_SUB(Direction,Y,0,1)
|
||||
IFC_FLT_SUB(Direction,Z,0,2)
|
||||
@@ -288,11 +288,81 @@ IFC_END_CLASS
|
||||
IFC_HELPER_CLASS(OpeningElement)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_SKIP_CLASS(PropertySingleValue)
|
||||
IFC_SKIP_CLASS(PropertySet)
|
||||
IFC_SKIP_CLASS(ComplexProperty)
|
||||
IFC_SKIP_CLASS(RelDefinesByProperty)
|
||||
IFC_SKIP_CLASS(MaterialLayer)
|
||||
IFC_SKIP_CLASS(MaterialLayerSet)
|
||||
IFC_SKIP_CLASS(MaterialLayerSetUsage)
|
||||
IFC_SKIP_CLASS(PresentationLayerAssignment)
|
||||
|
||||
IFC_RENDER_CLASS(BuildingElementProxy)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Covering)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Beam)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Column)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(CurtainWall)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Door)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Member)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Railing)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Ramp)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(RampFlight)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Wall)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(WallStandardCase)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Slab)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(StairFlight)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Window)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Stair)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Roof)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Pile)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Footing)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(BuildingElementComponent)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Plate)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_RENDER_CLASS(IfcFlowFitting)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcFlowSegment)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcFlowController)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcFlowTerminal)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcFlowMovingDevice)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcEnergyConversionDevice)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcFlowStorageDevice)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcFlowTreatmentDevice)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(IfcDistributionChamberElement)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(DistributionControlElement)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_RENDER_CLASS(Site)
|
||||
IFC_END_CLASS
|
||||
IFC_RENDER_CLASS(Space)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_RENDER_CLASS(FurnishingElement)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_RENDER_CLASS(TransportElement)
|
||||
IFC_END_CLASS
|
||||
|
||||
IFC_RENDER_CLASS(GeographicElement) // 2x4 compatibility
|
||||
IFC_END_CLASS
|
||||
|
||||
@@ -28,22 +28,47 @@ using namespace IfcSchema;
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_PARSE_SOURCE
|
||||
|
||||
namespace IfcGeom {
|
||||
namespace Cache {
|
||||
std::map<int,TopoDS_Shape> Shape;
|
||||
std::map<int,TopoDS_Face> Face;
|
||||
std::map<int,TopoDS_Wire> Wire;
|
||||
std::map<int,Handle(Geom_Curve)> Curve;
|
||||
void PurgeShapeCache() {
|
||||
Shape.clear();
|
||||
Face.clear();
|
||||
Wire.clear();
|
||||
Curve.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IfcGeom::convert_shape(const IfcEntity L, TopoDS_Shape &result) {
|
||||
if ( ! L ) return false;
|
||||
bool r = false;
|
||||
std::map<int,TopoDS_Shape>::const_iterator it = Cache::Shape.find(L->id);
|
||||
if ( it != Cache::Shape.end() ) { result = it->second; r = true; /*std::cout << "Read #" << L->id << " from cache" << std::endl;*/}
|
||||
if ( false ) {}
|
||||
#define IFC_SHAPE_SRC
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_SHAPE_SRC
|
||||
std::cout << "[Error] Failed to interpret:" << std::endl << L->toString() << std::endl;
|
||||
return false;
|
||||
else std::cout << "[Error] Failed to interpret:" << std::endl << L->toString() << std::endl;
|
||||
if ( r ) Cache::Shape[L->id] = result;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert_wire(const IfcEntity L, TopoDS_Wire &result) {
|
||||
if ( ! L ) return false;
|
||||
bool r = false;
|
||||
std::map<int,TopoDS_Wire>::const_iterator it = Cache::Wire.find(L->id);
|
||||
if ( it != Cache::Wire.end() ) { result = it->second; r = true; /*std::cout << "Read #" << L->id << " from cache" << std::endl;*/}
|
||||
if ( false ) {}
|
||||
#define IFC_WIRE_SRC
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_WIRE_SRC
|
||||
std::cout << "[Error] Failed to interpret:" << std::endl << L->toString() << std::endl;
|
||||
return false;
|
||||
else std::cout << "[Error] Failed to interpret:" << std::endl << L->toString() << std::endl;
|
||||
if ( r ) Cache::Wire[L->id] = result;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool IfcGeom::convert_curve(const IfcEntity L, Handle(Geom_Curve) &result) {
|
||||
@@ -57,10 +82,14 @@ bool IfcGeom::convert_curve(const IfcEntity L, Handle(Geom_Curve) &result) {
|
||||
|
||||
bool IfcGeom::convert_face(const IfcEntity L, TopoDS_Face &result) {
|
||||
if ( ! L ) return false;
|
||||
TopoDS_Wire wire;
|
||||
bool r = false;
|
||||
std::map<int,TopoDS_Face>::const_iterator it = Cache::Face.find(L->id);
|
||||
if ( it != Cache::Face.end() ) { result = it->second; r = true; /*std::cout << "Read #" << L->id << " from cache" << std::endl;*/}
|
||||
if ( false ) {}
|
||||
#define IFC_FACE_SRC
|
||||
#include "../ifcparse/IfcSchema.h"
|
||||
#undef IFC_FACE_SRC
|
||||
std::cout << "[Error] Failed to interpret:" << std::endl << L->toString() << std::endl;
|
||||
return false;
|
||||
else std::cout << "[Error] Failed to interpret:" << std::endl << L->toString() << std::endl;
|
||||
if ( r ) Cache::Face[L->id] = result;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#include <gp_Trsf2d.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
|
||||
#include "../ifcparse/IfcParse.h"
|
||||
|
||||
@@ -47,6 +49,10 @@ namespace IfcGeom {
|
||||
bool convert_face(const IfcEntity L, TopoDS_Face& result);
|
||||
bool convert_openings(const IfcSchema::BuildingElement* IfcBuildingElement, const IfcEntities openings, TopoDS_Shape& result, const gp_Trsf& trsf);
|
||||
bool profile_helper(int numVerts, float* verts, int numFillets, int* filletIndices, float* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face);
|
||||
namespace Cache {
|
||||
void Purge();
|
||||
void PurgeShapeCache();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user