From 75b9e6cec987de80dff8be9513fcf532f4323d6b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 24 Mar 2024 16:45:31 +0100 Subject: [PATCH] setOnlyValid() option that skips and logs invalid topology #4130 --- .../kernels/opencascade/base_utils.cpp | 42 +++++++++++++++++++ src/ifcgeom/kernels/opencascade/base_utils.h | 1 + src/serializers/SvgSerializer.cpp | 4 ++ src/serializers/SvgSerializer.h | 9 ++++ 4 files changed, 56 insertions(+) diff --git a/src/ifcgeom/kernels/opencascade/base_utils.cpp b/src/ifcgeom/kernels/opencascade/base_utils.cpp index ac19c47be8..e05dc4884d 100644 --- a/src/ifcgeom/kernels/opencascade/base_utils.cpp +++ b/src/ifcgeom/kernels/opencascade/base_utils.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include @@ -822,3 +824,43 @@ bool IfcGeom::util::flatten_shape_list(const IfcGeom::ConversionResults& shapes, const bool success = !result.IsNull(); return success; } + +bool IfcGeom::util::validate_shape(const TopoDS_Shape& s) { + BRepCheck_Analyzer ana(s); + if (ana.IsValid()) { + return true; + } + + std::stringstream str; + bool any_emitted = false; + + std::function dump; + dump = [&ana, &str, &dump, &any_emitted](const TopoDS_Shape& s) { + if (!ana.Result(s).IsNull()) { + BRepCheck_ListIteratorOfListOfStatus itl; + itl.Initialize(ana.Result(s)->Status()); + for (; itl.More(); itl.Next()) { + if (itl.Value() != BRepCheck_NoError) { + if (any_emitted) { + str << ", "; + } + BRepCheck::Print(itl.Value(), str); + str.seekp(str.tellp() - (std::streamoff)1); + str << " on "; + TopAbs::Print(s.ShapeType(), str); + BRepTools::Dump(s, str); + any_emitted = true; + } + } + } + for (TopoDS_Iterator it(s); it.More(); it.Next()) { + dump(it.Value()); + } + }; + + dump(s); + + Logger::Warning(str.str()); + + return false; +} diff --git a/src/ifcgeom/kernels/opencascade/base_utils.h b/src/ifcgeom/kernels/opencascade/base_utils.h index 84c57a8af2..23905f5f31 100644 --- a/src/ifcgeom/kernels/opencascade/base_utils.h +++ b/src/ifcgeom/kernels/opencascade/base_utils.h @@ -74,6 +74,7 @@ namespace IfcGeom { TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&); bool flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse, double tol); + bool validate_shape(const TopoDS_Shape&); } } diff --git a/src/serializers/SvgSerializer.cpp b/src/serializers/SvgSerializer.cpp index e2cef5228d..1db8f772da 100644 --- a/src/serializers/SvgSerializer.cpp +++ b/src/serializers/SvgSerializer.cpp @@ -742,6 +742,10 @@ void SvgSerializer::write(const IfcGeom::BRepElement* brep_obj) { compound_local = comp2; } + if (only_valid_ && !IfcGeom::util::validate_shape(compound_local)) { + return; + } + geometry_data data{ compound_local, dash_arrays, trsf, brep_obj->product(), storey, elev, brep_obj->name(), nameElement(storey, brep_obj) }; if (auto_section_ || auto_elevation_ || section_ref_ || elevation_ref_ || elevation_ref_guid_ || deferred_section_data_) { diff --git a/src/serializers/SvgSerializer.h b/src/serializers/SvgSerializer.h index 1cb1806754..73980860d1 100644 --- a/src/serializers/SvgSerializer.h +++ b/src/serializers/SvgSerializer.h @@ -556,6 +556,7 @@ protected: bool unify_inputs_; bool mirror_y_; bool mirror_x_; + bool only_valid_; int profile_threshold_; @@ -723,6 +724,14 @@ public: return unify_inputs_; } + void setOnlyValid(bool b) { + only_valid_ = b; + } + + bool getOnlyValid(bool b) const { + return only_valid_; + } + void setScale(double s) { scale_ = s; } void setDrawingCenter(double x, double y) { center_x_ = x; center_y_ = y;