Taxonomy curve upgrades #4832

This commit is contained in:
Thomas Krijnen
2024-06-18 20:18:39 +02:00
parent 691fe549d7
commit 0e42130e9d
+229 -90
View File
@@ -8,6 +8,7 @@
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <boost/math/constants/constants.hpp>
#include <Eigen/Dense> #include <Eigen/Dense>
@@ -1116,39 +1117,22 @@ typedef item const* ptr;
static const size_t max = std::tuple_size<impl::SurfacesTuple>::value; static const size_t max = std::tuple_size<impl::SurfacesTuple>::value;
}; };
// Hacks around not wanting to use if constexpr
template <typename T> template <typename T>
class loop_to_face_upgrade { class loop_to_face_upgrade {
public:
loop_to_face_upgrade(taxonomy::ptr) {}
operator bool() const {
return false;
}
operator taxonomy::face::ptr() const {
throw taxonomy::topology_error();
}
operator typename T::ptr() const {
throw taxonomy::topology_error();
}
};
template <>
class loop_to_face_upgrade<taxonomy::face> {
private: private:
boost::optional<taxonomy::face::ptr> face_; boost::optional<taxonomy::face::ptr> face_;
public: public:
loop_to_face_upgrade(taxonomy::ptr item) { loop_to_face_upgrade(taxonomy::ptr item) {
auto loop = taxonomy::dcast<taxonomy::loop>(item); if constexpr (std::is_same_v<T, face>) {
if (loop) { auto loop = taxonomy::dcast<taxonomy::loop>(item);
loop->external = true; if (loop) {
loop->external = true;
face_ = taxonomy::make<taxonomy::face>(); face_ = taxonomy::make<taxonomy::face>();
(*face_)->instance = loop->instance; (*face_)->instance = loop->instance;
(*face_)->matrix = loop->matrix; (*face_)->matrix = loop->matrix;
(*face_)->children = { taxonomy::clone(loop) }; (*face_)->children = { taxonomy::clone(loop) };
}
} }
} }
@@ -1156,66 +1140,178 @@ typedef item const* ptr;
return face_.is_initialized(); return face_.is_initialized();
} }
operator taxonomy::face::ptr() const { operator typename T::ptr() const {
return *face_; if constexpr (std::is_same_v<T, face>) {
if (face_) {
return *face_;
}
}
return nullptr;
} }
}; };
// Hacks around not wanting to use if constexpr template <typename T>
template <typename T> class curve_to_edge_upgrade {
class loop_to_piecewise_function_upgrade { private:
public: boost::optional<taxonomy::edge::ptr> edge_;
loop_to_piecewise_function_upgrade(taxonomy::ptr) {} public:
curve_to_edge_upgrade(taxonomy::ptr item) {
if constexpr (std::is_same_v<T, edge>) {
auto circle = taxonomy::dcast<taxonomy::circle>(item);
auto ellipse = taxonomy::dcast<taxonomy::ellipse>(item);
if (circle || ellipse) {
edge_ = taxonomy::make<taxonomy::edge>();
if (circle) {
(*edge_)->basis = circle;
} else {
(*edge_)->basis = ellipse;
}
// @todo make trims optional to allow unbounded edges
(*edge_)->start = 0.;
(*edge_)->end = 2 * boost::math::constants::pi<double>();
}
}
}
operator bool() const { operator bool() const {
return false; return edge_.is_initialized();
} }
operator taxonomy::piecewise_function::ptr() const { operator typename T::ptr() const {
throw taxonomy::topology_error(); if constexpr (std::is_same_v<T, edge>) {
} if (edge_) {
return *edge_;
}
}
return nullptr;
}
};
operator typename T::ptr() const {
throw taxonomy::topology_error();
}
};
template <> template <typename T>
class loop_to_piecewise_function_upgrade<taxonomy::piecewise_function> { class curve_to_loop_upgrade {
private:
boost::optional<taxonomy::loop::ptr> loop_;
public:
curve_to_loop_upgrade(taxonomy::ptr item) {
if constexpr (std::is_same_v<T, loop>) {
auto circle = taxonomy::dcast<taxonomy::circle>(item);
auto ellipse = taxonomy::dcast<taxonomy::ellipse>(item);
if (circle || ellipse) {
auto edge = taxonomy::make<taxonomy::edge>();
if (circle) {
edge->basis = circle;
} else {
edge->basis = ellipse;
}
// @todo make trims optional to allow unbounded edges
edge->start = 0.;
edge->end = 2 * boost::math::constants::pi<double>();
loop_ = taxonomy::make<taxonomy::loop>();
(*loop_)->children.push_back(edge);
}
}
}
operator bool() const {
return loop_.is_initialized();
}
operator typename T::ptr() const {
if constexpr (std::is_same_v<T, loop>) {
if (loop_) {
return *loop_;
}
}
return nullptr;
}
};
template <typename T>
class curve_to_face_upgrade {
private:
boost::optional<taxonomy::face::ptr> face_;
public:
curve_to_face_upgrade(taxonomy::ptr item) {
if constexpr (std::is_same_v<T, edge>) {
auto circle = taxonomy::dcast<taxonomy::circle>(item);
auto ellipse = taxonomy::dcast<taxonomy::ellipse>(item);
if (circle || ellipse) {
auto edge = taxonomy::make<taxonomy::edge>();
if (circle) {
edge->basis = circle;
} else {
edge->basis = ellipse;
}
// @todo make trims optional to allow unbounded edges
edge->start = 0.;
edge->end = 2 * boost::math::constants::pi<double>();
auto loop = taxonomy::make<taxonomy::loop>();
loop->children.push_back(edge);
face_ = taxonomy::make<taxonomy::face>();
(*face_)->instance = loop->instance;
(*face_)->matrix = loop->matrix;
(*face_)->children = { taxonomy::clone(loop) };
}
}
}
operator bool() const {
return face_.is_initialized();
}
operator typename T::ptr() const {
if constexpr (std::is_same_v<T, face>) {
if (face_) {
return *face_;
}
}
return nullptr;
}
};
template <typename T>
class loop_to_piecewise_function_upgrade {
private: private:
boost::optional<taxonomy::piecewise_function::ptr> pwf_; boost::optional<taxonomy::piecewise_function::ptr> pwf_;
public: public:
loop_to_piecewise_function_upgrade(taxonomy::ptr item) { loop_to_piecewise_function_upgrade(taxonomy::ptr item) {
auto loop = taxonomy::dcast<taxonomy::loop>(item); if constexpr (std::is_same_v<T, piecewise_function>) {
if (loop) { auto loop = taxonomy::dcast<taxonomy::loop>(item);
if (loop->pwf.is_initialized()) { if (loop) {
pwf_ = loop->pwf; if (loop->pwf.is_initialized()) {
} else { pwf_ = loop->pwf;
taxonomy::piecewise_function::spans spans; } else {
spans.reserve(loop->children.size()); taxonomy::piecewise_function::spans spans;
for (auto& edge : loop->children) { spans.reserve(loop->children.size());
// the edge could be an arc or trimmed circle in the case of IfcIndexPolyCurve - support for this isn't implemented yet for (auto& edge : loop->children) {
if (edge->basis) { // the edge could be an arc or trimmed circle in the case of IfcIndexPolyCurve - support for this isn't implemented yet
Logger::Message(Logger::Severity::LOG_NOTICE, "Shape of basis curve ignored - edge is treated as a straight line edge"); if (edge->basis) {
} Logger::Message(Logger::Severity::LOG_NOTICE, "Shape of basis curve ignored - edge is treated as a straight line edge");
}
const auto& s = boost::get<taxonomy::point3::ptr>(edge->start)->ccomponents(); const auto& s = boost::get<taxonomy::point3::ptr>(edge->start)->ccomponents();
const auto& e = boost::get<taxonomy::point3::ptr>(edge->end)->ccomponents(); const auto& e = boost::get<taxonomy::point3::ptr>(edge->end)->ccomponents();
Eigen::Vector3d v = e - s; Eigen::Vector3d v = e - s;
auto l = v.norm(); // the norm of a vector is a measure of its length auto l = v.norm(); // the norm of a vector is a measure of its length
v.normalize(); // normalize the vector so that it is a unit direction vector v.normalize(); // normalize the vector so that it is a unit direction vector
std::function<Eigen::Matrix4d(double)> fn = [s, v](double u) { std::function<Eigen::Matrix4d(double)> fn = [s, v](double u) {
Eigen::Vector3d o(s + u * v), axis(0, 0, 1), refDirection(v); Eigen::Vector3d o(s + u * v), axis(0, 0, 1), refDirection(v);
auto Y = axis.cross(refDirection).normalized(); auto Y = axis.cross(refDirection).normalized();
axis = refDirection.cross(Y).normalized(); axis = refDirection.cross(Y).normalized();
return taxonomy::make<taxonomy::matrix4>(o, axis, refDirection)->components(); return taxonomy::make<taxonomy::matrix4>(o, axis, refDirection)->components();
}; };
spans.emplace_back(l, fn); spans.emplace_back(l, fn);
} }
pwf_ = taxonomy::make<taxonomy::piecewise_function>(spans); pwf_ = taxonomy::make<taxonomy::piecewise_function>(spans);
loop->pwf = pwf_; loop->pwf = pwf_;
} }
}
} }
} }
@@ -1223,22 +1319,49 @@ typedef item const* ptr;
return pwf_.is_initialized(); return pwf_.is_initialized();
} }
operator taxonomy::piecewise_function::ptr() const { operator typename T::ptr() const {
return *pwf_; if constexpr (std::is_same_v<T, piecewise_function>) {
if (pwf_) {
return *pwf_;
}
}
return nullptr;
} }
}; };
#ifdef TAXONOMY_USE_SHARED_PTR #ifdef TAXONOMY_USE_SHARED_PTR
template <typename T, typename U> template <typename T, typename U>
std::shared_ptr<T> cast(const std::shared_ptr<U>& u) { std::shared_ptr<T> cast(const std::shared_ptr<U>& u) {
loop_to_face_upgrade<T> upg(u); {
if (upg) { curve_to_edge_upgrade<T> upg(u);
return upg; if (upg) {
return upg;
}
}
{
curve_to_loop_upgrade<T> upg(u);
if (upg) {
return upg;
}
}
{
curve_to_face_upgrade<T> upg(u);
if (upg) {
return upg;
}
}
{
loop_to_face_upgrade<T> upg(u);
if (upg) {
return upg;
}
}
{
loop_to_piecewise_function_upgrade<T> upg(u);
if (upg) {
return upg;
}
} }
loop_to_piecewise_function_upgrade<T> pwupg(u);
if (pwupg) {
return pwupg;
}
if (auto r = std::dynamic_pointer_cast<T>(u)) { if (auto r = std::dynamic_pointer_cast<T>(u)) {
return r; return r;
} else { } else {
@@ -1247,15 +1370,31 @@ typedef item const* ptr;
} }
template <typename T, typename U> template <typename T, typename U>
std::shared_ptr<T> dcast(const std::shared_ptr<U>& u) { std::shared_ptr<T> dcast(const std::shared_ptr<U>& u) {
loop_to_face_upgrade<T> upg(u); {
if (upg) { curve_to_edge_upgrade<T> upg(u);
return upg; if (upg) {
return upg;
}
} }
loop_to_piecewise_function_upgrade<T> pwupg(u); {
if (pwupg) { curve_to_face_upgrade<T> upg(u);
return pwupg; if (upg) {
} return upg;
return std::dynamic_pointer_cast<T>(u); }
}
{
loop_to_face_upgrade<T> upg(u);
if (upg) {
return upg;
}
}
{
loop_to_piecewise_function_upgrade<T> upg(u);
if (upg) {
return upg;
}
}
return std::dynamic_pointer_cast<T>(u);
} }
#endif #endif
#ifdef TAXONOMY_USE_UNIQUE_PTR #ifdef TAXONOMY_USE_UNIQUE_PTR