diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index e0ebbc964d..4c7a8eb2f0 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -340,11 +340,13 @@ int main(int argc, char** argv) { "Specifies a material file that describes the material object types will have" "if an object does not have any specified material in the IFC file.") ("validate", "Checks whether geometrical output conforms to the included explicit quantities.") - ("no-wire-intersection-check", "Skip wire intersection check") + ("no-wire-intersection-check", "Skip wire intersection check.") + ("no-wire-intersection-tolerance", "Set wire intersection tolerance to 0.") + ("strict-tolerance", "Use exact tolerance from model. Default is a 10 " - "times increase for more permissive edge curves and fewer artifacts after " - "boolean operations at the expense of geometric detail " - "due to vertex collapsing and wire intersection fuzziness."); + "times increase for more permissive edge curves and fewer artifacts after " + "boolean operations at the expense of geometric detail " + "due to vertex collapsing and wire intersection fuzziness."); std::string bounds; #ifdef HAVE_ICU @@ -487,6 +489,7 @@ int main(int argc, char** argv) { const bool validate = vmap.count("validate") != 0; const bool edge_arrows = vmap.count("edge-arrows") != 0; const bool no_wire_intersection_check = vmap.count("no-wire-intersection-check") != 0; + const bool no_wire_intersection_tolerance = vmap.count("no-wire-intersection-tolerance") != 0; const bool strict_tolerance = vmap.count("strict-tolerance") != 0; if (!quiet || vmap.count("version")) { @@ -749,6 +752,7 @@ int main(int argc, char** argv) { settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement); settings.set(IfcGeom::IteratorSettings::VALIDATE_QUANTITIES, validate); settings.set(IfcGeom::IteratorSettings::NO_WIRE_INTERSECTION_CHECK, no_wire_intersection_check); + settings.set(IfcGeom::IteratorSettings::NO_WIRE_INTERSECTION_TOLERANCE, no_wire_intersection_tolerance); settings.set(IfcGeom::IteratorSettings::STRICT_TOLERANCE, strict_tolerance); settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names); diff --git a/src/ifcgeom/IfcGeom.h b/src/ifcgeom/IfcGeom.h index 83c4843fd8..5ce73b61ab 100644 --- a/src/ifcgeom/IfcGeom.h +++ b/src/ifcgeom/IfcGeom.h @@ -225,6 +225,7 @@ private: double dimensionality; double layerset_first; double no_wire_intersection_check; + double no_wire_intersection_tolerance; double precision_factor; // For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) @@ -259,6 +260,7 @@ public: , layerset_first(-1.) , disable_boolean_result(-1.) , no_wire_intersection_check(-1) + , no_wire_intersection_tolerance(-1) , precision_factor(10.) {} diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp index 837054fa72..e21427076b 100644 --- a/src/ifcgeom/IfcGeomFunctions.cpp +++ b/src/ifcgeom/IfcGeomFunctions.cpp @@ -1421,6 +1421,9 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) { case GV_PRECISION_FACTOR: precision_factor = value; break; + case GV_NO_WIRE_INTERSECTION_TOLERANCE: + no_wire_intersection_tolerance = value; + break; default: throw std::runtime_error("Invalid setting"); } @@ -1454,6 +1457,8 @@ double IfcGeom::Kernel::getValue(GeomValue var) const { return no_wire_intersection_check; case GV_PRECISION_FACTOR: return precision_factor; + case GV_NO_WIRE_INTERSECTION_TOLERANCE: + return no_wire_intersection_tolerance; } throw std::runtime_error("Invalid setting"); } @@ -3851,11 +3856,14 @@ bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListO // TopoDS_Face face = BRepBuilderAPI_MakeFace(wire, true).Face(); // ShapeAnalysis_Wire saw(wd, face, getValue(GV_PRECISION)); - const double eps = faceset_helper_ - // eps is added to both ends of the parametric domain, so 3. is chosen to be on the safe side here. - ? (faceset_helper_->epsilon() / 3.) - // @todo re-evaluate 2. here for the reasons above: - : (std::min)(min_edge_length(wire) / 2., getValue(GV_PRECISION) * 10.); + double eps = 0; + if (getValue(GV_NO_WIRE_INTERSECTION_TOLERANCE) < 0.) { + eps = faceset_helper_ + // eps is added to both ends of the parametric domain, so 3. is chosen to be on the safe side here. + ? (faceset_helper_->epsilon() / 3.) + // @todo re-evaluate 2. here for the reasons above: + : (std::min)(min_edge_length(wire) / 2., getValue(GV_PRECISION) * 10.); + } for (int i = 2; i < n; ++i) { diff --git a/src/ifcgeom/IfcGeomIteratorImplementation.h b/src/ifcgeom/IfcGeomIteratorImplementation.h index 98b788030c..99010b218f 100644 --- a/src/ifcgeom/IfcGeomIteratorImplementation.h +++ b/src/ifcgeom/IfcGeomIteratorImplementation.h @@ -1008,6 +1008,11 @@ namespace IfcGeom { ? +1.0 : -1.0 ); + kernel.setValue(IfcGeom::Kernel::GV_NO_WIRE_INTERSECTION_TOLERANCE, + settings.get(IteratorSettings::NO_WIRE_INTERSECTION_TOLERANCE) + ? +1.0 + : -1.0 + ); kernel.setValue(IfcGeom::Kernel::GV_PRECISION_FACTOR, settings.get(IteratorSettings::STRICT_TOLERANCE) ? 1.0 diff --git a/src/ifcgeom/IfcGeomIteratorSettings.h b/src/ifcgeom/IfcGeomIteratorSettings.h index bf615237bf..02476a9dd2 100644 --- a/src/ifcgeom/IfcGeomIteratorSettings.h +++ b/src/ifcgeom/IfcGeomIteratorSettings.h @@ -96,10 +96,12 @@ namespace IfcGeom DISABLE_BOOLEAN_RESULT = 1 << 20, // Disables wire intersection checks NO_WIRE_INTERSECTION_CHECK = 1 << 21, + // Set wire intersection tolerance to 0 + NO_WIRE_INTERSECTION_TOLERANCE = 1 << 22, // Sets kernel precision factor to 1 - STRICT_TOLERANCE = 1 << 22, + STRICT_TOLERANCE = 1 << 23, /// Number of different setting flags. - NUM_SETTINGS = 22, + NUM_SETTINGS = 24, }; /// Used to store logical OR combination of setting flags. typedef unsigned SettingField; diff --git a/src/ifcgeom_schema_agnostic/Kernel.h b/src/ifcgeom_schema_agnostic/Kernel.h index 36f07d2549..29f59a6f23 100644 --- a/src/ifcgeom_schema_agnostic/Kernel.h +++ b/src/ifcgeom_schema_agnostic/Kernel.h @@ -57,6 +57,7 @@ namespace IfcGeom { GV_DISABLE_BOOLEAN_RESULT, GV_NO_WIRE_INTERSECTION_CHECK, GV_PRECISION_FACTOR, + GV_NO_WIRE_INTERSECTION_TOLERANCE, }; Kernel(IfcParse::IfcFile* file_ = 0);