From 901e805d244a289fbfb33adb1d9db2853b12c6c9 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Fri, 24 May 2019 14:29:21 +0200 Subject: [PATCH] Revert 13d2cf33575b13382efb574f0d6c879095bcdbca --- src/ifcconvert/IfcConvert.cpp | 8 +++++++ src/ifcgeom/IfcGeom.h | 11 +++------ src/ifcgeom/IfcGeomFunctions.cpp | 26 +++++++-------------- src/ifcgeom/IfcGeomIteratorImplementation.h | 1 + src/ifcgeom/IfcGeomShapes.cpp | 14 +++++++---- src/ifcgeom/IfcGeomTree.h | 1 + src/ifcgeom_schema_agnostic/Kernel.h | 8 +++---- src/ifcwrap/IfcGeomWrapper.i | 1 + 8 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index a1397023bf..31f195c200 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -242,6 +242,11 @@ int main(int argc, char** argv) { "Specifies whether to convert back geometrical output back to the " "unit of measure in which it is defined in the IFC file. Default is " "to use meters.") + ("orient-shells", + "Specifies whether to orient the faces of IfcConnectedFaceSets. " + "This is a potentially time consuming operation, but guarantees a " + "consistent orientation of surface normals, even if the faces are not " + "properly oriented in the IFC file.") #if OCC_VERSION_HEX < 0x60900 // In Open CASCADE version prior to 6.9.0 boolean operations with multiple // arguments where not introduced yet and a work-around was implemented to @@ -386,6 +391,7 @@ int main(int argc, char** argv) { const bool weld_vertices = vmap.count("weld-vertices") != 0; const bool use_world_coords = vmap.count("use-world-coords") != 0; const bool convert_back_units = vmap.count("convert-back-units") != 0; + const bool orient_shells = vmap.count("orient-shells") != 0; #if OCC_VERSION_HEX < 0x60900 const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0; #endif @@ -622,6 +628,7 @@ int main(int argc, char** argv) { settings.set(IfcGeom::IteratorSettings::APPLY_DEFAULT_MATERIALS, true); settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, use_world_coords || output_extension == SVG || output_extension == OBJ); settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, weld_vertices); + settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, orient_shells); settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units); #if OCC_VERSION_HEX < 0x60900 settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands); @@ -1188,6 +1195,7 @@ void fix_quantities(IfcParse::IfcFile& f, bool no_progress, bool quiet, bool std IfcGeom::IteratorSettings settings; settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, false); settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, false); + settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, true); settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, true); settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true); diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 7d4318fd90..c563da8049 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -209,13 +209,11 @@ private: }; double deflection_tolerance; - double wire_creation_tolerance; - double point_equality_tolerance; - double max_faces_to_sew; double ifc_length_unit; double ifc_planeangle_unit; double modelling_precision; double dimensionality; + double max_faces_to_orient; #ifndef NO_CACHE MAKE_TYPE_NAME(Cache) cache; @@ -234,9 +232,7 @@ public: MAKE_TYPE_NAME(Kernel)() : IfcGeom::Kernel(0) , deflection_tolerance(0.001) - , wire_creation_tolerance(0.0001) - , point_equality_tolerance(0.00001) - , max_faces_to_sew(-1.0) + , max_faces_to_orient(-1.0) , ifc_length_unit(1.0) , ifc_planeangle_unit(-1.0) , modelling_precision(0.00001) @@ -251,8 +247,7 @@ public: MAKE_TYPE_NAME(Kernel)& operator=(const MAKE_TYPE_NAME(Kernel)& other) { setValue(GV_DEFLECTION_TOLERANCE, other.getValue(GV_DEFLECTION_TOLERANCE)); - setValue(GV_WIRE_CREATION_TOLERANCE, other.getValue(GV_WIRE_CREATION_TOLERANCE)); - setValue(GV_POINT_EQUALITY_TOLERANCE, other.getValue(GV_POINT_EQUALITY_TOLERANCE)); + setValue(GV_MAX_FACES_TO_ORIENT, other.getValue(GV_MAX_FACES_TO_ORIENT)); setValue(GV_LENGTH_UNIT, other.getValue(GV_LENGTH_UNIT)); setValue(GV_PLANEANGLE_UNIT, other.getValue(GV_PLANEANGLE_UNIT)); setValue(GV_PRECISION, other.getValue(GV_PRECISION)); diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index f5f6a9d303..0e1bcb7e35 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -1265,12 +1265,6 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) { case GV_DEFLECTION_TOLERANCE: deflection_tolerance = value; break; - case GV_WIRE_CREATION_TOLERANCE: - wire_creation_tolerance = value; - break; - case GV_POINT_EQUALITY_TOLERANCE: - point_equality_tolerance = value; - break; case GV_LENGTH_UNIT: ifc_length_unit = value; break; @@ -1283,8 +1277,11 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) { case GV_DIMENSIONALITY: dimensionality = value; break; + case GV_MAX_FACES_TO_ORIENT: + max_faces_to_orient = value; + break; default: - assert(!"never reach here"); + throw std::runtime_error("Invalid setting"); } } @@ -1292,29 +1289,24 @@ double IfcGeom::Kernel::getValue(GeomValue var) const { switch (var) { case GV_DEFLECTION_TOLERANCE: return deflection_tolerance; - case GV_WIRE_CREATION_TOLERANCE: - return wire_creation_tolerance; case GV_MINIMAL_FACE_AREA: // Considering a right-angled triangle, this about the smallest // area you can obtain without the vertices being confused. - return modelling_precision * modelling_precision / 2.; + return modelling_precision * modelling_precision / 20.; case GV_POINT_EQUALITY_TOLERANCE: - return point_equality_tolerance; + return modelling_precision; case GV_LENGTH_UNIT: return ifc_length_unit; - break; case GV_PLANEANGLE_UNIT: return ifc_planeangle_unit; - break; case GV_PRECISION: return modelling_precision; - break; case GV_DIMENSIONALITY: return dimensionality; - break; + case GV_MAX_FACES_TO_ORIENT: + return max_faces_to_orient; } - assert(!"never reach here"); - return 0; + throw std::runtime_error("Invalid setting"); } namespace { diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index c17243d667..84e1ffdcec 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -706,6 +706,7 @@ namespace IfcGeom { unit_name = "METER"; unit_magnitude = 1.f; + kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_ORIENT, settings.get(IteratorSettings::SEW_SHELLS) ? std::numeric_limits::infinity() : -1); kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IteratorSettings::INCLUDE_CURVES) ? (settings.get(IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); if (settings.get(IteratorSettings::BUILDING_LOCAL_PLACEMENT)) { diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp index 30e2f7cc41..4526eda8c5 100644 --- a/src/ifcgeom/IfcGeomShapes.cpp +++ b/src/ifcgeom/IfcGeomShapes.cpp @@ -637,6 +637,10 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh IfcSchema::IfcFace::list::ptr faces = l->CfsFaces(); + double min_face_area = faceset_helper_ + ? (faceset_helper_->epsilon() * faceset_helper_->epsilon() / 20.) + : getValue(GV_MINIMAL_FACE_AREA); + TopTools_ListOfShape face_list; for (IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++it) { bool success = false; @@ -667,18 +671,18 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh if (face_it.Value().ShapeType() == TopAbs_FACE) { // This should really be the case. This is not asserted. const TopoDS_Face& triangle = TopoDS::Face(face_it.Value()); - if (face_area(triangle) > getValue(GV_MINIMAL_FACE_AREA)) { + if (face_area(triangle) > min_face_area) { face_list.Append(triangle); } else { - Logger::Message(Logger::LOG_WARNING, "Invalid face:", (*it)); + Logger::Message(Logger::LOG_WARNING, "Degenerate face:", (*it)); } } } } else { - if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) { + if (face_area(face) > min_face_area) { face_list.Append(face); } else { - Logger::Message(Logger::LOG_WARNING, "Invalid face:", (*it)); + Logger::Message(Logger::LOG_WARNING, "Degenerate face:", (*it)); } } } @@ -687,7 +691,7 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Sh return false; } - if (!create_solid_from_faces(face_list, shape)) { + if (face_list.Extent() > getValue(GV_MAX_FACES_TO_ORIENT) || !create_solid_from_faces(face_list, shape)) { TopoDS_Compound compound; BRep_Builder builder; builder.MakeCompound(compound); diff --git a/src/ifcgeom/IfcGeomTree.h b/src/ifcgeom/IfcGeomTree.h index d2acf71c33..8911183b58 100644 --- a/src/ifcgeom/IfcGeomTree.h +++ b/src/ifcgeom/IfcGeomTree.h @@ -262,6 +262,7 @@ namespace IfcGeom { IfcGeom::IteratorSettings settings_ = settings; settings_.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true); settings_.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true); + settings_.set(IfcGeom::IteratorSettings::SEW_SHELLS, true); IfcGeom::Iterator it(settings_, &f); diff --git a/src/ifcgeom_schema_agnostic/Kernel.h b/src/ifcgeom_schema_agnostic/Kernel.h index f41020889e..21a76b8fe4 100644 --- a/src/ifcgeom_schema_agnostic/Kernel.h +++ b/src/ifcgeom_schema_agnostic/Kernel.h @@ -27,15 +27,15 @@ namespace IfcGeom { // Specifies the deflection of the mesher // Default: 0.001m / 1mm GV_DEFLECTION_TOLERANCE, - // Specifies the tolerance of the wire builder, most notably for trimmed curves - // Default: 0.0001m / 0.1mm - GV_WIRE_CREATION_TOLERANCE, // Specifies the minimal area of a face to be included in an IfcConnectedFaceset // Read-only GV_MINIMAL_FACE_AREA, // Specifies the threshold distance under which cartesian points are deemed equal - // Default: 0.00001m / 0.01mm + // Read-only GV_POINT_EQUALITY_TOLERANCE, + // Specifies maximum number of faces for a shell to be reoriented. + // Default: -1 + GV_MAX_FACES_TO_ORIENT, // The length unit used the creation of TopoDS_Shapes, primarily affects the // interpretation of IfcCartesianPoints and IfcVector magnitudes // DefaultL 1.0 diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index ce359b1708..5e0060be62 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -289,6 +289,7 @@ struct ShapeRTTI : public boost::static_visitor IfcParse::IfcFile* file = instance->data().file; IfcGeom::Kernel kernel(file); + kernel.setValue(IfcGeom::Kernel::GV_MAX_FACES_TO_SEW, settings.get(IfcGeom::IteratorSettings::SEW_SHELLS) ? std::numeric_limits::infinity() : -1); kernel.setValue(IfcGeom::Kernel::GV_DIMENSIONALITY, (settings.get(IfcGeom::IteratorSettings::INCLUDE_CURVES) ? (settings.get(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES) ? -1. : 0.) : +1.)); if (instance->declaration().is(Schema::IfcProduct::Class())) {