mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
Consistent policy on normalization in halfspace eq map()
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "../ifcgeom/ConversionSettings.h"
|
||||
#include "../ifcgeom/taxonomy.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
@@ -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<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& to) = 0;
|
||||
virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) = 0;
|
||||
virtual std::size_t map(const std::vector<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& 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;
|
||||
|
||||
@@ -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<NumberEpeck*>(p.get(0))->value(),
|
||||
static_cast<NumberEpeck*>(p.get(1))->value(),
|
||||
static_cast<NumberEpeck*>(p.get(2))->value(),
|
||||
static_cast<NumberEpeck*>(p.get(3))->value()
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void insert_normalized_plane_map(plane_map<Kernel_>& mp, const OpaqueCoordinate<4>& from, const OpaqueCoordinate<4>& to) {
|
||||
mp.insert({
|
||||
normalized_plane_for_map<Kernel_>(plane_from_opaque(from)),
|
||||
normalized_plane_for_map<Kernel_>(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<OpaqueCoordinate<4>>&, const std::vector<OpaqueCoordinate<4>>&) {
|
||||
std::size_t ifcopenshell::geometry::CgalShape::map(const std::vector<OpaqueCoordinate<4>>&, const std::vector<OpaqueCoordinate<4>>&) {
|
||||
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<Kernel_> mp;
|
||||
mp.insert({
|
||||
CGAL::Plane_3<Kernel_>(
|
||||
static_cast<NumberEpeck*>(from.get(0))->value(),
|
||||
static_cast<NumberEpeck*>(from.get(1))->value(),
|
||||
static_cast<NumberEpeck*>(from.get(2))->value(),
|
||||
static_cast<NumberEpeck*>(from.get(3))->value()
|
||||
),
|
||||
CGAL::Plane_3<Kernel_>(
|
||||
static_cast<NumberEpeck*>(to.get(0))->value(),
|
||||
static_cast<NumberEpeck*>(to.get(1))->value(),
|
||||
static_cast<NumberEpeck*>(to.get(2))->value(),
|
||||
static_cast<NumberEpeck*>(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<OpaqueCoordinate<4>>& froms, const std::vector<OpaqueCoordinate<4>>& tos) {
|
||||
std::size_t ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const std::vector<OpaqueCoordinate<4>>& froms, const std::vector<OpaqueCoordinate<4>>& tos) {
|
||||
plane_map<Kernel_> 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<Kernel_>(
|
||||
static_cast<NumberEpeck*>(from.get(0))->value(),
|
||||
static_cast<NumberEpeck*>(from.get(1))->value(),
|
||||
static_cast<NumberEpeck*>(from.get(2))->value(),
|
||||
static_cast<NumberEpeck*>(from.get(3))->value()
|
||||
),
|
||||
CGAL::Plane_3<Kernel_>(
|
||||
static_cast<NumberEpeck*>(to.get(0))->value(),
|
||||
static_cast<NumberEpeck*>(to.get(1))->value(),
|
||||
static_cast<NumberEpeck*>(to.get(2))->value(),
|
||||
static_cast<NumberEpeck*>(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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& to);
|
||||
virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to);
|
||||
virtual std::size_t map(const std::vector<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& 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<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& to);
|
||||
virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to);
|
||||
virtual std::size_t map(const std::vector<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& 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 {
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/graph/copy.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
@@ -116,6 +117,23 @@ template <typename Kernel>
|
||||
using plane_map = std::map<typename Kernel::Plane_3, typename Kernel::Plane_3, PlaneLess<Kernel>>;
|
||||
// using plane_map = std::unordered_map<typename Kernel::Plane_3, typename Kernel::Plane_3, PlaneHash<Kernel>>;
|
||||
|
||||
template <typename Kernel>
|
||||
typename Kernel::Plane_3 normalized_plane_for_map(const typename Kernel::Plane_3& plane) {
|
||||
std::array<typename Kernel::FT, 3> 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<CGAL::Dimension_tag<4>>::Point_d;
|
||||
@@ -264,7 +282,11 @@ class halfspace_tree {
|
||||
public:
|
||||
virtual CGAL::Nef_polyhedron_3<Kernel> evaluate() const = 0;
|
||||
virtual void accumulate(std::list<typename Kernel::Plane_3>&) const = 0;
|
||||
virtual std::unique_ptr<halfspace_tree> map(const plane_map<Kernel>&) const = 0;
|
||||
std::unique_ptr<halfspace_tree> map(const plane_map<Kernel>& m) const {
|
||||
std::size_t ignored = 0;
|
||||
return map(m, ignored);
|
||||
}
|
||||
virtual std::unique_ptr<halfspace_tree> map(const plane_map<Kernel>&, 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<Kernel>&) const = 0;
|
||||
@@ -366,10 +388,10 @@ public:
|
||||
op->accumulate(points);
|
||||
}
|
||||
}
|
||||
virtual std::unique_ptr<halfspace_tree<Kernel>> map(const plane_map<Kernel>& m) const {
|
||||
virtual std::unique_ptr<halfspace_tree<Kernel>> map(const plane_map<Kernel>& 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<halfspace_tree<Kernel>>(new halfspace_tree_nary_branch(operation_, std::move(mapped)));
|
||||
}
|
||||
@@ -485,21 +507,12 @@ public:
|
||||
virtual void accumulate(std::list<typename Kernel::Plane_3>& points) const {
|
||||
points.push_back(plane_);
|
||||
}
|
||||
virtual std::unique_ptr<halfspace_tree<Kernel>> map(const plane_map<Kernel>& m) const {
|
||||
|
||||
std::array<typename Kernel::FT, 3> 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<Kernel> pp(
|
||||
plane_.a() / maxval,
|
||||
plane_.b() / maxval,
|
||||
plane_.c() / maxval,
|
||||
plane_.d() / maxval
|
||||
);
|
||||
virtual std::unique_ptr<halfspace_tree<Kernel>> map(const plane_map<Kernel>& m, std::size_t& mutated) const {
|
||||
CGAL::Plane_3<Kernel> pp = normalized_plane_for_map<Kernel>(plane_);
|
||||
|
||||
auto it = m.find(pp);
|
||||
if (it != m.end()) {
|
||||
++mutated;
|
||||
return std::unique_ptr<halfspace_tree<Kernel>>(new halfspace_tree_plane(it->second));
|
||||
} else {
|
||||
return std::unique_ptr<halfspace_tree<Kernel>>(new halfspace_tree_plane(plane_));
|
||||
@@ -1358,4 +1371,4 @@ bool write_to_obj(const CGAL::Nef_polyhedron_3<Kernel>& a, std::ostream& ofs, si
|
||||
return volume_index == std::numeric_limits<size_t>::max();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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<OpaqueCoordinate<4>>&, const std::vector<OpaqueCoordinate<4>>&) {
|
||||
std::size_t ifcopenshell::geometry::OpenCascadeShape::map(const std::vector<OpaqueCoordinate<4>>&, const std::vector<OpaqueCoordinate<4>>&) {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
|
||||
@@ -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<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& to);
|
||||
virtual std::size_t map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to);
|
||||
virtual std::size_t map(const std::vector<OpaqueCoordinate<4>>& from, const std::vector<OpaqueCoordinate<4>>& 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
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user