Decouples evaluation of a piecewise_function from the function itself (#5344)

This commit is contained in:
Richard Brice
2024-09-10 10:11:17 -07:00
committed by GitHub
parent 67a7e713b2
commit cc7171060f
17 changed files with 240 additions and 221 deletions
+3 -1
View File
@@ -3,6 +3,7 @@
#include "../ifcgeom/IfcGeomElement.h"
#include "../ifcgeom/ConversionSettings.h"
#include "../ifcgeom/abstract_mapping.h"
#include "../ifcgeom/piecewise_function_evaluator.h"
#ifdef IFOPSH_WITH_OPENCASCADE
#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h"
@@ -220,7 +221,8 @@ bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonom
}
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::piecewise_function::ptr item, IfcGeom::ConversionResults& cs) {
auto expl = item->evaluate();
piecewise_function_evaluator evaluator(item);
auto expl = evaluator.evaluate();
expl->instance = item->instance;
return convert(expl, cs);
}
+1 -1
View File
@@ -92,7 +92,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
return loop;
}
else {
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0,pwfs,&settings_,inst);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0,pwfs,inst);
return pwf;
}
}
+1 -1
View File
@@ -961,7 +961,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCurveSegment* inst) {
taxonomy::piecewise_function::spans_t spans;
spans.emplace_back(fabs(length), fn);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0, spans,&settings_,inst);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0, spans,inst);
return pwf;
}
@@ -18,6 +18,7 @@
********************************************************************************/
#include "mapping.h"
#include "../piecewise_function_evaluator.h"
#define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell::geometry;
@@ -34,6 +35,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcFixedReferenceSweptAreaSolid
// @todo currently only the case is handled where directrix returns a piecewise_function
if (auto pwf = taxonomy::dcast<taxonomy::piecewise_function>(dir)) {
piecewise_function_evaluator evaluator(pwf,&settings_);
double start = 0;
double end = pwf->length();
#ifdef SCHEMA_HAS_IfcDirectrixCurveSweptAreaSolid
@@ -53,20 +55,9 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcFixedReferenceSweptAreaSolid
}
}
#endif
auto curve_length = end - start;
auto param_type = settings_.get<ifcopenshell::geometry::settings::PiecewiseStepType>().get();
auto param = settings_.get<ifcopenshell::geometry::settings::PiecewiseStepParam>().get();
size_t num_steps = 0;
if (param_type == ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE) {
// parameter is max step size
num_steps = (size_t) std::ceil(curve_length / param);
} else {
// parameter is minimum number of steps
num_steps = (size_t) std::ceil(param);
}
for (size_t i = 0; i <= num_steps; ++i) {
auto distalong = start + curve_length / num_steps * i;
auto m4 = pwf->evaluate(distalong);
auto evaluation_points = evaluator.evaluation_points();
for (const auto& dist_along : evaluation_points) {
auto m4 = evaluator.evaluate(dist_along);
/*
std::stringstream ss;
+7 -5
View File
@@ -18,6 +18,7 @@
********************************************************************************/
#include "mapping.h"
#include "../piecewise_function_evaluator.h"
#define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell::geometry;
@@ -55,7 +56,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) {
double gradient_start = m(0, 3); // start of vertical (row 0, col 3) - "Distance Along" horizontal curve
// create the vertical pwf
auto vertical = taxonomy::make<taxonomy::piecewise_function>(gradient_start, pwfs, &settings_);
auto vertical = taxonomy::make<taxonomy::piecewise_function>(gradient_start, pwfs);
// Determine the valid domain of the PWF... the valid domain is where both
// the base curve and gradient curves are defined
@@ -69,11 +70,12 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) {
}
// define the callback function for the gradient curve
auto composition = [horizontal, vertical](double u)->Eigen::Matrix4d {
piecewise_function_evaluator horizontal_evaluator(horizontal, &settings_), vertical_evaluator(vertical, &settings_);
auto composition = [horizontal_evaluator, vertical_evaluator,start=vertical->start()](double u) -> Eigen::Matrix4d {
// u is distance from start of gradient curve (vertical)
// add vertical->start() to u to get distance from start of horizontal
auto xy = horizontal->evaluate(u + vertical->start());
auto uz = vertical->evaluate(u);
auto xy = horizontal_evaluator.evaluate(u + start);
auto uz = vertical_evaluator.evaluate(u);
uz.col(3)(0) = 0.0; // x is distance along. zero it out so it doesn't add to the x from horizontal
uz.col(1).swap(uz.col(2)); // uz is 2D in distance along - y plane, swap y and z so elevations become z
@@ -86,7 +88,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) {
taxonomy::piecewise_function::spans_t spans;
spans.emplace_back(length, composition);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start, spans, &settings_, inst);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start, spans, inst);
return pwf;
}
@@ -19,6 +19,7 @@
#include "mapping.h"
#include "../profile_helper.h"
#include "../piecewise_function_evaluator.h"
#define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell::geometry;
@@ -144,11 +145,12 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
offset_spans.emplace_back(l, fn);
}
auto offsets = taxonomy::make<taxonomy::piecewise_function>(start,offset_spans,&settings_);
auto offsets = taxonomy::make<taxonomy::piecewise_function>(start,offset_spans);
auto composition = [pw_curve, offsets](double u) -> Eigen::Matrix4d {
auto p = pw_curve->evaluate(u);
auto offset = offsets->evaluate(u);
piecewise_function_evaluator pw_evaluator(pw_curve, &settings_), offsets_evaluator(offsets, &settings_);
auto composition = [pw_evaluator, offsets_evaluator](double u) -> Eigen::Matrix4d {
auto p = pw_evaluator.evaluate(u);
auto offset = offsets_evaluator.evaluate(u);
Eigen::Matrix4d m = p * offset;
return m;
};
@@ -157,7 +159,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
// this may change depending on decisions in the bSI-IF
taxonomy::piecewise_function::spans_t spans;
spans.emplace_back(basis_curve_length, composition);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start,spans,&settings_,inst);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start,spans,inst);
return pwf;
}
@@ -19,6 +19,7 @@
#include "mapping.h"
#include "../profile_helper.h"
#include "../piecewise_function_evaluator.h"
#define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell::geometry;
@@ -31,7 +32,8 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPointByDistanceExpression* i
//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);
piecewise_function_evaluator evaluator(pw_curve,&settings_);
auto m = evaluator.evaluate(u);
auto o = m.col(3).head<3>();
auto z = m.col(2).head<3>();
@@ -22,6 +22,7 @@
using namespace ifcopenshell::geometry;
#include "../../ifcgeom/profile_helper.h"
#include "../piecewise_function_evaluator.h"
#include <boost/range/combine.hpp>
@@ -114,7 +115,8 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSolidHorizontal* in
// @todo currently only the case is handled where directrix returns a piecewise_function
// @todo this "if" statement is not really required because the function returns at the start if the Directrix is not a piecewise function
if (pwf) {
double start = std::max(0., cross_sections.front().dist_along);
piecewise_function_evaluator evaluator(pwf, &settings_);
double start = std::max(0., cross_sections.front().dist_along);
double end = std::min(pwf->length(), cross_sections.back().dist_along);
if (end - start < 1.e-9) {
@@ -232,7 +234,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSectionedSolidHorizontal* in
}
}
auto m4 = pwf->evaluate(dist_along);
auto m4 = evaluator.evaluate(dist_along);
/* {
std::wcout << "#" << pwf->instance->data().id() << " " << dist_along << ": " << m4.col(3).row(2).value() << std::endl;
}*/
@@ -21,6 +21,8 @@
#define mapping POSTFIX_SCHEMA(mapping)
using namespace ifcopenshell::geometry;
#include "../piecewise_function_evaluator.h"
#ifdef SCHEMA_HAS_IfcSegmentedReferenceCurve
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* inst) {
@@ -53,7 +55,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins
const Eigen::Matrix4d& m = p->ccomponents();
double cant_start = m(0, 3); // start of cant curve
auto cant = taxonomy::make<taxonomy::piecewise_function>(cant_start,pwfs,&settings_);
auto cant = taxonomy::make<taxonomy::piecewise_function>(cant_start,pwfs);
// Determine the valid domain of the PWF... the valid domain is where
// horizontal, gradient and cant curves are defined
@@ -68,11 +70,12 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins
}
// define the callback function for the segmented reference curve
auto composition = [gradient, cant](double u)->Eigen::Matrix4d {
piecewise_function_evaluator gradient_evaluator(gradient, &settings_), cant_evaluator(cant, &settings_);
auto composition = [gradient_evaluator, cant_evaluator, start = cant->start()](double u) -> Eigen::Matrix4d {
// u is distance from start of cant curve
// add cant->start() to u to get the distance from start of gradient curve
auto g = gradient->evaluate(u+cant->start());
auto c = cant->evaluate(u);
auto g = gradient_evaluator.evaluate(u + start);
auto c = cant_evaluator.evaluate(u);
// Need to multiply g and c so the axis vectors
// from cant have the correct rotation applied so
@@ -105,7 +108,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins
taxonomy::piecewise_function::spans_t spans;
spans.emplace_back(length, composition);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start, spans, &settings_, inst);
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start, spans, inst);
return pwf;
}
@@ -0,0 +1,103 @@
#include "piecewise_function_evaluator.h"
#include "profile_helper.h"
using namespace ifcopenshell::geometry;
piecewise_function_evaluator::piecewise_function_evaluator(taxonomy::piecewise_function::const_ptr pwf, ifcopenshell::geometry::Settings* settings) : pwf_(pwf) {
if (settings) {
settings_ = *settings;
}
}
std::vector<double> piecewise_function_evaluator::evaluation_points() const {
if (!eval_points_.has_value()) {
double curve_length = pwf_->length();
auto param_type = settings_.get<ifcopenshell::geometry::settings::PiecewiseStepType>().get();
auto param = settings_.get<ifcopenshell::geometry::settings::PiecewiseStepParam>().get();
unsigned num_steps = 0;
if (param_type == ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE) {
// parameter is max step size
num_steps = (unsigned)std::ceil(curve_length / param);
} else {
// parameter is minimum number of steps
num_steps = (unsigned)std::ceil(param);
}
eval_points_ = evaluation_points(pwf_->start(), pwf_->start() + curve_length, num_steps);
}
return *eval_points_;
}
std::vector<double> piecewise_function_evaluator::evaluation_points(double ustart, double uend, unsigned nsteps) const {
double curve_length = pwf_->length();
ustart = std::max(pwf_->start(), ustart);
uend = std::min(uend, pwf_->start() + curve_length);
nsteps = std::max(1u, nsteps); // never have fewer than 1 step
auto resolution = (uend - ustart) / nsteps;
std::vector<double> u_values;
u_values.reserve(nsteps);
for (unsigned i = 0; i <= nsteps; ++i) {
auto u = resolution * i + ustart;
u_values.push_back(u);
}
return u_values;
}
taxonomy::item::ptr piecewise_function_evaluator::evaluate() const {
return evaluate(evaluation_points());
}
taxonomy::item::ptr piecewise_function_evaluator::evaluate(double ustart, double uend, unsigned nsteps) const {
return evaluate(evaluation_points(ustart, uend, nsteps));
}
Eigen::Matrix4d piecewise_function_evaluator::evaluate(double u) const {
// assume monotonic evaluation and store last evaluated segment
if (current_span_fn_ == nullptr || (u < current_span_start_ || current_span_end_ < u)) {
// there isn't a current span or u is outside the range of the current span
// get a new "current span"
std::tie(current_span_start_, current_span_end_, current_span_fn_) = get_span(u);
}
u -= current_span_start_; // make u relative to start of span
return (*current_span_fn_)(u);
}
taxonomy::item::ptr piecewise_function_evaluator::evaluate(const std::vector<double>& dist) const {
std::vector<taxonomy::point3::ptr> polygon;
polygon.reserve(dist.size());
for (auto& u : dist) {
Eigen::Matrix4d m = evaluate(u);
polygon.push_back(taxonomy::make<taxonomy::point3>(m(0, 3), m(1, 3), m(2, 3)));
}
return polygon_from_points(polygon);
}
std::tuple<double, double, const std::function<Eigen::Matrix4d(double u)>*> piecewise_function_evaluator::get_span(double u) const {
// force u to be within bounds of the curve
double s = pwf_->start();
double e = pwf_->end();
u = std::max(s, u);
u = std::min(u, e);
double span_start = s;
for (auto& [length, fn] : pwf_->spans()) {
double span_end = span_start + length;
auto tolerance = settings_.get<ifcopenshell::geometry::settings::Precision>().get();
if (span_start <= u && u < span_end + tolerance) {
return {span_start, span_end, &fn};
}
span_start += length;
}
Logger::Error("piecewise_function_impl::get_span span not found.");
return {0, 0, nullptr};
}
@@ -0,0 +1,58 @@
#ifndef ITERATOR_PWF_EVALUATOR_H
#define ITERATOR_PWF_EVALUATOR_H
#include "../ifcgeom/taxonomy.h"
#include <boost/function.hpp>
namespace ifcopenshell { namespace geometry {
/// @brief utility class to evaluate piecewise_function objects
class piecewise_function_evaluator {
public:
piecewise_function_evaluator(taxonomy::piecewise_function::const_ptr pwf, ifcopenshell::geometry::Settings* settings=nullptr);
/// @brief returns a vector of "distance along" points where the evaluate function computes loop points
std::vector<double> evaluation_points() const;
/// @brief returns a vector of "distance along" points between ustart and uend
/// @param ustart starting location
/// @param uend ending location
/// @param nsteps number of steps to evaluate
std::vector<double> evaluation_points(double ustart, double uend, unsigned nsteps) const;
/// @brief evaluates the piecewise function between start and end
/// evaluation point step size is taken from the settings object
taxonomy::item::ptr evaluate() const;
/// @brief evaluates the piecewise function between ustart and uend
/// if ustart and uend are out of range, the range of values evaluated
/// are constrained to start_ and start_+length_
/// @param ustart starting location
/// @param uend ending location
/// @param nsteps number of steps to evaluate
/// @return taxonomy::loop::ptr
taxonomy::item::ptr evaluate(double ustart, double uend, unsigned nsteps) const;
/// @brief evaluates the piecewise function at u
/// @param u u is constrained to be between start_ and start_+length
/// @return 4x4 placement matrix
Eigen::Matrix4d evaluate(double u) const;
private:
taxonomy::item::ptr evaluate(const std::vector<double>& dist) const;
std::tuple<double, double, const std::function<Eigen::Matrix4d(double u)>*> get_span(double u) const;
taxonomy::piecewise_function::const_ptr pwf_;
ifcopenshell::geometry::Settings settings_;
mutable double current_span_start_ = 0;
mutable double current_span_end_ = 0;
mutable const std::function<Eigen::Matrix4d(double u)>* current_span_fn_ = nullptr;
mutable boost::optional<std::vector<double>> eval_points_;
};
}}
#endif
+22 -79
View File
@@ -7,97 +7,40 @@ namespace geometry {
namespace taxonomy {
std::vector<double> ifcopenshell::geometry::taxonomy::piecewise_function_impl::evaluation_points() const {
if (!eval_points_.has_value()) {
double curve_length = length();
piecewise_function_impl::piecewise_function_impl(double start, const spans_t& s) : start_(start), spans_(s) {
}
auto param_type = settings_ ? settings_->get<ifcopenshell::geometry::settings::PiecewiseStepType>().get() : ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE;
auto param = settings_ ? settings_->get<ifcopenshell::geometry::settings::PiecewiseStepParam>().get() : 0.5;
unsigned num_steps = 0;
if (param_type == ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE) {
// parameter is max step size
num_steps = (unsigned)std::ceil(curve_length / param);
} else {
// parameter is minimum number of steps
num_steps = (unsigned)std::ceil(param);
}
eval_points_ = evaluation_points(start_, start_ + curve_length, num_steps);
piecewise_function_impl::piecewise_function_impl(double start, const std::vector<piecewise_function::ptr>& pwfs) : start_(start) {
for (auto& pwf : pwfs) {
spans_.insert(spans_.end(), pwf->spans().begin(), pwf->spans().end());
}
return *eval_points_;
}
std::vector<double> ifcopenshell::geometry::taxonomy::piecewise_function_impl::evaluation_points(double ustart, double uend, unsigned nsteps) const {
double curve_length = length();
ustart = std::max(start_, ustart);
uend = std::min(uend, start_ + curve_length);
const piecewise_function_impl::spans_t& piecewise_function_impl::spans() const { return spans_; }
nsteps = std::max(1u, nsteps); // never have fewer than 1 step
bool piecewise_function_impl::is_empty() const { return spans_.empty(); }
auto resolution = (uend - ustart) / nsteps;
std::vector<double> u_values;
u_values.reserve(nsteps);
for (unsigned i = 0; i <= nsteps; ++i) {
auto u = resolution * i + ustart;
u_values.push_back(u);
}
return u_values;
double piecewise_function_impl::start() const {
return start_;
}
ifcopenshell::geometry::taxonomy::item::ptr ifcopenshell::geometry::taxonomy::piecewise_function_impl::evaluate() const {
return evaluate(evaluation_points());
double piecewise_function_impl::end() const {
return start_ + length();
}
item::ptr ifcopenshell::geometry::taxonomy::piecewise_function_impl::evaluate(double ustart, double uend, unsigned nsteps) const {
return evaluate(evaluation_points(ustart, uend, nsteps));
double piecewise_function_impl::length() const {
return std::accumulate(spans_.begin(), spans_.end(), 0.0, [](const auto& v, const auto& s) { return v + s.first; });
// this is a secondary option where we only compute length once and cache it.
// mutex is needed to prevent interruption of the accumulation if there is multi-threading
// skipping this detail for now and just adding up the span lengths every time
//if (!length_.has_value()) {
// length_ = std::accumulate(spans_.begin(), spans_.end(), 0.0, [](const auto& v, const auto& s) { return v + s.first; });
//}
//return *length_;
}
item::ptr ifcopenshell::geometry::taxonomy::piecewise_function_impl::evaluate(const std::vector<double>& dist) const {
std::vector<taxonomy::point3::ptr> polygon;
polygon.reserve(dist.size());
for (auto& u : dist) {
Eigen::Matrix4d m = evaluate(u);
polygon.push_back(taxonomy::make<taxonomy::point3>(m.col(3)(0), m.col(3)(1), m.col(3)(2)));
}
return polygon_from_points(polygon);
}
Eigen::Matrix4d ifcopenshell::geometry::taxonomy::piecewise_function_impl::evaluate(double u) const {
// assume monotonic evaluation and store last evaluated segment
if (current_span_fn_ == nullptr || (u < current_span_start_ || current_span_end_ < u)) {
// there isn't a current span or u is outside the range of the current span
// get a new "current span"
std::tie(current_span_start_, current_span_end_, current_span_fn_) = get_span(u);
}
u -= current_span_start_; // make u relative to start of span
return (*current_span_fn_)(u);
}
std::tuple<double, double, const std::function<Eigen::Matrix4d(double u)>*> ifcopenshell::geometry::taxonomy::piecewise_function_impl::get_span(double u) const {
// force u to be within bounds of the curve
double s = start();
double e = end();
u = std::max(s, u);
u = std::min(u, e);
double span_start = s;
for (auto& [length, fn] : spans_) {
double span_end = span_start + length;
auto tolerance = settings_ ? settings_->get<ifcopenshell::geometry::settings::Precision>().get() : 0.001;
if (span_start <= u && u < span_end + tolerance) {
return {span_start, span_end, &fn};
}
span_start += length;
}
Logger::Error("piecewise_function_impl::get_span span not found.");
return {0, 0, nullptr};
}
piecewise_function_impl* piecewise_function_impl::clone_() const { return new piecewise_function_impl(*this); }
} // namespace taxonomy
+9 -65
View File
@@ -12,79 +12,23 @@ namespace taxonomy {
struct piecewise_function_impl {
using spans_t = std::vector<std::pair<double, std::function<Eigen::Matrix4d(double u)>>>;
piecewise_function_impl(double start, const spans_t& s, ifcopenshell::geometry::Settings* settings = nullptr) : start_(start),
settings_(settings),
spans_(s){};
piecewise_function_impl(double start, const std::vector<piecewise_function::ptr>& pwfs, ifcopenshell::geometry::Settings* settings = nullptr) : start_(start),
settings_(settings) {
for (auto& pwf : pwfs) {
spans_.insert(spans_.end(), pwf->spans().begin(), pwf->spans().end());
}
};
piecewise_function_impl(double start, const spans_t& s);
piecewise_function_impl(double start, const std::vector<piecewise_function::ptr>& pwfs);
piecewise_function_impl(piecewise_function_impl&&) = default;
piecewise_function_impl(const piecewise_function_impl&) = default;
const ifcopenshell::geometry::Settings* settings_ = nullptr;
const spans_t& spans() const { return spans_; }
bool is_empty() const { return spans_.empty(); }
double start() const {
return start_;
}
double end() const {
return start_ + length();
}
double length() const {
if (!length_.has_value()) {
length_ = std::accumulate(spans_.begin(), spans_.end(), 0.0, [](const auto& v, const auto& s) { return v + s.first; });
}
return *length_;
}
piecewise_function_impl* clone_() const { return new piecewise_function_impl(*this); }
/// @brief returns a vector of "distance along" points where the evaluate function computes loop points
std::vector<double> evaluation_points() const;
/// @brief returns a vector of "distance along" points between ustart and uend
/// @param ustart starting location
/// @param uend ending location
/// @param nsteps number of steps to evaluate
std::vector<double> evaluation_points(double ustart, double uend, unsigned nsteps) const;
/// @brief evaluates the piecewise function between start and end
/// evaluation point step size is taken from the settings object
item::ptr evaluate() const;
/// @brief evaluates the piecewise function between ustart and uend
/// if ustart and uend are out of range, the range of values evaluated
/// are constrained to start_ and start_+length_
/// @param ustart starting location
/// @param uend ending location
/// @param nsteps number of steps to evaluate
/// @return taxonomy::loop::ptr
item::ptr evaluate(double ustart, double uend, unsigned nsteps) const;
/// @brief evaluates the piecewise function at u
/// @param u u is constrained to be between start_ and start_+length
/// @return 4x4 placement matrix
Eigen::Matrix4d evaluate(double u) const;
const spans_t& spans() const;
bool is_empty() const;
double start() const;
double end() const;
double length() const;
piecewise_function_impl* clone_() const;
private:
item::ptr evaluate(const std::vector<double>& dist) const;
std::tuple<double, double, const std::function<Eigen::Matrix4d(double u)>*> get_span(double u) const;
double start_ = 0.0; // starting value of the pwf
spans_t spans_;
mutable double current_span_start_ = 0;
mutable double current_span_end_ = 0;
mutable const std::function<Eigen::Matrix4d(double u)>* current_span_fn_ = nullptr;
mutable boost::optional<double> length_;
mutable boost::optional<std::vector<double>> eval_points_;
//mutable boost::optional<double> length_; // used for length() method
};
} // namespace taxonomy
+4 -9
View File
@@ -464,12 +464,12 @@ ifcopenshell::geometry::taxonomy::solid::ptr ifcopenshell::geometry::create_box(
}
///////////////////
piecewise_function::piecewise_function(double start, const spans_t& s, ifcopenshell::geometry::Settings* settings, const IfcUtil::IfcBaseInterface* instance) : implicit_item(instance) {
impl_ = new piecewise_function_impl(start, s, settings);
piecewise_function::piecewise_function(double start, const spans_t& s, const IfcUtil::IfcBaseInterface* instance) : implicit_item(instance) {
impl_ = new piecewise_function_impl(start, s);
}
piecewise_function::piecewise_function(double start, const std::vector<piecewise_function::ptr>& pwfs, ifcopenshell::geometry::Settings* settings, const IfcUtil::IfcBaseInterface* instance) : implicit_item(instance) {
impl_ = new piecewise_function_impl(start, pwfs, settings);
piecewise_function::piecewise_function(double start, const std::vector<piecewise_function::ptr>& pwfs, const IfcUtil::IfcBaseInterface* instance) : implicit_item(instance) {
impl_ = new piecewise_function_impl(start, pwfs);
};
piecewise_function::piecewise_function(const piecewise_function& other) : implicit_item(other) {
@@ -486,11 +486,6 @@ double piecewise_function::start() const { return impl_->start(); }
double piecewise_function::end() const { return impl_->end(); }
double piecewise_function::length() const { return impl_->length(); }
std::vector<double> piecewise_function::evaluation_points() const { return impl_->evaluation_points(); }
std::vector<double> piecewise_function::evaluation_points(double ustart, double uend, unsigned nsteps) const { return impl_->evaluation_points(ustart, uend, nsteps); }
item::ptr piecewise_function::evaluate() const { return impl_->evaluate(); }
item::ptr piecewise_function::evaluate(double ustart, double uend, unsigned nsteps) const { return impl_->evaluate(ustart, uend, nsteps); }
Eigen::Matrix4d piecewise_function::evaluate(double u) const { return impl_->evaluate(u); }
ifcopenshell::geometry::taxonomy::collection::ptr ifcopenshell::geometry::flatten(const taxonomy::collection::ptr& deep) {
auto flat = make<taxonomy::collection>();
+2 -33
View File
@@ -347,8 +347,6 @@ typedef item const* ptr;
struct implicit_item : public geom_item {
DECLARE_PTR(implicit_item)
using geom_item::geom_item;
virtual item::ptr evaluate() const = 0;
};
struct piecewise_function_impl; // forward declaration
@@ -357,14 +355,12 @@ typedef item const* ptr;
using spans_t = std::vector<std::pair<double, std::function<Eigen::Matrix4d(double u)>>>;
piecewise_function(double start, const spans_t& s, ifcopenshell::geometry::Settings* settings = nullptr, const IfcUtil::IfcBaseInterface* instance = nullptr);
piecewise_function(double start, const std::vector<piecewise_function::ptr>& pwfs, ifcopenshell::geometry::Settings* settings = nullptr, const IfcUtil::IfcBaseInterface* instance = nullptr);
piecewise_function(double start, const spans_t& s, const IfcUtil::IfcBaseInterface* instance = nullptr);
piecewise_function(double start, const std::vector<piecewise_function::ptr>& pwfs, const IfcUtil::IfcBaseInterface* instance = nullptr);
piecewise_function(piecewise_function&&) = default;
piecewise_function(const piecewise_function&);
virtual ~piecewise_function();
const ifcopenshell::geometry::Settings* settings_ = nullptr;
const spans_t& spans() const;
bool is_empty() const;
double start() const;
@@ -379,33 +375,6 @@ typedef item const* ptr;
return boost::hash<decltype(v)>{}(v);
}
/// @brief returns a vector of "distance along" points where the evaluate function computes loop points
std::vector<double> evaluation_points() const;
/// @brief returns a vector of "distance along" points between ustart and uend
/// @param ustart starting location
/// @param uend ending location
/// @param nsteps number of steps to evaluate
std::vector<double> evaluation_points(double ustart, double uend, unsigned nsteps) const;
/// @brief evaluates the piecewise function between start and end
/// evaluation point step size is taken from the settings object
item::ptr evaluate() const override;
/// @brief evaluates the piecewise function between ustart and uend
/// if ustart and uend are out of range, the range of values evaluated
/// are constrained to start_ and start_+length_
/// @param ustart starting location
/// @param uend ending location
/// @param nsteps number of steps to evaluate
/// @return taxonomy::loop::ptr
item::ptr evaluate(double ustart, double uend, unsigned nsteps) const;
/// @brief evaluates the piecewise function at u
/// @param u u is constrained to be between start_ and start_+length
/// @return 4x4 placement matrix
Eigen::Matrix4d evaluate(double u) const;
private:
// note: it would be better if this were a std::unique_ptr, but that requires having the full definition
// of piecewise_function_impl in this header file, which defeats the purpose of the PIMPL idiom.
+1
View File
@@ -246,6 +246,7 @@ namespace {
%include "../ifcgeom/Iterator.h"
%include "../ifcgeom/GeometrySerializer.h"
%include "../ifcgeom/taxonomy.h"
%include "../ifcgeom/piecewise_function_evaluator.h"
%include "../serializers/SvgSerializer.h"
%include "../serializers/HdfSerializer.h"
+2
View File
@@ -84,6 +84,7 @@
%{
#include "../ifcgeom/Iterator.h"
#include "../ifcgeom/taxonomy.h"
#include "../ifcgeom/piecewise_function_evaluator.h"
#ifdef IFOPSH_WITH_OPENCASCADE
#include "../ifcgeom/Serialization/Serialization.h"
#include "../ifcgeom/kernels/opencascade/IfcGeomTree.h"
@@ -159,6 +160,7 @@
%module ifcopenshell_wrapper %{
#include "../ifcgeom/Converter.h"
#include "../ifcgeom/taxonomy.h"
#include "../ifcgeom/piecewise_function_evaluator.h"
#ifdef IFOPSH_WITH_OPENCASCADE
#include "../ifcgeom/Serialization/Serialization.h"
#include "../ifcgeom/kernels/opencascade/IfcGeomTree.h"