diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index a5781fea18..60d432dadc 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -47,8 +47,10 @@ #define DEFLECTION_TOLERANCE 0.001 // Specifies the tolerance of the wire builder, most notably for trimmed curves #define WIRE_CREATION_TOLERANCE 0.0001 +// Specifies the minimal area of a face to be included in an IfcConnectedFaceset +#define MINIMAL_FACE_AREA 0.000001 // Specifies the treshold distance under which cartesian points are deemed equal -#define POINT_EQUALITY_TOLERANCE 0.0000001 +#define POINT_EQUALITY_TOLERANCE 0.00001 // Specifies maximum number of faces for a shell to be sewed. Sewing shells // that consist of many faces is really detrimental for the performance. @@ -72,6 +74,7 @@ namespace IfcGeom { const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid); bool profile_helper(int numVerts, double* verts, int numFillets, int* filletIndices, double* filletRadii, gp_Trsf2d trsf, TopoDS_Face& face); double shape_volume(const TopoDS_Shape& s); + double face_area(const TopoDS_Face& f); namespace Cache { void Purge(); void PurgeShapeCache(); diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp index ee00f59a90..94369ccb8f 100644 --- a/src/ifcgeom/IfcGeomFaces.cpp +++ b/src/ifcgeom/IfcGeomFaces.cpp @@ -73,8 +73,6 @@ #include #include -#include - #include #include "../ifcgeom/IfcGeom.h" @@ -97,28 +95,33 @@ bool IfcGeom::convert(const Ifc2x3::IfcFace::ptr l, TopoDS_Face& face) { if ( er != BRepBuilderAPI_FaceDone ) return false; if ( bounds->Size() == 1 ) { face = mf.Face(); - return true; - } - for( ++it; it != bounds->end(); ++ it) { - Ifc2x3::IfcLoop::ptr loop = (*it)->Bound(); - TopoDS_Wire wire; - if ( ! IfcGeom::convert_wire(loop,wire) ) return false; - mf.Add(wire); - } - if ( mf.IsDone() ) { - ShapeFix_Shape sfs(mf.Face()); - sfs.Perform(); - TopoDS_Shape sfs_shape = sfs.Shape(); - bool is_face = sfs_shape.ShapeType() == TopAbs_FACE; - if ( is_face ) { - face = TopoDS::Face(sfs_shape); - return true; + } else { + for( ++it; it != bounds->end(); ++ it) { + Ifc2x3::IfcLoop::ptr loop = (*it)->Bound(); + TopoDS_Wire wire; + if ( ! IfcGeom::convert_wire(loop,wire) ) return false; + mf.Add(wire); + } + if ( mf.IsDone() ) { + ShapeFix_Shape sfs(mf.Face()); + sfs.Perform(); + TopoDS_Shape sfs_shape = sfs.Shape(); + bool is_face = sfs_shape.ShapeType() == TopAbs_FACE; + if ( is_face ) { + face = TopoDS::Face(sfs_shape); + } else { + return false; + } } else { return false; } - } else { - return false; } + // It might be a good idea to globally discard faces + // smaller than a certain treshold value. But for now + // only when processing IfcConnectedFacesets the small + // faces are skipped. + // return face_area(face) > 0.0001; + return true; } bool IfcGeom::convert(const Ifc2x3::IfcArbitraryClosedProfileDef::ptr l, TopoDS_Face& face) { TopoDS_Wire wire; diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 915e83c8c4..660c492bfc 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -88,7 +88,9 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { BRepOffsetAPI_Sewing builder; - builder.SetTolerance(0.01); + builder.SetTolerance(POINT_EQUALITY_TOLERANCE); + builder.SetMaxTolerance(POINT_EQUALITY_TOLERANCE); + builder.SetMinTolerance(POINT_EQUALITY_TOLERANCE); TopExp_Explorer exp(compound,TopAbs_FACE); if ( ! exp.More() ) return false; for ( ; exp.More(); exp.Next() ) { @@ -99,7 +101,7 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Sh shape = builder.SewedShape(); try { ShapeFix_Solid sf_solid; - sf_solid.LimitTolerance(0.01); + sf_solid.LimitTolerance(POINT_EQUALITY_TOLERANCE); shape = sf_solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} return true; @@ -259,9 +261,14 @@ bool IfcGeom::profile_helper(int numVerts, double* verts, int numFillets, int* f return true; } double IfcGeom::shape_volume(const TopoDS_Shape& s) { - GProp_GProps System; - BRepGProp::VolumeProperties(s, System); - return (double) System.Mass(); + GProp_GProps prop; + BRepGProp::VolumeProperties(s, prop); + return prop.Mass(); +} +double IfcGeom::face_area(const TopoDS_Face& f) { + GProp_GProps prop; + BRepGProp::SurfaceProperties(f,prop); + return prop.Mass(); } bool IfcGeom::is_convex(const TopoDS_Wire& wire) { for ( TopExp_Explorer exp1(wire,TopAbs_VERTEX); exp1.More(); exp1.Next() ) { diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 0fe2105cae..8a66e40bc3 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -296,10 +296,12 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh const unsigned int num_faces = faces->Size(); if ( Ifc::SewShells && num_faces < MAX_FACES_TO_SEW ) { BRepOffsetAPI_Sewing builder; - builder.SetTolerance(0.01); + builder.SetTolerance(POINT_EQUALITY_TOLERANCE); + builder.SetMaxTolerance(POINT_EQUALITY_TOLERANCE); + builder.SetMinTolerance(POINT_EQUALITY_TOLERANCE); for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) { TopoDS_Face face; - if ( IfcGeom::convert_face(*it,face) ) { + if ( IfcGeom::convert_face(*it,face) && face_area(face) > MINIMAL_FACE_AREA ) { builder.Add(face); facesAdded = true; } else { @@ -311,7 +313,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh shape = builder.SewedShape(); try { ShapeFix_Solid solid; - solid.LimitTolerance(0.01); + solid.LimitTolerance(POINT_EQUALITY_TOLERANCE); shape = solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} } else { @@ -320,7 +322,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh builder.MakeCompound(compound); for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) { TopoDS_Face face; - if ( IfcGeom::convert_face(*it,face) ) { + if ( IfcGeom::convert_face(*it,face) && face_area(face) > MINIMAL_FACE_AREA ) { builder.Add(compound,face); facesAdded = true; } else {