diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index d5d43a7975..73d730d98b 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -42,21 +42,23 @@ #include "../ifcgeom/IfcShapeList.h" -// Tolerances for various geometrical operations: -// Specifies the deflection of the mesher -#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.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. -#define MAX_FACES_TO_SEW 1000 - namespace IfcGeom { + + // Tolerances and settings for various geometrical operations: + enum GeomValue { + // Specifies the deflection of the mesher + GV_DEFLECTION_TOLERANCE, + // Specifies the tolerance of the wire builder, most notably for trimmed curves + GV_WIRE_CREATION_TOLERANCE, + // Specifies the minimal area of a face to be included in an IfcConnectedFaceset + GV_MINIMAL_FACE_AREA, + // Specifies the treshold distance under which cartesian points are deemed equal + GV_POINT_EQUALITY_TOLERANCE, + // Specifies maximum number of faces for a shell to be sewed. Sewing shells + // that consist of many faces is really detrimental for the performance. + GV_MAX_FACES_TO_SEW + }; + bool convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face); bool convert_shapes(const IfcUtil::IfcBaseClass* L, ShapeList& result); bool is_shape_collection(const IfcUtil::IfcBaseClass* L); @@ -76,6 +78,9 @@ namespace IfcGeom { 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); + void SetValue(GeomValue var, double value); + double GetValue(GeomValue var); + namespace Cache { void Purge(); void PurgeShapeCache(); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index c750f42db8..0f5c264524 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -23,6 +23,8 @@ * * ********************************************************************************/ +#include + #include #include #include @@ -88,9 +90,9 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) { BRepOffsetAPI_Sewing builder; - builder.SetTolerance(POINT_EQUALITY_TOLERANCE); - builder.SetMaxTolerance(POINT_EQUALITY_TOLERANCE); - builder.SetMinTolerance(POINT_EQUALITY_TOLERANCE); + builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); TopExp_Explorer exp(compound,TopAbs_FACE); if ( ! exp.More() ) return false; for ( ; exp.More(); exp.Next() ) { @@ -101,7 +103,7 @@ bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Sh shape = builder.SewedShape(); try { ShapeFix_Solid sf_solid; - sf_solid.LimitTolerance(POINT_EQUALITY_TOLERANCE); + sf_solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); shape = sf_solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} return true; @@ -369,8 +371,8 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) { edge_points.push_back(P2); } if ( edge_points.size() != 2 ) continue; - if ( edge_points[0].IsEqual(P1,POINT_EQUALITY_TOLERANCE)) neighbors.push_back(edge_points[1]); - else if ( edge_points[1].IsEqual(P1,POINT_EQUALITY_TOLERANCE)) neighbors.push_back(edge_points[0]); + if ( edge_points[0].IsEqual(P1,GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[1]); + else if ( edge_points[1].IsEqual(P1, GetValue(GV_POINT_EQUALITY_TOLERANCE))) neighbors.push_back(edge_points[0]); } // There should be two of these if ( neighbors.size() != 2 ) return false; @@ -379,10 +381,10 @@ bool IfcGeom::is_convex(const TopoDS_Wire& wire) { for ( TopExp_Explorer exp2(wire,TopAbs_VERTEX); exp2.More(); exp2.Next() ) { TopoDS_Vertex V2 = TopoDS::Vertex(exp2.Current()); gp_Pnt P2 = BRep_Tool::Pnt(V2); - if ( P1.IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) continue; + if ( P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) continue; bool found = false; for( std::vector::const_iterator it = neighbors.begin(); it != neighbors.end(); ++ it ) { - if ( (*it).IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) { found = true; break; } + if ( (*it).IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) { found = true; break; } } if ( ! found ) non_neighbors.push_back(P2); } @@ -421,4 +423,43 @@ gp_Pnt IfcGeom::point_above_plane(const gp_Pln& pln, bool agree) { } else { return pln.Location().Translated(-pln.Axis().Direction()); } +} + +static double deflection_tolerance = 0.001; +static double wire_creation_tolerance = 0.0001; +static double minimal_face_area = 0.000001; +static double point_equality_tolerance = 0.00001; +static double max_faces_to_sew = 1000; + +void IfcGeom::SetValue(GeomValue var, double value) { + switch (var) { + case GV_DEFLECTION_TOLERANCE: + deflection_tolerance = value; + case GV_WIRE_CREATION_TOLERANCE: + wire_creation_tolerance = value; + case GV_MINIMAL_FACE_AREA: + minimal_face_area = value; + case GV_POINT_EQUALITY_TOLERANCE: + point_equality_tolerance = value; + case GV_MAX_FACES_TO_SEW: + max_faces_to_sew = value; + } + assert(!"never reach here"); +} + +double IfcGeom::GetValue(GeomValue var) { + switch (var) { + case GV_DEFLECTION_TOLERANCE: + return deflection_tolerance; + case GV_WIRE_CREATION_TOLERANCE: + return wire_creation_tolerance; + case GV_MINIMAL_FACE_AREA: + return minimal_face_area; + case GV_POINT_EQUALITY_TOLERANCE: + return point_equality_tolerance; + case GV_MAX_FACES_TO_SEW: + return max_faces_to_sew; + } + assert(!"never reach here"); + return 0; } \ No newline at end of file diff --git a/src/ifcgeom/IfcGeomObjects.cpp b/src/ifcgeom/IfcGeomObjects.cpp index 4867e97b20..51d6ec819d 100644 --- a/src/ifcgeom/IfcGeomObjects.cpp +++ b/src/ifcgeom/IfcGeomObjects.cpp @@ -103,7 +103,7 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) { // Triangulate the shape try { //BRepTools::Clean(s); - BRepMesh::Mesh(s,DEFLECTION_TOLERANCE); + BRepMesh::Mesh(s, IfcGeom::GetValue(IfcGeom::GV_DEFLECTION_TOLERANCE)); } catch(...) { Ifc::LogMessage("Error","Failed to triangulate mesh:",Ifc::EntityById(i)->entity); continue; diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 8a66e40bc3..ef4943ecc8 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -294,14 +294,14 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh Ifc2x3::IfcFace::list faces = l->CfsFaces(); bool facesAdded = false; const unsigned int num_faces = faces->Size(); - if ( Ifc::SewShells && num_faces < MAX_FACES_TO_SEW ) { + if ( Ifc::SewShells && num_faces < GetValue(GV_MAX_FACES_TO_SEW) ) { BRepOffsetAPI_Sewing builder; - builder.SetTolerance(POINT_EQUALITY_TOLERANCE); - builder.SetMaxTolerance(POINT_EQUALITY_TOLERANCE); - builder.SetMinTolerance(POINT_EQUALITY_TOLERANCE); + builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); + builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); for( Ifc2x3::IfcFace::it it = faces->begin(); it != faces->end(); ++ it ) { TopoDS_Face face; - if ( IfcGeom::convert_face(*it,face) && face_area(face) > MINIMAL_FACE_AREA ) { + if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) { builder.Add(face); facesAdded = true; } else { @@ -313,7 +313,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcConnectedFaceSet::ptr l, TopoDS_Shape& sh shape = builder.SewedShape(); try { ShapeFix_Solid solid; - solid.LimitTolerance(POINT_EQUALITY_TOLERANCE); + solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE)); shape = solid.SolidFromShell(TopoDS::Shell(shape)); } catch(...) {} } else { @@ -322,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) && face_area(face) > MINIMAL_FACE_AREA ) { + if ( IfcGeom::convert_face(*it,face) && face_area(face) > GetValue(GV_MINIMAL_FACE_AREA) ) { builder.Add(compound,face); facesAdded = true; } else { diff --git a/src/ifcgeom/IfcGeomWires.cpp b/src/ifcgeom/IfcGeomWires.cpp index 53243bc65d..e9206a72bd 100644 --- a/src/ifcgeom/IfcGeomWires.cpp +++ b/src/ifcgeom/IfcGeomWires.cpp @@ -117,7 +117,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcCompositeCurve::ptr l, TopoDS_Wire& wire) } if ( ! (*it)->SameSense() ) wire2.Reverse(); ShapeFix_ShapeTolerance FTol; - FTol.SetTolerance(wire2, WIRE_CREATION_TOLERANCE, TopAbs_WIRE); + FTol.SetTolerance(wire2, GetValue(GV_WIRE_CREATION_TOLERANCE), TopAbs_WIRE); /*if ( it != segments->begin() ) { TopExp_Explorer exp (wire2,TopAbs_VERTEX); const TopoDS_Vertex& first_vertex = TopoDS::Vertex(exp.Current()); @@ -204,7 +204,7 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyline::ptr l, TopoDS_Wire& result) { gp_Pnt P1;gp_Pnt P2; for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) { IfcGeom::convert(*it,P2); - if ( it != points->begin() && ( !P1.IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) ) + if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) w.Add(BRepBuilderAPI_MakeEdge(P1,P2)); P1 = P2; } @@ -220,13 +220,13 @@ bool IfcGeom::convert(const Ifc2x3::IfcPolyLoop::ptr l, TopoDS_Wire& result) { int count = 0; for( Ifc2x3::IfcCartesianPoint::it it = points->begin(); it != points->end(); ++ it ) { IfcGeom::convert(*it,P2); - if ( it != points->begin() && ( !P1.IsEqual(P2,POINT_EQUALITY_TOLERANCE) ) ) { + if ( it != points->begin() && ( !P1.IsEqual(P2,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) ) { w.Add(BRepBuilderAPI_MakeEdge(P1,P2)); count ++; } else if ( ! count ) F = P2; P1 = P2; } - if ( !P1.IsEqual(F,POINT_EQUALITY_TOLERANCE) ) { + if ( !P1.IsEqual(F,GetValue(GV_POINT_EQUALITY_TOLERANCE)) ) { w.Add(BRepBuilderAPI_MakeEdge(P1,F)); count ++; }