diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 058fe8f867..1b5946f796 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -24,6 +24,7 @@ #include "../ifcgeom/ConversionSettings.h" #include "../ifcgeom/taxonomy.h" +#include #include #include #include @@ -293,8 +294,8 @@ namespace IfcGeom { virtual ConversionResultShape* intersect(ConversionResultShape*) = 0; virtual ConversionResultShape* concat(ConversionResultShape*) = 0; - virtual void map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) = 0; - virtual void map(const std::vector>& from, const std::vector>& to) = 0; + virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) = 0; + virtual std::size_t map(const std::vector>& from, const std::vector>& to) = 0; virtual ConversionResultShape* moved(ifcopenshell::geometry::taxonomy::matrix4::ptr) const = 0; virtual bool surface_area_along_direction(double tol, const ifcopenshell::geometry::taxonomy::matrix4::ptr&, double& along_x, double& along_y, double& along_z) const = 0; diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 749fd1435e..f8fa868946 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -78,6 +78,31 @@ namespace { ); } + cgal_plane_t plane_from_opaque(const OpaqueCoordinate<4>& p) { +#ifdef IFOPSH_SIMPLE_KERNEL + return cgal_plane_t( + p.get(0)->to_double(), + p.get(1)->to_double(), + p.get(2)->to_double(), + p.get(3)->to_double() + ); +#else + return cgal_plane_t( + static_cast(p.get(0))->value(), + static_cast(p.get(1))->value(), + static_cast(p.get(2))->value(), + static_cast(p.get(3))->value() + ); +#endif + } + + void insert_normalized_plane_map(plane_map& mp, const OpaqueCoordinate<4>& from, const OpaqueCoordinate<4>& to) { + mp.insert({ + normalized_plane_for_map(plane_from_opaque(from)), + normalized_plane_for_map(plane_from_opaque(to)) + }); + } + cgal_vector_t wire_normal(const cgal_wire_t& wire) { typename Kernel_::FT a(0), b(0), c(0); if (wire.size() < 3) { @@ -984,11 +1009,11 @@ ConversionResultShape* ifcopenshell::geometry::CgalShape::moved(ifcopenshell::ge return new CgalShape(s, convex_tag_); } -void ifcopenshell::geometry::CgalShape::map(OpaqueCoordinate<4>&, OpaqueCoordinate<4>&) { +std::size_t ifcopenshell::geometry::CgalShape::map(OpaqueCoordinate<4>&, OpaqueCoordinate<4>&) { throw std::runtime_error("Not implemented"); } -void ifcopenshell::geometry::CgalShape::map(const std::vector>&, const std::vector>&) { +std::size_t ifcopenshell::geometry::CgalShape::map(const std::vector>&, const std::vector>&) { throw std::runtime_error("Not implemented"); } @@ -1165,27 +1190,16 @@ ConversionResultShape* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition:: throw std::runtime_error("Not implemented"); } -void ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) { +std::size_t ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) { plane_map mp; - mp.insert({ - CGAL::Plane_3( - static_cast(from.get(0))->value(), - static_cast(from.get(1))->value(), - static_cast(from.get(2))->value(), - static_cast(from.get(3))->value() - ), - CGAL::Plane_3( - static_cast(to.get(0))->value(), - static_cast(to.get(1))->value(), - static_cast(to.get(2))->value(), - static_cast(to.get(3))->value() - ) - }); - auto nw = shape_->map(mp); + insert_normalized_plane_map(mp, from, to); + std::size_t mutated = 0; + auto nw = shape_->map(mp, mutated); shape_ = std::move(nw); + return mutated; } -void ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const std::vector>& froms, const std::vector>& tos) { +std::size_t ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const std::vector>& froms, const std::vector>& tos) { plane_map mp; if (froms.size() != tos.size()) { throw std::runtime_error("Expected equal size"); @@ -1195,23 +1209,12 @@ void ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const std::vec for (; it < froms.end(); ++it, ++jt) { auto& from = *it; auto& to = *jt; - mp.insert({ - CGAL::Plane_3( - static_cast(from.get(0))->value(), - static_cast(from.get(1))->value(), - static_cast(from.get(2))->value(), - static_cast(from.get(3))->value() - ), - CGAL::Plane_3( - static_cast(to.get(0))->value(), - static_cast(to.get(1))->value(), - static_cast(to.get(2))->value(), - static_cast(to.get(3))->value() - ) - }); + insert_normalized_plane_map(mp, from, to); } - auto nw = shape_->map(mp); + std::size_t mutated = 0; + auto nw = shape_->map(mp, mutated); shape_ = std::move(nw); + return mutated; } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index b441776d6e..d169f5495e 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -276,8 +276,8 @@ namespace ifcopenshell { namespace geometry { virtual ConversionResultShape* intersect(ConversionResultShape*); virtual ConversionResultShape* concat(ConversionResultShape*); - virtual void map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to); - virtual void map(const std::vector>& from, const std::vector>& to); + virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to); + virtual std::size_t map(const std::vector>& from, const std::vector>& to); virtual ConversionResultShape* moved(ifcopenshell::geometry::taxonomy::matrix4::ptr) const; virtual bool surface_area_along_direction(double tol, const ifcopenshell::geometry::taxonomy::matrix4::ptr&, double& along_x, double& along_y, double& along_z) const; @@ -347,8 +347,8 @@ namespace ifcopenshell { namespace geometry { return nullptr; } - virtual void map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to); - virtual void map(const std::vector>& from, const std::vector>& to); + virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to); + virtual std::size_t map(const std::vector>& from, const std::vector>& to); virtual ConversionResultShape* moved(ifcopenshell::geometry::taxonomy::matrix4::ptr) const; virtual bool surface_area_along_direction(double tol, const ifcopenshell::geometry::taxonomy::matrix4::ptr&, double& along_x, double& along_y, double& along_z) const { diff --git a/src/ifcgeom/kernels/cgal/nef_to_halfspace_tree.h b/src/ifcgeom/kernels/cgal/nef_to_halfspace_tree.h index 368e49a2d2..df90aa2b47 100644 --- a/src/ifcgeom/kernels/cgal/nef_to_halfspace_tree.h +++ b/src/ifcgeom/kernels/cgal/nef_to_halfspace_tree.h @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -116,6 +117,23 @@ template using plane_map = std::map>; // using plane_map = std::unordered_map>; +template +typename Kernel::Plane_3 normalized_plane_for_map(const typename Kernel::Plane_3& plane) { + std::array abc{ plane.a(), plane.b(), plane.c() }; + auto minel = std::min_element(abc.begin(), abc.end()); + auto maxel = std::max_element(abc.begin(), abc.end()); + auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; + if (maxval == 0) { + return plane; + } + return typename Kernel::Plane_3( + plane.a() / maxval, + plane.b() / maxval, + plane.c() / maxval, + plane.d() / maxval + ); +} + // Lexicographic comparator for CGAL Point_d (operator< is deleted in CGAL 6.x) struct Point_d_4d_Less { using Point_d = CGAL::Epick_d>::Point_d; @@ -264,7 +282,11 @@ class halfspace_tree { public: virtual CGAL::Nef_polyhedron_3 evaluate() const = 0; virtual void accumulate(std::list&) const = 0; - virtual std::unique_ptr map(const plane_map&) const = 0; + std::unique_ptr map(const plane_map& m) const { + std::size_t ignored = 0; + return map(m, ignored); + } + virtual std::unique_ptr map(const plane_map&, std::size_t& mutated) const = 0; virtual std::string dump(int level = 0) const = 0; virtual tree_type kind() const = 0; virtual void merge(CGAL::Nef_polyhedron_3&) const = 0; @@ -366,10 +388,10 @@ public: op->accumulate(points); } } - virtual std::unique_ptr> map(const plane_map& m) const { + virtual std::unique_ptr> map(const plane_map& m, std::size_t& mutated) const { decltype(operands_) mapped; for (auto& op : operands_) { - mapped.emplace_back(op->map(m)); + mapped.emplace_back(op->map(m, mutated)); } return std::unique_ptr>(new halfspace_tree_nary_branch(operation_, std::move(mapped))); } @@ -485,21 +507,12 @@ public: virtual void accumulate(std::list& points) const { points.push_back(plane_); } - virtual std::unique_ptr> map(const plane_map& m) const { - - std::array abc{ plane_.a(), plane_.b(), plane_.c() }; - auto minel = std::min_element(abc.begin(), abc.end()); - auto maxel = std::max_element(abc.begin(), abc.end()); - auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; - CGAL::Plane_3 pp( - plane_.a() / maxval, - plane_.b() / maxval, - plane_.c() / maxval, - plane_.d() / maxval - ); + virtual std::unique_ptr> map(const plane_map& m, std::size_t& mutated) const { + CGAL::Plane_3 pp = normalized_plane_for_map(plane_); auto it = m.find(pp); if (it != m.end()) { + ++mutated; return std::unique_ptr>(new halfspace_tree_plane(it->second)); } else { return std::unique_ptr>(new halfspace_tree_plane(plane_)); @@ -1358,4 +1371,4 @@ bool write_to_obj(const CGAL::Nef_polyhedron_3& a, std::ostream& ofs, si return volume_index == std::numeric_limits::max(); } -#endif \ No newline at end of file +#endif diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp index 38d7b12330..36e423730e 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp @@ -696,10 +696,10 @@ bool ifcopenshell::geometry::OpenCascadeShape::surface_area_along_direction(doub return true; } -void ifcopenshell::geometry::OpenCascadeShape::map(OpaqueCoordinate<4>&, OpaqueCoordinate<4>&) { +std::size_t ifcopenshell::geometry::OpenCascadeShape::map(OpaqueCoordinate<4>&, OpaqueCoordinate<4>&) { throw std::runtime_error("Not implemented"); } -void ifcopenshell::geometry::OpenCascadeShape::map(const std::vector>&, const std::vector>&) { +std::size_t ifcopenshell::geometry::OpenCascadeShape::map(const std::vector>&, const std::vector>&) { throw std::runtime_error("Not implemented"); } diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h index 927c9f3dac..643c797905 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h @@ -101,8 +101,8 @@ namespace ifcopenshell { virtual ConversionResultShape* intersect(ConversionResultShape*); virtual ConversionResultShape* concat(ConversionResultShape*); - virtual void map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to); - virtual void map(const std::vector>& from, const std::vector>& to); + virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to); + virtual std::size_t map(const std::vector>& from, const std::vector>& to); virtual ConversionResultShape* moved(ifcopenshell::geometry::taxonomy::matrix4::ptr) const; virtual bool surface_area_along_direction(double tol, const ifcopenshell::geometry::taxonomy::matrix4::ptr&, double& along_x, double& along_y, double& along_z) const; @@ -113,4 +113,4 @@ namespace ifcopenshell { } } -#endif \ No newline at end of file +#endif