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
This commit is contained in:
Thomas Krijnen
2012-03-23 17:38:44 +00:00
parent df2bcecf96
commit a9bba39b9d
9 changed files with 96 additions and 51 deletions
+3 -1
View File
@@ -50,7 +50,9 @@
// Specifies the treshold distance under which cartesian points are deemed equal // Specifies the treshold distance under which cartesian points are deemed equal
#define POINT_EQUALITY_TOLERANCE 0.000001 #define POINT_EQUALITY_TOLERANCE 0.000001
#define FACESET_AS_COMPOUND 1 // Specifies maximum number of faces for a shell to be sewed. Sewing shells
// that consist of many faces is really detrimental for the performance.
#define MAX_FACES_TO_SEW 100
namespace IfcGeom { namespace IfcGeom {
bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face); bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face);
+3 -1
View File
@@ -25,7 +25,6 @@
#include <gp_GTrsf2d.hxx> #include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx> #include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx> #include <gp_Trsf2d.hxx>
#include <gp_Quaternion.hxx>
#include <TopoDS_Compound.hxx> #include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx> #include <BRep_Builder.hxx>
#include <BRepTools.hxx> #include <BRepTools.hxx>
@@ -522,6 +521,9 @@ void IfcGeomObjects::Settings(int setting, bool value) {
case USE_BREP_DATA: case USE_BREP_DATA:
use_brep_data = value; use_brep_data = value;
break; break;
case SEW_SHELLS:
Ifc::SewShells = value;
break;
} }
} }
int IfcGeomObjects::Progress() { int IfcGeomObjects::Progress() {
+29 -7
View File
@@ -38,9 +38,7 @@
* IfcGeomObject.matrix is a 4x3 matrix that defines the orientation and * * IfcGeomObject.matrix is a 4x3 matrix that defines the orientation and *
* translation of the mesh in relation to the world origin * * translation of the mesh in relation to the world origin *
* * * *
* Init(char* fn, bool world_coords) parses the IFC file in fn, returns true * * Init(char* fn) parses the IFC file in fn, returns true on succes. *
* 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 *
* * * *
@@ -69,13 +67,37 @@
namespace IfcGeomObjects { namespace IfcGeomObjects {
const int WELD_VERTICES = 1; // Enumeration of setting identifiers. These settings define the
const int USE_WORLD_COORDS = 2; // behaviour of various aspects of IfcOpenShell.
const int CONVERT_BACK_UNITS = 3;
const int USE_BREP_DATA = 4;
// Specifies whether vertices are welded, meaning that the coordinates
// vector will only contain unique xyz-triplets. This results in a
// manifold mesh which is useful for modelling applications, but might
// result in unwanted shading artifacts in rendering applications.
const int WELD_VERTICES = 1;
// Specifies whether to apply the local placements of building elements
// directly to the coordinates of the representation mesh rather than
// to represent the local placement in the 4x3 matrix, which will in that
// case be the identity matrix.
const int USE_WORLD_COORDS = 2;
// Internally IfcOpenShell measures everything in meters. This settings
// specifies whether to convert IfcGeomObjects back to the units in which
// the geometry in the IFC file is specified.
const int CONVERT_BACK_UNITS = 3;
// Specifies whether to use the Open Cascade BREP format for representation
// items rather than to create triangle meshes. This is useful is IfcOpenShell
// is used as a library in an application that is also built on Open Cascade.
const int USE_BREP_DATA = 4;
// Specifies whether to sew IfcConnectedFaceSets (open and closed shells) to
// TopoDS_Shells or whether to keep them as a loose collection of faces.
const int SEW_SHELLS = 5;
// End of settings enumeration.
// Some typedefs for convenience
typedef std::vector<int>::const_iterator IntIt; typedef std::vector<int>::const_iterator IntIt;
typedef std::vector<double>::const_iterator FltIt; typedef std::vector<double>::const_iterator FltIt;
// A nested pair of doubles to be able to store an XYZ coordinate in a map.
typedef std::pair< double,std::pair<double,double> > VertKey; typedef std::pair< double,std::pair<double,double> > VertKey;
typedef std::map<VertKey,int> VertKeyMap; typedef std::map<VertKey,int> VertKeyMap;
typedef std::pair<int,int> Edge; typedef std::pair<int,int> Edge;
+35 -33
View File
@@ -71,8 +71,6 @@
#include <ShapeFix_ShapeTolerance.hxx> #include <ShapeFix_ShapeTolerance.hxx>
#include <ShapeFix_Solid.hxx> #include <ShapeFix_Solid.hxx>
#include <BRepFilletAPI_MakeFillet2d.hxx>
#include <TopLoc_Location.hxx> #include <TopLoc_Location.hxx>
#include <BRepCheck_Analyzer.hxx> #include <BRepCheck_Analyzer.hxx>
@@ -293,41 +291,45 @@ bool IfcGeom::convert(const Ifc2x3::IfcBooleanClippingResult::ptr l, TopoDS_Shap
} }
bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) { bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& shape) {
#ifdef FACESET_AS_COMPOUND
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
#else
BRepOffsetAPI_Sewing builder;
builder.SetTolerance(0.01);
#endif
Ifc2x3::IfcFace::list faces = l->CfsFaces(); Ifc2x3::IfcFace::list faces = l->CfsFaces();
bool facesAdded = false; bool facesAdded = false;
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) { const unsigned int num_faces = faces->Size();
TopoDS_Face face; if ( Ifc::SewShells && num_faces < MAX_FACES_TO_SEW ) {
if ( IfcGeom::convert_face(*it,face) ) { BRepOffsetAPI_Sewing builder;
#ifdef FACESET_AS_COMPOUND builder.SetTolerance(0.01);
builder.Add(compound,face); for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
#else TopoDS_Face face;
builder.Add(face); if ( IfcGeom::convert_face(*it,face) ) {
#endif builder.Add(face);
facesAdded = true; facesAdded = true;
} else { } else {
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity); Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
}
} }
if ( ! facesAdded ) return false;
builder.Perform();
shape = builder.SewedShape();
try {
ShapeFix_Solid solid;
solid.LimitTolerance(0.01);
shape = solid.SolidFromShell(TopoDS::Shell(shape));
} catch(...) {}
} else {
TopoDS_Compound compound;
BRep_Builder builder;
builder.MakeCompound(compound);
for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) {
TopoDS_Face face;
if ( IfcGeom::convert_face(*it,face) ) {
builder.Add(compound,face);
facesAdded = true;
} else {
Ifc::LogMessage("Warning","Invalid face:",(*it)->entity);
}
}
if ( ! facesAdded ) return false;
shape = compound;
} }
if ( ! facesAdded ) return false;
#ifdef FACESET_AS_COMPOUND
shape = compound;
#else
builder.Perform();
shape = builder.SewedShape();
try {
ShapeFix_Solid solid;
solid.LimitTolerance(0.01);
shape = solid.SolidFromShell(TopoDS::Shell(shape));
} catch(...) {}
#endif
return true; return true;
} }
bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, ShapeList& shapes) { bool IfcGeom::convert(const Ifc2x3::IfcMappedItem::ptr l, ShapeList& shapes) {
+22 -9
View File
@@ -24,6 +24,7 @@
#include "../ifcmax/IfcMax.h" #include "../ifcmax/IfcMax.h"
#include "../ifcmax/MaxMaterials.h" #include "../ifcmax/MaxMaterials.h"
#include "../ifcgeom/IfcGeomObjects.h" #include "../ifcgeom/IfcGeomObjects.h"
int controlsInit = false; int controlsInit = false;
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) { BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) {
@@ -106,10 +107,11 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false); IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,false);
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true); IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,true);
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
if ( ! IfcGeomObjects::Init((char*)name,0,0) ) return false; if ( ! IfcGeomObjects::Init((char*)name,0,0) ) return false;
std::map<int, TriObject*> dict; //std::map<int, TriObject*> dict;
MtlBaseLib* mats = itfc->GetSceneMtls(); MtlBaseLib* mats = itfc->GetSceneMtls();
int slot = mats->Count(); int slot = mats->Count();
@@ -129,10 +131,14 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
m = static_cast<Mtl*>((*mats)[matIndex]); m = static_cast<Mtl*>((*mats)[matIndex]);
} }
std::map<int, TriObject*>::const_iterator it = dict.find(o->mesh->id); // This mapping is useless for now, because this even in case
// meshes entities in IFC share the same representation elements
// they will never be given the same id.
// TODO: Fix this!
// std::map<int, TriObject*>::const_iterator it = dict.find(o->mesh->id);
TriObject* tri; TriObject* tri;
if ( it == dict.end() ) { // if ( it == dict.end() ) {
tri = CreateNewTriObject(); tri = CreateNewTriObject();
const int numVerts = o->mesh->verts.size()/3; const int numVerts = o->mesh->verts.size()/3;
tri->mesh.setNumVerts(numVerts); tri->mesh.setNumVerts(numVerts);
@@ -145,14 +151,21 @@ int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc,
tri->mesh.faces[i].setVerts(o->mesh->faces[3*i+0],o->mesh->faces[3*i+1],o->mesh->faces[3*i+2]); tri->mesh.faces[i].setVerts(o->mesh->faces[3*i+0],o->mesh->faces[3*i+1],o->mesh->faces[3*i+2]);
tri->mesh.faces[i].setEdgeVisFlags(o->mesh->edges[3*i+0],o->mesh->edges[3*i+1],o->mesh->edges[3*i+2]); tri->mesh.faces[i].setEdgeVisFlags(o->mesh->edges[3*i+0],o->mesh->edges[3*i+1],o->mesh->edges[3*i+2]);
} }
tri->mesh.InvalidateTopologyCache();
tri->mesh.InvalidateGeomCache();
tri->mesh.buildNormals(); tri->mesh.buildNormals();
// Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have
// properly oriented normals. Using only the line below will result in a consistent
// orientation of normals accross shells, but not always oriented towards the
// outside.
// tri->mesh.UnifyNormals(false);
tri->mesh.BuildStripsAndEdges(); tri->mesh.BuildStripsAndEdges();
dict[o->mesh->id] = tri; tri->mesh.InvalidateTopologyCache();
} else { tri->mesh.InvalidateGeomCache();
tri = (*it).second;
} // dict[o->mesh->id] = tri;
// } else {
// tri = (*it).second;
// }
ImpNode* node = impitfc->CreateNode(); ImpNode* node = impitfc->CreateNode();
node->Reference(tri); node->Reference(tri);
+1
View File
@@ -49,6 +49,7 @@ int main ( int argc, char** argv ) {
IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,true); IfcGeomObjects::Settings(IfcGeomObjects::USE_WORLD_COORDS,true);
IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,false); IfcGeomObjects::Settings(IfcGeomObjects::WELD_VERTICES,false);
IfcGeomObjects::Settings(IfcGeomObjects::SEW_SHELLS,true);
// Stream for log messages, we don't want to interupt our new progress bar... // Stream for log messages, we don't want to interupt our new progress bar...
std::stringstream ss; std::stringstream ss;
+1
View File
@@ -822,6 +822,7 @@ Tokens* Ifc::tokens = 0;
double Ifc::LengthUnit = 1.0f; double Ifc::LengthUnit = 1.0f;
double Ifc::PlaneAngleUnit = 1.0f; double Ifc::PlaneAngleUnit = 1.0f;
bool Ifc::hasPlaneAngleUnit = false; bool Ifc::hasPlaneAngleUnit = false;
bool Ifc::SewShells = false;
int Ifc::CircleSegments = 32; int Ifc::CircleSegments = 32;
MapEntitiesByType Ifc::bytype; MapEntitiesByType Ifc::bytype;
MapEntityById Ifc::byid; MapEntityById Ifc::byid;
+1
View File
@@ -268,6 +268,7 @@ public:
static std::string GetLog(); static std::string GetLog();
static void Dispose(); static void Dispose();
static bool hasPlaneAngleUnit; static bool hasPlaneAngleUnit;
static bool SewShells;
static double LengthUnit; static double LengthUnit;
static double PlaneAngleUnit; static double PlaneAngleUnit;
static int CircleSegments; static int CircleSegments;
+1
View File
@@ -23,6 +23,7 @@ namespace IfcGeomObjects {
const int USE_WORLD_COORDS = 2; const int USE_WORLD_COORDS = 2;
const int CONVERT_BACK_UNITS = 3; const int CONVERT_BACK_UNITS = 3;
const int USE_BREP_DATA = 4; const int USE_BREP_DATA = 4;
const int SEW_SHELLS = 5;
class IfcMesh { class IfcMesh {
public: public: