mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 18:16:40 +00:00
Adds loop_to_piecewise_function_upgrade
This provides for a more uniform treatment of curves when mapping IfcOffsetCurveByDistances and IfcPointByDistanceExpression
This commit is contained in:
@@ -12,12 +12,13 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copz of the Lesser GNU General Public License *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "mapping.h"
|
||||
#include "../profile_helper.h"
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
@@ -34,17 +35,12 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
Logger::Error("IfcOffsetCurveByDistances must have at least one offset value");
|
||||
}
|
||||
|
||||
auto basis_curve = inst->BasisCurve();
|
||||
|
||||
auto first_offset_value = *(offset_values->begin());
|
||||
|
||||
// todo@ rb - basis_curve might not be piecewise - other valid types are IfcOffsetCurveByDistances, IfcPolyline and IfcIndexedPolyCurve
|
||||
// Is there a more generic type that can be evaluated at "u"?
|
||||
auto basis = taxonomy::cast<taxonomy::piecewise_function>(map(basis_curve));
|
||||
double basis_curve_length = 0;
|
||||
for (auto& s : basis->spans) {
|
||||
basis_curve_length += s.first;
|
||||
}
|
||||
auto basis_curve = inst->BasisCurve();
|
||||
//auto pw_curve = ifcopenshell::geometry::piecewise_from_item(map(basis_curve));
|
||||
auto pw_curve = taxonomy::dcast<taxonomy::piecewise_function>(map(basis_curve));
|
||||
double basis_curve_length = pw_curve->length();
|
||||
|
||||
auto offsets = taxonomy::make<taxonomy::piecewise_function>(&settings_);
|
||||
|
||||
@@ -95,7 +91,10 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
#endif
|
||||
if ((dp < 0.0 || basis_curve_length < dp)
|
||||
or
|
||||
(dn < 0.0 || basis_curve_length < dn))
|
||||
(dn < 0.0 || basis_curve_length < dn)
|
||||
or
|
||||
(dn < dp)
|
||||
)
|
||||
{
|
||||
Logger::Warning("IfcOffsetCurveByDistance offset value is out of bounds.");
|
||||
continue;
|
||||
@@ -144,14 +143,14 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
offsets->spans.push_back({l, fn});
|
||||
}
|
||||
|
||||
auto composition = [basis, offsets](double u)->Eigen::Matrix4d {
|
||||
auto p = basis->evaluate(u);
|
||||
auto composition = [pw_curve, offsets](double u) -> Eigen::Matrix4d {
|
||||
auto p = pw_curve->evaluate(u);
|
||||
auto offset = offsets->evaluate(u);
|
||||
Eigen::Matrix4d m = p * offset;
|
||||
return m;
|
||||
};
|
||||
|
||||
// current implementation assumes that offsets is equal to the full length of basis curve
|
||||
// current implementation assumes that composition is equal to the full length of basis curve
|
||||
// this may change depending on decisions in the bSI-IF
|
||||
auto pwf = taxonomy::make<taxonomy::piecewise_function>(&settings_);
|
||||
pwf->spans.emplace_back( basis_curve_length, composition );
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "mapping.h"
|
||||
#include "../profile_helper.h"
|
||||
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
@@ -25,9 +27,11 @@ using namespace ifcopenshell::geometry;
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPointByDistanceExpression* inst) {
|
||||
auto u = (*inst->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>()) * length_unit_;
|
||||
// @todo: rb - is it safe to assume the basis curve is a piecewise_function?
|
||||
auto curve = ifcopenshell::geometry::taxonomy::cast<ifcopenshell::geometry::taxonomy::piecewise_function>(map(inst->BasisCurve()));
|
||||
auto m = curve->evaluate(u);
|
||||
//auto basis_curve = inst->BasisCurve();
|
||||
//auto item = map(basis_curve);
|
||||
//auto pw_curve = ifcopenshell::geometry::piecewise_from_item(item);
|
||||
auto pw_curve = taxonomy::dcast<taxonomy::piecewise_function>(map(inst->BasisCurve()));
|
||||
auto m = pw_curve->evaluate(u);
|
||||
|
||||
auto o = m.col(3).head<3>();
|
||||
auto z = m.col(2).head<3>();
|
||||
|
||||
@@ -455,9 +455,7 @@ ifcopenshell::geometry::taxonomy::solid::ptr ifcopenshell::geometry::create_box(
|
||||
|
||||
ifcopenshell::geometry::taxonomy::item::ptr ifcopenshell::geometry::taxonomy::piecewise_function::evaluate() const {
|
||||
// @todo configure resolution
|
||||
double length = 0.0;
|
||||
for (auto& s : spans)
|
||||
length += s.first;
|
||||
double curve_length = length();
|
||||
|
||||
std::vector<taxonomy::point3::ptr> polygon;
|
||||
|
||||
@@ -466,12 +464,12 @@ ifcopenshell::geometry::taxonomy::item::ptr ifcopenshell::geometry::taxonomy::pi
|
||||
int num_steps = 0;
|
||||
if (param_type == ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE) {
|
||||
// parameter is max step size
|
||||
num_steps = (int)std::ceil(length / param);
|
||||
num_steps = (int)std::ceil(curve_length / param);
|
||||
} else {
|
||||
// parameter is minimum number of steps
|
||||
num_steps = (int)std::ceil(param);
|
||||
}
|
||||
auto resolution = length / num_steps;
|
||||
auto resolution = curve_length / num_steps;
|
||||
|
||||
for (int i = 0; i <= num_steps; ++i) {
|
||||
auto u = resolution * i;
|
||||
|
||||
+94
-5
@@ -2,6 +2,7 @@
|
||||
#define TAXONOMY_H
|
||||
|
||||
#include "../ifcparse/IfcBaseClass.h"
|
||||
#include "../ifcparse/IfcLogger.h"
|
||||
|
||||
#include "ConversionSettings.h"
|
||||
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <exception>
|
||||
#include <numeric>
|
||||
|
||||
#ifndef TAXONOMY_USE_UNIQUE_PTR
|
||||
#ifndef TAXONOMY_USE_NAKED_PTR
|
||||
@@ -147,6 +149,10 @@ typedef item const* ptr;
|
||||
// length of span, function to evaluate span
|
||||
std::vector<std::pair<double, std::function<Eigen::Matrix4d(double u)>>> spans;
|
||||
|
||||
double length() const {
|
||||
return std::accumulate(spans.begin(), spans.end(), 0.0, [](const auto& v,const auto& s) { return v + s.first; });
|
||||
}
|
||||
|
||||
void print(std::ostream& o, int = 0) const {
|
||||
o << "piecewise_function" << std::endl;
|
||||
}
|
||||
@@ -1096,6 +1102,65 @@ typedef item const* ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Hacks around not wanting to use if constexpr
|
||||
template <typename T>
|
||||
class loop_to_piecewise_function_upgrade {
|
||||
public:
|
||||
loop_to_piecewise_function_upgrade(taxonomy::ptr) {}
|
||||
|
||||
operator bool() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
operator taxonomy::piecewise_function::ptr() const {
|
||||
throw taxonomy::topology_error();
|
||||
}
|
||||
|
||||
operator typename T::ptr() const {
|
||||
throw taxonomy::topology_error();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class loop_to_piecewise_function_upgrade<taxonomy::piecewise_function> {
|
||||
private:
|
||||
boost::optional<taxonomy::piecewise_function::ptr> pwf_;
|
||||
|
||||
public:
|
||||
loop_to_piecewise_function_upgrade(taxonomy::ptr item) {
|
||||
auto loop = taxonomy::dcast<taxonomy::loop>(item);
|
||||
if (loop) {
|
||||
pwf_ = taxonomy::make<taxonomy::piecewise_function>();
|
||||
for (auto& edge : loop->children) {
|
||||
// the edge could be an arc or trimmed circle in the case of IfcIndexPolyCurve - support for this isn't implemented yet
|
||||
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& e = boost::get<taxonomy::point3::ptr>(edge->end)->ccomponents();
|
||||
Eigen::Vector3d v = e - s;
|
||||
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
|
||||
std::function<Eigen::Matrix4d(double)> fn = [s, v](double u) {
|
||||
Eigen::Vector3d o(s + u * v), axis(0, 0, 1), refDirection(v);
|
||||
auto Y = axis.cross(refDirection).normalized();
|
||||
axis = refDirection.cross(Y).normalized();
|
||||
return taxonomy::make<taxonomy::matrix4>(o, axis, refDirection)->components();
|
||||
};
|
||||
(*pwf_)->spans.emplace_back(l, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return pwf_.is_initialized();
|
||||
}
|
||||
|
||||
operator taxonomy::piecewise_function::ptr() const {
|
||||
return *pwf_;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef TAXONOMY_USE_SHARED_PTR
|
||||
template <typename T, typename U>
|
||||
@@ -1104,6 +1169,10 @@ typedef item const* ptr;
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
loop_to_piecewise_function_upgrade<T> pwupg(u);
|
||||
if (pwupg) {
|
||||
return pwupg;
|
||||
}
|
||||
return std::static_pointer_cast<T>(u);
|
||||
}
|
||||
template <typename T, typename U>
|
||||
@@ -1112,7 +1181,11 @@ typedef item const* ptr;
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
return std::dynamic_pointer_cast<T>(u);
|
||||
loop_to_piecewise_function_upgrade<T> pwupg(u);
|
||||
if (pwupg) {
|
||||
return pwupg;
|
||||
}
|
||||
return std::dynamic_pointer_cast<T>(u);
|
||||
}
|
||||
#endif
|
||||
#ifdef TAXONOMY_USE_UNIQUE_PTR
|
||||
@@ -1122,7 +1195,11 @@ typedef item const* ptr;
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
return static_cast<T*>(&*u);
|
||||
loop_to_piecewise_function_upgrade<T> pwupg(u);
|
||||
if (pwupg) {
|
||||
return pwupg;
|
||||
}
|
||||
return static_cast<T*>(&*u);
|
||||
}
|
||||
template <typename T, typename U>
|
||||
T* dcast(const std::unique_ptr<U>& u) {
|
||||
@@ -1130,7 +1207,11 @@ typedef item const* ptr;
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
return dynamic_cast<T*>(&*u);
|
||||
loop_to_piecewise_function_upgrade<T> pwupg(u);
|
||||
if (pwupg) {
|
||||
return pwupg;
|
||||
}
|
||||
return dynamic_cast<T*>(&*u);
|
||||
}
|
||||
#endif
|
||||
#ifdef TAXONOMY_USE_NAKED_PTR
|
||||
@@ -1140,7 +1221,11 @@ typedef item const* ptr;
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
return std::static_cast<T*>(u);
|
||||
loop_to_piecewise_function_upgrade<T> pwupg(u);
|
||||
if (pwupg) {
|
||||
return pwupg;
|
||||
}
|
||||
return std::static_cast<T*>(u);
|
||||
}
|
||||
template <typename T, typename U>
|
||||
T* dcast(const U*& u) {
|
||||
@@ -1148,7 +1233,11 @@ typedef item const* ptr;
|
||||
if (upg) {
|
||||
return upg;
|
||||
}
|
||||
return std::dynamic_cast<T*>(u);
|
||||
loop_to_piecewise_function_upgrade<T> pwupg(u);
|
||||
if (pwupg) {
|
||||
return pwupg;
|
||||
}
|
||||
return std::dynamic_cast<T*>(u);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user