Skip to content

Commit a9bba39

Browse files
committed
Applied Patch #3509752 by mv2ax
Made the sewing of TopoDS_Shells into a IfcGeomObjects::Setting Limit the maximum number of faces a shell to be sewed
1 parent df2bcec commit a9bba39

File tree

9 files changed

+92
-47
lines changed

9 files changed

+92
-47
lines changed

src/ifcgeom/IfcGeom.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
// Specifies the treshold distance under which cartesian points are deemed equal
5151
#define POINT_EQUALITY_TOLERANCE 0.000001
5252

53-
#define FACESET_AS_COMPOUND 1
53+
// Specifies maximum number of faces for a shell to be sewed. Sewing shells
54+
// that consist of many faces is really detrimental for the performance.
55+
#define MAX_FACES_TO_SEW 100
5456

5557
namespace IfcGeom {
5658
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);

src/ifcgeom/IfcGeomObjects.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include <gp_GTrsf2d.hxx>
2626
#include <gp_Trsf.hxx>
2727
#include <gp_Trsf2d.hxx>
28-
#include <gp_Quaternion.hxx>
2928
#include <TopoDS_Compound.hxx>
3029
#include <BRep_Builder.hxx>
3130
#include <BRepTools.hxx>
@@ -522,6 +521,9 @@ void IfcGeomObjects::Settings(int setting, bool value) {
522521
case USE_BREP_DATA:
523522
use_brep_data = value;
524523
break;
524+
case SEW_SHELLS:
525+
Ifc::SewShells = value;
526+
break;
525527
}
526528
}
527529
int IfcGeomObjects::Progress() {

src/ifcgeom/IfcGeomObjects.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@
3838
* IfcGeomObject.matrix is a 4x3 matrix that defines the orientation and *
3939
* translation of the mesh in relation to the world origin *
4040
* *
41-
* Init(char* fn, bool world_coords) parses the IFC file in fn, returns true *
42-
* on succes, world_coords = true will result in all IfcGeomObject.matrix *
43-
* being an identity matrix and IfcMesh.verts containing global positions *
41+
* Init(char* fn) parses the IFC file in fn, returns true on succes. *
4442
* *
4543
* Get() returns a pointer to the current IfcGeomObject *
4644
* *
@@ -69,13 +67,37 @@
6967

7068
namespace IfcGeomObjects {
7169

70+
// Enumeration of setting identifiers. These settings define the
71+
// behaviour of various aspects of IfcOpenShell.
72+
73+
// Specifies whether vertices are welded, meaning that the coordinates
74+
// vector will only contain unique xyz-triplets. This results in a
75+
// manifold mesh which is useful for modelling applications, but might
76+
// result in unwanted shading artifacts in rendering applications.
7277
const int WELD_VERTICES = 1;
78+
// Specifies whether to apply the local placements of building elements
79+
// directly to the coordinates of the representation mesh rather than
80+
// to represent the local placement in the 4x3 matrix, which will in that
81+
// case be the identity matrix.
7382
const int USE_WORLD_COORDS = 2;
83+
// Internally IfcOpenShell measures everything in meters. This settings
84+
// specifies whether to convert IfcGeomObjects back to the units in which
85+
// the geometry in the IFC file is specified.
7486
const int CONVERT_BACK_UNITS = 3;
87+
// Specifies whether to use the Open Cascade BREP format for representation
88+
// items rather than to create triangle meshes. This is useful is IfcOpenShell
89+
// is used as a library in an application that is also built on Open Cascade.
7590
const int USE_BREP_DATA = 4;
91+
// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
92+
// TopoDS_Shells or whether to keep them as a loose collection of faces.
93+
const int SEW_SHELLS = 5;
94+
95+
// End of settings enumeration.
7696

97+
// Some typedefs for convenience
7798
typedef std::vector<int>::const_iterator IntIt;
7899
typedef std::vector<double>::const_iterator FltIt;
100+
// A nested pair of doubles to be able to store an XYZ coordinate in a map.
79101
typedef std::pair< double,std::pair<double,double> > VertKey;
80102
typedef std::map<VertKey,int> VertKeyMap;
81103
typedef std::pair<int,int> Edge;

src/ifcgeom/IfcGeomShapes.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@
7171
#include <ShapeFix_ShapeTolerance.hxx>
7272
#include <ShapeFix_Solid.hxx>
7373

74-
#include <BRepFilletAPI_MakeFillet2d.hxx>
75-
7674
#include <TopLoc_Location.hxx>
7775

7876
#include <BRepCheck_Analyzer.hxx>
@@ -293,41 +291,45 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
293291

294292
}
295293
bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
296-
#ifdef FACESET_AS_COMPOUND
297-
TopoDS_Compound compound;
298-
BRep_Builder builder;
299-
builder.MakeCompound(compound);
300-
#else
301-
BRepOffsetAPI_Sewing builder;
302-
builder.SetTolerance(0.01);
303-
#endif
304294
Ifc2x3::IfcFace::list faces = l->CfsFaces();
305295
bool facesAdded = false;
306-
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
307-
TopoDS_Face face;
308-
if ( IfcGeom::convert_face(*it,face) ) {
309-
#ifdef FACESET_AS_COMPOUND
310-
builder.Add(compound,face);
311-
#else
312-
builder.Add(face);
313-
#endif
314-
facesAdded = true;
315-
} else {
316-
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
296+
const unsigned int num_faces = faces->Size();
297+
if ( Ifc::SewShells && num_faces < MAX_FACES_TO_SEW ) {
298+
BRepOffsetAPI_Sewing builder;
299+
builder.SetTolerance(0.01);
300+
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
301+
TopoDS_Face face;
302+
if ( IfcGeom::convert_face(*it,face) ) {
303+
builder.Add(face);
304+
facesAdded = true;
305+
} else {
306+
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
307+
}
308+
}
309+
if ( ! facesAdded ) return false;
310+
builder.Perform();
311+
shape = builder.SewedShape();
312+
try {
313+
ShapeFix_Solid solid;
314+
solid.LimitTolerance(0.01);
315+
shape = solid.SolidFromShell(TopoDS::Shell(shape));
316+
} catch(...) {}
317+
} else {
318+
TopoDS_Compound compound;
319+
BRep_Builder builder;
320+
builder.MakeCompound(compound);
321+
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
322+
TopoDS_Face face;
323+
if ( IfcGeom::convert_face(*it,face) ) {
324+
builder.Add(compound,face);
325+
facesAdded = true;
326+
} else {
327+
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
328+
}
317329
}
330+
if ( ! facesAdded ) return false;
331+
shape = compound;
318332
}
319-
if ( ! facesAdded ) return false;
320-
#ifdef FACESET_AS_COMPOUND
321-
shape = compound;
322-
#else
323-
builder.Perform();
324-
shape = builder.SewedShape();
325-
try {
326-
ShapeFix_Solid solid;
327-
solid.LimitTolerance(0.01);
328-
shape = solid.SolidFromShell(TopoDS::Shell(shape));
329-
} catch(...) {}
330-
#endif
331333
return true;
332334
}
333335
bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, ShapeList& shapes) {

src/ifcmax/IfcMax.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "../ifcmax/IfcMax.h"
2525
#include "../ifcmax/MaxMaterials.h"
2626
#include "../ifcgeom/IfcGeomObjects.h"
27+
2728
int controlsInit = false;
2829

2930
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) {
@@ -106,10 +107,11 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
106107

107108
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false);
108109
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true);
110+
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
109111

110112
if ( ! IfcGeomObjects::Init((char*)name,0,0) ) return false;
111113

112-
std::map<int, TriObject*> dict;
114+
//std::map<int, TriObject*> dict;
113115
MtlBaseLib* mats = itfc->GetSceneMtls();
114116
int slot = mats->Count();
115117

@@ -129,10 +131,14 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
129131
m = static_cast<Mtl*>((*mats)[matIndex]);
130132
}
131133

132-
std::map<int, TriObject*>::const_iterator it = dict.find(o->mesh->id);
134+
// This mapping is useless for now, because this even in case
135+
// meshes entities in IFC share the same representation elements
136+
// they will never be given the same id.
137+
// TODO: Fix this!
138+
// std::map<int, TriObject*>::const_iterator it = dict.find(o->mesh->id);
133139

134140
TriObject* tri;
135-
if ( it == dict.end() ) {
141+
// if ( it == dict.end() ) {
136142
tri = CreateNewTriObject();
137143
const int numVerts = o->mesh->verts.size()/3;
138144
tri->mesh.setNumVerts(numVerts);
@@ -145,14 +151,21 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
145151
tri->mesh.faces[i].setVerts(o->mesh->faces[3*i+0],o->mesh->faces[3*i+1],o->mesh->faces[3*i+2]);
146152
tri->mesh.faces[i].setEdgeVisFlags(o->mesh->edges[3*i+0],o->mesh->edges[3*i+1],o->mesh->edges[3*i+2]);
147153
}
148-
tri->mesh.InvalidateTopologyCache();
149-
tri->mesh.InvalidateGeomCache();
154+
150155
tri->mesh.buildNormals();
156+
// Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have
157+
// properly oriented normals. Using only the line below will result in a consistent
158+
// orientation of normals accross shells, but not always oriented towards the
159+
// outside.
160+
// tri->mesh.UnifyNormals(false);
151161
tri->mesh.BuildStripsAndEdges();
152-
dict[o->mesh->id] = tri;
153-
} else {
154-
tri = (*it).second;
155-
}
162+
tri->mesh.InvalidateTopologyCache();
163+
tri->mesh.InvalidateGeomCache();
164+
165+
// dict[o->mesh->id] = tri;
166+
// } else {
167+
// tri = (*it).second;
168+
// }
156169

157170
ImpNode* node = impitfc->CreateNode();
158171
node->Reference(tri);

src/ifcobj/IfcObj.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ int main ( int argc, char** argv ) {
4949

5050
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,true);
5151
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,false);
52+
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
5253

5354
// Stream for log messages, we don't want to interupt our new progress bar...
5455
std::stringstream ss;

src/ifcparse/IfcParse.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ Tokens* Ifc::tokens = 0;
822822
double Ifc::LengthUnit = 1.0f;
823823
double Ifc::PlaneAngleUnit = 1.0f;
824824
bool Ifc::hasPlaneAngleUnit = false;
825+
bool Ifc::SewShells = false;
825826
int Ifc::CircleSegments = 32;
826827
MapEntitiesByType Ifc::bytype;
827828
MapEntityById Ifc::byid;

src/ifcparse/IfcParse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ class Ifc {
268268
static std::string GetLog();
269269
static void Dispose();
270270
static bool hasPlaneAngleUnit;
271+
static bool SewShells;
271272
static double LengthUnit;
272273
static double PlaneAngleUnit;
273274
static int CircleSegments;

src/ifcwrap/Interface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace IfcGeomObjects {
2323
const int USE_WORLD_COORDS = 2;
2424
const int CONVERT_BACK_UNITS = 3;
2525
const int USE_BREP_DATA = 4;
26+
const int SEW_SHELLS = 5;
2627

2728
class IfcMesh {
2829
public:

0 commit comments

Comments
 (0)