mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 01:11:40 +00:00
Refactors alignment geometry
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
#include "../ifcgeom/IfcGeomElement.h"
|
||||
#include "../ifcgeom/ConversionSettings.h"
|
||||
#include "../ifcgeom/abstract_mapping.h"
|
||||
#include "../ifcgeom/piecewise_function_evaluator.h"
|
||||
#include "../ifcgeom/function_item_evaluator.h"
|
||||
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
#include "../ifcgeom/kernels/opencascade/OpenCascadeKernel.h"
|
||||
@@ -71,6 +71,7 @@ bool is_valid_for_kernel(const ifcopenshell::geometry::kernels::AbstractKernel*
|
||||
return dynamic_cast<ifcopenshell::geometry::CgalShape*>(shp.Shape().get()) != nullptr;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
class HybridKernel : public ifcopenshell::geometry::kernels::AbstractKernel {
|
||||
@@ -237,9 +238,44 @@ bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonom
|
||||
return r.size() > s;
|
||||
}
|
||||
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::piecewise_function::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
piecewise_function_evaluator evaluator(item);
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::function_item::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
function_item_evaluator evaluator(settings(),item);
|
||||
auto expl = evaluator.evaluate();
|
||||
expl->instance = item->instance;
|
||||
return convert(expl, cs);
|
||||
}
|
||||
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::functor_item::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
function_item_evaluator evaluator(settings(), item);
|
||||
auto expl = evaluator.evaluate();
|
||||
expl->instance = item->instance;
|
||||
return convert(expl, cs);
|
||||
}
|
||||
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::piecewise_function::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
function_item_evaluator evaluator(settings(), item);
|
||||
auto expl = evaluator.evaluate();
|
||||
expl->instance = item->instance;
|
||||
return convert(expl, cs);
|
||||
}
|
||||
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::gradient_function::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
function_item_evaluator evaluator(settings(), item);
|
||||
auto expl = evaluator.evaluate();
|
||||
expl->instance = item->instance;
|
||||
return convert(expl, cs);
|
||||
}
|
||||
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::cant_function::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
function_item_evaluator evaluator(settings(), item);
|
||||
auto expl = evaluator.evaluate();
|
||||
expl->instance = item->instance;
|
||||
return convert(expl, cs);
|
||||
}
|
||||
|
||||
bool ifcopenshell::geometry::kernels::AbstractKernel::convert_impl(const taxonomy::offset_function::ptr item, IfcGeom::ConversionResults& cs) {
|
||||
function_item_evaluator evaluator(settings(), item);
|
||||
auto expl = evaluator.evaluate();
|
||||
expl->instance = item->instance;
|
||||
return convert(expl, cs);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,12 @@ namespace ifcopenshell {
|
||||
virtual bool convert_impl(const taxonomy::sweep_along_curve::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); }
|
||||
virtual bool convert_impl(const taxonomy::loft::ptr, IfcGeom::ConversionResults&) { throw not_implemented_error(); }
|
||||
virtual bool convert_impl(const taxonomy::collection::ptr, IfcGeom::ConversionResults&);
|
||||
virtual bool convert_impl(const taxonomy::piecewise_function::ptr item, IfcGeom::ConversionResults& cs);
|
||||
virtual bool convert_impl(const taxonomy::function_item::ptr item, IfcGeom::ConversionResults& cs);
|
||||
virtual bool convert_impl(const taxonomy::functor_item::ptr item, IfcGeom::ConversionResults& cs);
|
||||
virtual bool convert_impl(const taxonomy::piecewise_function::ptr item, IfcGeom::ConversionResults& cs);
|
||||
virtual bool convert_impl(const taxonomy::gradient_function::ptr item, IfcGeom::ConversionResults& cs);
|
||||
virtual bool convert_impl(const taxonomy::cant_function::ptr item, IfcGeom::ConversionResults& cs);
|
||||
virtual bool convert_impl(const taxonomy::offset_function::ptr item, IfcGeom::ConversionResults& cs);
|
||||
|
||||
/*
|
||||
virtual void set_offset(const std::array<double, 3> &p_offset);
|
||||
|
||||
@@ -49,7 +49,7 @@ std::istream& ifcopenshell::geometry::settings::operator>>(std::istream& in, Ite
|
||||
return in;
|
||||
}
|
||||
|
||||
std::istream& ifcopenshell::geometry::settings::operator>>(std::istream& in, PiecewiseStepMethod& ioo) {
|
||||
std::istream& ifcopenshell::geometry::settings::operator>>(std::istream& in, FunctionStepMethod& ioo) {
|
||||
std::string token;
|
||||
in >> token;
|
||||
boost::to_upper(token);
|
||||
|
||||
@@ -365,22 +365,22 @@ namespace ifcopenshell {
|
||||
static constexpr bool defaultvalue = false;
|
||||
};
|
||||
|
||||
enum PiecewiseStepMethod {
|
||||
enum FunctionStepMethod {
|
||||
MAXSTEPSIZE,
|
||||
MINSTEPS };
|
||||
|
||||
std::istream& operator>>(std::istream& in, PiecewiseStepMethod& ioo);
|
||||
std::istream& operator>>(std::istream& in, FunctionStepMethod& ioo);
|
||||
|
||||
struct PiecewiseStepType : public SettingBase<PiecewiseStepType, PiecewiseStepMethod> {
|
||||
static constexpr const char* const name = "piecewise-step-type";
|
||||
static constexpr const char* const description = "Indicates the method used for defining step size when evaluating piecewise curves. Provides interpretation of piecewise-step-param";
|
||||
static constexpr PiecewiseStepMethod defaultvalue = MAXSTEPSIZE;
|
||||
struct FunctionStepType : public SettingBase<FunctionStepType, FunctionStepMethod> {
|
||||
static constexpr const char* const name = "function-step-type";
|
||||
static constexpr const char* const description = "Indicates the method used for defining step size when evaluating function-based curves. Provides interpretation of function-step-param";
|
||||
static constexpr FunctionStepMethod defaultvalue = MAXSTEPSIZE;
|
||||
};
|
||||
|
||||
struct PiecewiseStepParam : public SettingBase<PiecewiseStepParam, double> {
|
||||
static constexpr const char* const name = "piecewise-step-param";
|
||||
static constexpr const char* const description = "Indicates the parameter value for defining step size when evaluating piecewise curves.";
|
||||
static constexpr double defaultvalue = 0.5; // ceiling of this value is used when PiecewiseStepMethod is MinSteps
|
||||
struct FunctionStepParam : public SettingBase<FunctionStepParam, double> {
|
||||
static constexpr const char* const name = "function-step-param";
|
||||
static constexpr const char* const description = "Indicates the parameter value for defining step size when evaluating function-based curves.";
|
||||
static constexpr double defaultvalue = 0.5; // ceiling of this value is used when FunctionStepMethod is MinSteps
|
||||
};
|
||||
|
||||
struct ModelOffset : public SettingBase<ModelOffset, std::vector<double>> {
|
||||
@@ -413,7 +413,7 @@ namespace ifcopenshell {
|
||||
template <typename settings_t>
|
||||
class IFC_GEOM_API SettingsContainer {
|
||||
public:
|
||||
typedef boost::variant<bool, int, double, std::string, std::set<int>, std::set<std::string>, std::vector<double>, IteratorOutputOptions, PiecewiseStepMethod, OutputDimensionalityTypes, TriangulationMethod> value_variant_t;
|
||||
typedef boost::variant<bool, int, double, std::string, std::set<int>, std::set<std::string>, std::vector<double>, IteratorOutputOptions, FunctionStepMethod, OutputDimensionalityTypes, TriangulationMethod> value_variant_t;
|
||||
private:
|
||||
settings_t settings;
|
||||
|
||||
@@ -500,7 +500,7 @@ namespace ifcopenshell {
|
||||
};
|
||||
|
||||
class IFC_GEOM_API Settings : public SettingsContainer<
|
||||
std::tuple<MesherLinearDeflection, MesherAngularDeflection, ReorientShells, LengthUnit, PlaneUnit, Precision, OutputDimensionality, LayersetFirst, DisableBooleanResult, NoWireIntersectionCheck, NoWireIntersectionTolerance, PrecisionFactor, DebugBooleanOperations, BooleanAttempt2d, SurfaceColour, WeldVertices, UseWorldCoords, UnifyShapes, UseMaterialNames, ConvertBackUnits, ContextIds, ContextTypes, ContextIdentifiers, IteratorOutput, DisableOpeningSubtractions, ApplyDefaultMaterials, DontEmitNormals, GenerateUvs, ApplyLayerSets, UseElementHierarchy, ValidateQuantities, EdgeArrows, BuildingLocalPlacement, SiteLocalPlacement, ForceSpaceTransparency, CircleSegments, KeepBoundingBoxes, PiecewiseStepType, PiecewiseStepParam, NoParallelMapping, ModelOffset, ModelRotation, TriangulationType>
|
||||
std::tuple<MesherLinearDeflection, MesherAngularDeflection, ReorientShells, LengthUnit, PlaneUnit, Precision, OutputDimensionality, LayersetFirst, DisableBooleanResult, NoWireIntersectionCheck, NoWireIntersectionTolerance, PrecisionFactor, DebugBooleanOperations, BooleanAttempt2d, SurfaceColour, WeldVertices, UseWorldCoords, UnifyShapes, UseMaterialNames, ConvertBackUnits, ContextIds, ContextTypes, ContextIdentifiers, IteratorOutput, DisableOpeningSubtractions, ApplyDefaultMaterials, DontEmitNormals, GenerateUvs, ApplyLayerSets, UseElementHierarchy, ValidateQuantities, EdgeArrows, BuildingLocalPlacement, SiteLocalPlacement, ForceSpaceTransparency, CircleSegments, KeepBoundingBoxes, FunctionStepType, FunctionStepParam, NoParallelMapping, ModelOffset, ModelRotation, TriangulationType>
|
||||
>
|
||||
{};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
#include "function_item_evaluator.h"
|
||||
#include "profile_helper.h"
|
||||
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
|
||||
struct functor_fn_evaluator : public fn_evaluator {
|
||||
functor_fn_evaluator(taxonomy::functor_item::const_ptr fn, const ifcopenshell::geometry::Settings& settings) : fn_evaluator(settings),
|
||||
fn_(fn) {
|
||||
}
|
||||
|
||||
fn_evaluator* clone() const override { return new functor_fn_evaluator(*this); }
|
||||
double start() const override { return fn_->start(); }
|
||||
double end() const override { return fn_->end(); }
|
||||
|
||||
Eigen::Matrix4d evaluate(double u) const override {
|
||||
return (*fn_)(u);
|
||||
}
|
||||
|
||||
taxonomy::functor_item::const_ptr fn_;
|
||||
};
|
||||
|
||||
struct piecewise_fn_evaluator : public fn_evaluator {
|
||||
piecewise_fn_evaluator(taxonomy::piecewise_function::const_ptr fn, const ifcopenshell::geometry::Settings& settings) : fn_evaluator(settings),
|
||||
fn_(fn) {
|
||||
}
|
||||
|
||||
fn_evaluator* clone() const override { return new piecewise_fn_evaluator(*this); }
|
||||
double start() const override { return fn_->start(); }
|
||||
double end() const override { return fn_->end(); }
|
||||
|
||||
Eigen::Matrix4d evaluate(double u) const override {
|
||||
// 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
|
||||
function_item_evaluator evaluator(settings_, current_span_fn_);
|
||||
return evaluator.evaluate(u);
|
||||
}
|
||||
|
||||
std::tuple<double, double, taxonomy::function_item::const_ptr> get_span(double u) const {
|
||||
// force u to be within bounds of the curve
|
||||
double s = fn_->start();
|
||||
double e = fn_->end();
|
||||
u = std::max(s, u);
|
||||
u = std::min(u, e);
|
||||
|
||||
double span_start = s;
|
||||
for (auto& fn : fn_->spans()) {
|
||||
double span_end = span_start + fn->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 += fn->length();
|
||||
}
|
||||
|
||||
Logger::Error("piecewise span not found.");
|
||||
return {0, 0, nullptr};
|
||||
}
|
||||
|
||||
taxonomy::piecewise_function::const_ptr fn_;
|
||||
mutable double current_span_start_ = 0;
|
||||
mutable double current_span_end_ = 0;
|
||||
mutable taxonomy::function_item::const_ptr current_span_fn_ = nullptr;
|
||||
};
|
||||
|
||||
struct gradient_fn_evaluator : public fn_evaluator {
|
||||
gradient_fn_evaluator(taxonomy::gradient_function::const_ptr fn, const ifcopenshell::geometry::Settings& settings) :
|
||||
fn_evaluator(settings),
|
||||
fn_(fn),
|
||||
horizontal_evaluator_(settings, fn->get_horizontal()),
|
||||
vertical_evaluator_(settings, fn->get_vertical())
|
||||
{
|
||||
start_ = fn_->get_vertical()->start();
|
||||
}
|
||||
|
||||
fn_evaluator* clone() const override { return new gradient_fn_evaluator(*this); }
|
||||
double start() const override { return fn_->start(); }
|
||||
double end() const override { return fn_->end(); }
|
||||
|
||||
Eigen::Matrix4d evaluate(double u) const override {
|
||||
// u is distance from start of vertical.
|
||||
// add vertical->start() to u to get distance from start of horizontal
|
||||
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
|
||||
uz.row(1).swap(uz.row(2));
|
||||
|
||||
Eigen::Matrix4d m;
|
||||
m = xy * uz; // combine horizontal and vertical
|
||||
return m;
|
||||
}
|
||||
|
||||
function_item_evaluator horizontal_evaluator_, vertical_evaluator_;
|
||||
double start_; // start of vertical
|
||||
taxonomy::gradient_function::const_ptr fn_;
|
||||
};
|
||||
|
||||
struct cant_fn_evaluator : public fn_evaluator {
|
||||
cant_fn_evaluator(taxonomy::cant_function::const_ptr fn, const ifcopenshell::geometry::Settings& settings) : fn_evaluator(settings),
|
||||
fn_(fn),
|
||||
gradient_evaluator_(settings, fn->get_gradient()),
|
||||
cant_evaluator_(settings, fn->get_cant()) {
|
||||
start_ = fn_->get_cant()->start();
|
||||
}
|
||||
|
||||
fn_evaluator* clone() const override { return new cant_fn_evaluator(*this); }
|
||||
double start() const override { return fn_->start(); }
|
||||
double end() const override { return fn_->end(); }
|
||||
|
||||
Eigen::Matrix4d evaluate(double u) const override {
|
||||
// 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_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
|
||||
// they are relative to the gradient curve coordinate system
|
||||
//
|
||||
// However, the coordinate points don't need to have the rotations
|
||||
// of g applied. Save off the x,y,z and cant values
|
||||
auto x = g(0, 3);
|
||||
auto y = g(1, 3);
|
||||
auto z = g(2, 3);
|
||||
auto s = c(1, 3); // superelevation
|
||||
|
||||
// change column 3 to (0,0,0,1)
|
||||
Eigen::Vector4d p(0, 0, 0, 1);
|
||||
g.col(3) = p;
|
||||
c.col(3) = p;
|
||||
|
||||
// multiply g and c to get the axes in the correct orientation
|
||||
Eigen::Matrix4d m = g * c;
|
||||
|
||||
// reinstate the values for x and y.
|
||||
// z is the gradient curve z value plus the superelevation
|
||||
// that comes from the cant.
|
||||
m(0, 3) = x;
|
||||
m(1, 3) = y;
|
||||
m(2, 3) = z + s;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
function_item_evaluator gradient_evaluator_, cant_evaluator_;
|
||||
double start_; // start of cant
|
||||
taxonomy::cant_function::const_ptr fn_;
|
||||
};
|
||||
|
||||
struct offset_fn_evaluator : public fn_evaluator {
|
||||
offset_fn_evaluator(taxonomy::offset_function::const_ptr fn, const ifcopenshell::geometry::Settings& settings) : fn_evaluator(settings),
|
||||
fn_(fn),
|
||||
basis_evaluator_(settings, fn->get_basis()),
|
||||
offset_evaluator_(settings, fn->get_offset()) {
|
||||
}
|
||||
|
||||
fn_evaluator* clone() const override { return new offset_fn_evaluator(*this); }
|
||||
double start() const override { return fn_->start(); }
|
||||
double end() const override { return fn_->end(); }
|
||||
|
||||
Eigen::Matrix4d evaluate(double u) const override {
|
||||
auto p = basis_evaluator_.evaluate(u);
|
||||
auto offset = offset_evaluator_.evaluate(u);
|
||||
Eigen::Matrix4d m = p * offset;
|
||||
return m;
|
||||
}
|
||||
|
||||
function_item_evaluator basis_evaluator_, offset_evaluator_;
|
||||
taxonomy::offset_function::const_ptr fn_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function_item_evaluator::function_item_evaluator(const ifcopenshell::geometry::Settings& settings,taxonomy::function_item::const_ptr fn) {
|
||||
auto kind = fn->kind();
|
||||
if (kind == taxonomy::FUNCTOR_ITEM) {
|
||||
fn_evaluator_ = new functor_fn_evaluator(std::dynamic_pointer_cast<const taxonomy::functor_item>(fn),settings);
|
||||
} else if (kind == taxonomy::PIECEWISE_FUNCTION) {
|
||||
fn_evaluator_ = new piecewise_fn_evaluator(std::dynamic_pointer_cast<const taxonomy::piecewise_function>(fn), settings);
|
||||
} else if (kind == taxonomy::GRADIENT_FUNCTION) {
|
||||
fn_evaluator_ = new gradient_fn_evaluator(std::dynamic_pointer_cast<const taxonomy::gradient_function>(fn), settings);
|
||||
} else if (kind == taxonomy::CANT_FUNCTION) {
|
||||
fn_evaluator_ = new cant_fn_evaluator(std::dynamic_pointer_cast<const taxonomy::cant_function>(fn), settings);
|
||||
} else if (kind == taxonomy::OFFSET_FUNCTION) {
|
||||
fn_evaluator_ = new offset_fn_evaluator(std::dynamic_pointer_cast<const taxonomy::offset_function>(fn), settings);
|
||||
} else {
|
||||
Logger::Error("Unexpected function type");
|
||||
}
|
||||
}
|
||||
|
||||
function_item_evaluator::function_item_evaluator(const function_item_evaluator& other) {
|
||||
fn_evaluator_ = other.fn_evaluator_->clone();
|
||||
eval_points_ = other.eval_points_;
|
||||
}
|
||||
|
||||
function_item_evaluator::~function_item_evaluator() {
|
||||
delete fn_evaluator_;
|
||||
}
|
||||
|
||||
std::vector<double> function_item_evaluator::evaluation_points() const {
|
||||
if (!eval_points_.has_value()) {
|
||||
double curve_length = fn_evaluator_->length();
|
||||
|
||||
auto param_type = fn_evaluator_->settings_.get<ifcopenshell::geometry::settings::FunctionStepType>().get();
|
||||
auto param = fn_evaluator_->settings_.get<ifcopenshell::geometry::settings::FunctionStepParam>().get();
|
||||
unsigned num_steps = 0;
|
||||
if (param_type == ifcopenshell::geometry::settings::FunctionStepMethod::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(fn_evaluator_->start(), fn_evaluator_->end(), num_steps);
|
||||
}
|
||||
return *eval_points_;
|
||||
}
|
||||
|
||||
std::vector<double> function_item_evaluator::evaluation_points(double ustart, double uend, unsigned nsteps) const {
|
||||
double curve_length = fn_evaluator_->length();
|
||||
ustart = std::max(fn_evaluator_->start(), ustart);
|
||||
uend = std::min(uend, fn_evaluator_->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 function_item_evaluator::evaluate() const {
|
||||
return evaluate(evaluation_points());
|
||||
}
|
||||
|
||||
taxonomy::item::ptr function_item_evaluator::evaluate(double ustart, double uend, unsigned nsteps) const {
|
||||
return evaluate(evaluation_points(ustart, uend, nsteps));
|
||||
}
|
||||
|
||||
taxonomy::item::ptr function_item_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);
|
||||
}
|
||||
|
||||
Eigen::Matrix4d function_item_evaluator::evaluate(double u) const {
|
||||
return fn_evaluator_->evaluate(u);
|
||||
}
|
||||
+27
-15
@@ -7,10 +7,29 @@
|
||||
|
||||
namespace ifcopenshell { namespace geometry {
|
||||
|
||||
/// @brief utility class to evaluate piecewise_function objects
|
||||
class piecewise_function_evaluator {
|
||||
/// @brief Abstract class for evaluating a function_item. This class is specialized for each of the function_item types.
|
||||
struct fn_evaluator {
|
||||
fn_evaluator(const ifcopenshell::geometry::Settings& settings) : settings_(settings) {
|
||||
}
|
||||
fn_evaluator(const fn_evaluator& other) = default;
|
||||
virtual ~fn_evaluator() = default;
|
||||
|
||||
virtual fn_evaluator* clone() const = 0;
|
||||
|
||||
virtual Eigen::Matrix4d evaluate(double u) const = 0;
|
||||
virtual double start() const = 0;
|
||||
virtual double end() const = 0;
|
||||
double length() const { return end() - start(); }
|
||||
|
||||
ifcopenshell::geometry::Settings settings_;
|
||||
};
|
||||
|
||||
/// @brief utility class to evaluate function_item objects.
|
||||
class function_item_evaluator {
|
||||
public:
|
||||
piecewise_function_evaluator(taxonomy::piecewise_function::const_ptr pwf, const ifcopenshell::geometry::Settings* settings=nullptr);
|
||||
function_item_evaluator(const ifcopenshell::geometry::Settings& settings, taxonomy::function_item::const_ptr fn);
|
||||
function_item_evaluator(const function_item_evaluator& other);
|
||||
~function_item_evaluator();
|
||||
|
||||
/// @brief returns a vector of "distance along" points where the evaluate function computes loop points
|
||||
std::vector<double> evaluation_points() const;
|
||||
@@ -21,11 +40,11 @@ class piecewise_function_evaluator {
|
||||
/// @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
|
||||
/// @brief evaluates the 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
|
||||
/// @brief evaluates the 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
|
||||
@@ -34,23 +53,16 @@ class piecewise_function_evaluator {
|
||||
/// @return taxonomy::loop::ptr
|
||||
taxonomy::item::ptr evaluate(double ustart, double uend, unsigned nsteps) const;
|
||||
|
||||
/// @brief evaluates the piecewise function at u
|
||||
/// @brief evaluates the 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;
|
||||
fn_evaluator* fn_evaluator_ = nullptr;
|
||||
|
||||
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_;
|
||||
mutable boost::optional<std::vector<double>> eval_points_; // cache evaluation points
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "profile_helper.h"
|
||||
#include "infra_sweep_helper.h"
|
||||
#include "piecewise_function_evaluator.h"
|
||||
#include "function_item_evaluator.h"
|
||||
|
||||
#include <boost/range/combine.hpp>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
taxonomy::loft::ptr ifcopenshell::geometry::make_loft(const Settings& settings_, const IfcUtil::IfcBaseClass* inst, const taxonomy::piecewise_function::ptr& pwf, std::vector<cross_section>& cross_sections)
|
||||
taxonomy::loft::ptr ifcopenshell::geometry::make_loft(const Settings& settings_, const IfcUtil::IfcBaseClass* inst, const taxonomy::function_item::ptr& fn, std::vector<cross_section>& cross_sections)
|
||||
{
|
||||
std::sort(cross_sections.begin(), cross_sections.end());
|
||||
|
||||
@@ -22,23 +22,23 @@ taxonomy::loft::ptr ifcopenshell::geometry::make_loft(const Settings& settings_,
|
||||
// @todo intialize as default
|
||||
loft->axis = nullptr;
|
||||
|
||||
// @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) {
|
||||
piecewise_function_evaluator evaluator(pwf, &settings_);
|
||||
// @todo currently only the case is handled where directrix returns a function_item
|
||||
// @todo this "if" statement is not really required because the function returns at the start if the Directrix is not a function_item function
|
||||
if (fn) {
|
||||
function_item_evaluator evaluator(settings_,fn);
|
||||
double start = std::max(0., cross_sections.front().dist_along);
|
||||
double end = std::min(pwf->length(), cross_sections.back().dist_along);
|
||||
double end = std::min(fn->length(), cross_sections.back().dist_along);
|
||||
|
||||
if (end - start < 1.e-9) {
|
||||
Logger::Warning("Empty sweep domain with start at " + std::to_string(cross_sections.front().dist_along) + " end at " + std::to_string(cross_sections.back().dist_along) + " and curve domain length " + std::to_string(pwf->length()), inst);
|
||||
Logger::Warning("Empty sweep domain with start at " + std::to_string(cross_sections.front().dist_along) + " end at " + std::to_string(cross_sections.back().dist_along) + " and curve domain length " + std::to_string(fn->length()), inst);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto curve_length = end - start;
|
||||
auto param_type = settings_.get<ifcopenshell::geometry::settings::PiecewiseStepType>().get();
|
||||
auto param = settings_.get<ifcopenshell::geometry::settings::PiecewiseStepParam>().get();
|
||||
auto param_type = settings_.get<ifcopenshell::geometry::settings::FunctionStepType>().get();
|
||||
auto param = settings_.get<ifcopenshell::geometry::settings::FunctionStepParam>().get();
|
||||
size_t num_steps = 0;
|
||||
if (param_type == ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE) {
|
||||
if (param_type == ifcopenshell::geometry::settings::FunctionStepMethod::MAXSTEPSIZE) {
|
||||
// parameter is max step size
|
||||
num_steps = (size_t)std::ceil(curve_length / param);
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace ifcopenshell {
|
||||
}
|
||||
};
|
||||
|
||||
taxonomy::loft::ptr make_loft(const Settings& settings_, const IfcUtil::IfcBaseClass* inst, const taxonomy::piecewise_function::ptr& directrix, std::vector<cross_section>& cross_sections);
|
||||
taxonomy::loft::ptr make_loft(const Settings& settings_, const IfcUtil::IfcBaseClass* inst, const taxonomy::function_item::ptr& directrix, std::vector<cross_section>& cross_sections);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ using namespace ifcopenshell::geometry;
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
|
||||
auto loop = taxonomy::make<taxonomy::loop>();
|
||||
std::vector<taxonomy::piecewise_function::ptr> pwfs;
|
||||
taxonomy::piecewise_function::spans_t spans;
|
||||
|
||||
#ifdef SCHEMA_HAS_IfcSegment
|
||||
// 4x3
|
||||
@@ -74,17 +74,18 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
|
||||
for (auto& s : taxonomy::cast<taxonomy::loop>(crv)->children) {
|
||||
loop->children.push_back(s);
|
||||
}
|
||||
}
|
||||
else if (crv && crv->kind() == taxonomy::PIECEWISE_FUNCTION) {
|
||||
pwfs.push_back(taxonomy::cast<taxonomy::piecewise_function>(crv));
|
||||
} else if (!crv) {
|
||||
} else if (auto fi = taxonomy::dcast<taxonomy::function_item>(crv); crv && fi /*crv->kind() == taxonomy::FUNCTION_ITEM*/) {
|
||||
// crv->kind() is polymorphic and the kind of the actual function_item is returned. PWF can have spans of any FUNCTION_ITEM
|
||||
// for this reason, a dynamic cast is used and if crv is a function_item it is added to the span
|
||||
spans.push_back(fi);
|
||||
} else if (!crv) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pwfs.empty()) {
|
||||
if (spans.empty()) {
|
||||
aggregate_of_instance::ptr profile = inst->file_->getInverse(inst->id(), &IfcSchema::IfcProfileDef::Class(), -1);
|
||||
const bool force_close = profile && profile->size() > 0;
|
||||
loop->closed = force_close;
|
||||
@@ -92,7 +93,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) {
|
||||
return loop;
|
||||
}
|
||||
else {
|
||||
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0,pwfs,inst);
|
||||
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0,spans,inst);
|
||||
return pwf;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,87 @@ typedef boost::mpl::vector<
|
||||
#endif
|
||||
> curve_seg_types;
|
||||
|
||||
|
||||
struct parent_curve_function {
|
||||
parent_curve_function() = default;
|
||||
parent_curve_function(const parent_curve_function&) = default;
|
||||
parent_curve_function(std::function<Eigen::Matrix4d(double)> fn) : fn_(fn) {
|
||||
}
|
||||
|
||||
parent_curve_function& operator=(std::function<Eigen::Matrix4d(double)> fn) {
|
||||
fn_ = fn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual Eigen::Matrix4d operator()(double u) const { return fn_(u); }
|
||||
|
||||
private:
|
||||
std::function<Eigen::Matrix4d(double)> fn_;
|
||||
};
|
||||
|
||||
struct polynomial_parent_curve : public parent_curve_function {
|
||||
using parent_curve_function::parent_curve_function;
|
||||
};
|
||||
|
||||
struct line_parent_curve : public parent_curve_function {
|
||||
using parent_curve_function::parent_curve_function;
|
||||
};
|
||||
|
||||
struct circle_parent_curve : public parent_curve_function {
|
||||
using parent_curve_function::parent_curve_function;
|
||||
};
|
||||
|
||||
struct spiral_parent_curve : public parent_curve_function {
|
||||
using parent_curve_function::parent_curve_function;
|
||||
};
|
||||
|
||||
// this is the piecewise curve segment function for horizontal and vertical
|
||||
struct curve_segment_function {
|
||||
curve_segment_function(const Eigen::Matrix4d& curve_segment_placement, const Eigen::Matrix4d& remove_parent_curve_rotation, const Eigen::Matrix4d& remove_parent_curve_translation, std::shared_ptr<parent_curve_function> parent_curve_fn) :
|
||||
curve_segment_placement_(curve_segment_placement),
|
||||
remove_parent_curve_rotation_(remove_parent_curve_rotation),
|
||||
remove_parent_curve_translation_(remove_parent_curve_translation),
|
||||
parent_curve_fn_(parent_curve_fn) {
|
||||
}
|
||||
|
||||
Eigen::Matrix4d operator()(double u) const {
|
||||
Eigen::Matrix4d parent_curve_point = (*parent_curve_fn_)(u);
|
||||
Eigen::Matrix4d curve_segment_point = curve_segment_placement_ * remove_parent_curve_rotation_ * remove_parent_curve_translation_ * parent_curve_point;
|
||||
return curve_segment_point;
|
||||
}
|
||||
|
||||
private:
|
||||
Eigen::Matrix4d curve_segment_placement_;
|
||||
Eigen::Matrix4d remove_parent_curve_rotation_;
|
||||
Eigen::Matrix4d remove_parent_curve_translation_;
|
||||
std::shared_ptr<parent_curve_function> parent_curve_fn_;
|
||||
};
|
||||
|
||||
// this is the piecewise curve segment function for cant
|
||||
struct cant_curve_segment_function {
|
||||
cant_curve_segment_function(const Eigen::Matrix4d& curve_segment_placement, const Eigen::Matrix4d& parent_curve_start_point, std::shared_ptr<parent_curve_function> parent_curve_fn) :
|
||||
curve_segment_placement_(curve_segment_placement),
|
||||
parent_curve_start_point_(parent_curve_start_point),
|
||||
parent_curve_fn_(parent_curve_fn) {
|
||||
}
|
||||
|
||||
Eigen::Matrix4d operator()(double u) const {
|
||||
// The parent curve function returns the cant rotation and superelevation for the parent curve.
|
||||
// Subtract the parent_curve_start_point to get the incremental cant rotation and superelevation
|
||||
// Add the incremental cant rotation and superelevation to curve_segment_placement to get the curve_segment_point
|
||||
Eigen::Matrix4d parent_curve_point = (*parent_curve_fn_)(u);
|
||||
Eigen::Matrix4d cant_increment = parent_curve_point - parent_curve_start_point_;
|
||||
Eigen::Matrix4d curve_segment_point = curve_segment_placement_ + cant_increment;
|
||||
return curve_segment_point;
|
||||
}
|
||||
|
||||
private:
|
||||
Eigen::Matrix4d curve_segment_placement_;
|
||||
Eigen::Matrix4d parent_curve_start_point_;
|
||||
std::shared_ptr<parent_curve_function> parent_curve_fn_;
|
||||
};
|
||||
|
||||
// evaluates a IfcCurveSegment to set up the placement and parent curve function
|
||||
class curve_segment_evaluator {
|
||||
private:
|
||||
mapping* mapping_ = nullptr;
|
||||
@@ -108,24 +189,71 @@ class curve_segment_evaluator {
|
||||
|
||||
double projected_length_; // for vertical segments, this is the length of curve projected onto the "Distance Along" axis
|
||||
|
||||
std::optional<std::function<Eigen::Matrix4d(double)>> parent_curve_fn_; // function for the parent curve. Function takes distances along, u, and returns the 4x4 position matrix
|
||||
std::optional<Eigen::Matrix4d> parent_curve_start_point_; // placement matrix for the parent curve
|
||||
std::shared_ptr<parent_curve_function> parent_curve_fn_; // function for the parent curve. Function takes distances along, u, and returns the 4x4 position matrix
|
||||
std::optional<Eigen::Matrix4d> parent_curve_start_point_; // placement matrix for the parent curve
|
||||
|
||||
std::optional<Eigen::Matrix4d> placement_; // placement of this segment
|
||||
std::optional<Eigen::Matrix4d> curve_segment_placement_; // placement of this segment
|
||||
std::optional<Eigen::Matrix4d> next_segment_placement_; // placement of the next segment
|
||||
|
||||
public:
|
||||
curve_segment_evaluator(mapping* mapping, const IfcSchema::IfcCurveSegment* inst, const IfcSchema::IfcCurveSegment* next_inst, double length_unit, segment_type_t segment_type)
|
||||
curve_segment_evaluator(mapping* mapping, const IfcSchema::IfcCurveSegment* inst, double length_unit)
|
||||
: mapping_(mapping),
|
||||
inst_(inst),
|
||||
length_unit_(length_unit),
|
||||
segment_type_(segment_type),
|
||||
parent_curve_(inst->ParentCurve()) {
|
||||
|
||||
auto composite_curves = inst->UsingCurves();
|
||||
|
||||
// Find the next segment after inst
|
||||
const IfcSchema::IfcCurveSegment* next_inst = nullptr;
|
||||
if (composite_curves) {
|
||||
if (composite_curves->size() == 1) {
|
||||
auto segments = (*composite_curves->begin())->as<IfcSchema::IfcCompositeCurve>()->Segments();
|
||||
bool emit_next = false;
|
||||
for (auto& s : *segments) {
|
||||
if (emit_next) {
|
||||
next_inst = s->as<IfcSchema::IfcCurveSegment>();
|
||||
break;
|
||||
}
|
||||
if (s == inst) {
|
||||
emit_next = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger::Warning("IfcCurveSegment belongs to multiple IfcCompositeCurve instances. Cannot determine the next segment.");
|
||||
}
|
||||
}
|
||||
|
||||
bool is_horizontal = false;
|
||||
bool is_vertical = false;
|
||||
bool is_cant = false;
|
||||
|
||||
if (composite_curves) {
|
||||
for (auto& cc : *composite_curves) {
|
||||
if (cc->as<IfcSchema::IfcSegmentedReferenceCurve>()) {
|
||||
is_cant = true;
|
||||
} else if (cc->as<IfcSchema::IfcGradientCurve>()) {
|
||||
is_vertical = true;
|
||||
} else {
|
||||
is_horizontal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((is_horizontal + is_vertical + is_cant) != 1) {
|
||||
// We have to choose the correct functor based on usage. We can't
|
||||
// support multiple, because we don't know the caller at this point.
|
||||
Logger::Error(std::runtime_error("multiple uses of IfcSegmentCurve not supported"), inst_);
|
||||
}
|
||||
|
||||
segment_type_ = is_horizontal ? ST_HORIZONTAL : is_vertical ? ST_VERTICAL : ST_CANT;
|
||||
|
||||
|
||||
start_ = translate_if_param_value(inst->ParentCurve(), inst->SegmentStart()) * length_unit;
|
||||
length_ = translate_if_param_value(inst->ParentCurve(), inst->SegmentLength()) * length_unit;
|
||||
|
||||
if (inst) {
|
||||
placement_ = taxonomy::cast<taxonomy::matrix4>(mapping_->map(inst->Placement()))->ccomponents();
|
||||
curve_segment_placement_ = taxonomy::cast<taxonomy::matrix4>(mapping_->map(inst->Placement()))->ccomponents();
|
||||
}
|
||||
|
||||
if (next_inst) {
|
||||
@@ -133,7 +261,6 @@ class curve_segment_evaluator {
|
||||
} else {
|
||||
// there is not a next segment, however IfcGradientCurve and IfcSegmentReferenceCurve have an
|
||||
// optional EndPoint which services the same purpose as the zero-length last segment.
|
||||
auto composite_curves = inst->UsingCurves();
|
||||
IfcSchema::IfcPlacement* end_point = nullptr;
|
||||
if (composite_curves->size() == 1) {
|
||||
auto& cc = *(composite_curves)->begin();
|
||||
@@ -165,16 +292,47 @@ class curve_segment_evaluator {
|
||||
return (segment_type_ == ST_HORIZONTAL || segment_type_ == ST_CANT) ? length_ : projected_length_;
|
||||
}
|
||||
|
||||
const std::optional<std::function<Eigen::Matrix4d(double)>>& parent_curve_function() const {
|
||||
return parent_curve_fn_;
|
||||
}
|
||||
taxonomy::ptr get_segment_curve_function() {
|
||||
if (!parent_curve_fn_ || !parent_curve_start_point_) {
|
||||
Logger::Error(std::runtime_error(inst_->ParentCurve()->declaration().name() + " not implemented"), inst_);
|
||||
}
|
||||
|
||||
const std::optional<Eigen::Matrix4d>& parent_curve_start_point() const {
|
||||
return parent_curve_start_point_;
|
||||
}
|
||||
auto length = fabs(this->length());
|
||||
|
||||
const std::optional<Eigen::Matrix4d>& segment_placement() const {
|
||||
return placement_;
|
||||
if (segment_type_ == ST_CANT) {
|
||||
auto fn = cant_curve_segment_function(*curve_segment_placement_, *parent_curve_start_point_, parent_curve_fn_);
|
||||
return taxonomy::make<taxonomy::functor_item>(length, fn);
|
||||
} else {
|
||||
// The parent curve function returns the 4x4 matrix for the parent curve.
|
||||
// Subtract the parent curve start point (remove the translation and rotation)
|
||||
// to get the incremental translation and rotation. Apply the incremental
|
||||
// translation and rotation to the curve_segment_placement to get the curve_segment_point
|
||||
|
||||
// Do a negative translation of the parent curve point relative to the start of the parent curve.
|
||||
// This moves parent_curve_fn(u=0.0) to coordinate (0,0).
|
||||
// This is done so the curve_segment_placement is applied relative to (0,0)
|
||||
Eigen::Matrix4d remove_parent_curve_translation = Eigen::Matrix4d::Identity();
|
||||
remove_parent_curve_translation.col(3) = -1.0 * (*parent_curve_start_point_).col(3);
|
||||
remove_parent_curve_translation(3, 3) = 1.0;
|
||||
|
||||
// Do a rotation so that the tangent of the parent curve is in the direction (1,0)
|
||||
// Example: if the parent curve IfcLine is at a 30 degree clockwise angle, this does
|
||||
// a 30 degree counter-clockwise rotation
|
||||
// Clockwise rotation matrix = [cos(angle) -sin(angle)]
|
||||
// [sin(angle) cos(angle)]
|
||||
//
|
||||
// Counter-clockwise rotation = [ cos(angle) sin(angle)]
|
||||
// [-sin(angle) cos(angle)]
|
||||
//
|
||||
// That's just a sign flip in positions (0,1) and (1,0)
|
||||
Eigen::Matrix4d remove_parent_curve_rotation = (*parent_curve_start_point_);
|
||||
remove_parent_curve_rotation(0, 1) *= -1.0;
|
||||
remove_parent_curve_rotation(1, 0) *= -1.0;
|
||||
remove_parent_curve_rotation.col(3) = Eigen::Vector4d(0, 0, 0, 1); // remove the parent curve placement point
|
||||
|
||||
auto fn = curve_segment_function(*curve_segment_placement_, remove_parent_curve_rotation, remove_parent_curve_translation, parent_curve_fn_);
|
||||
return taxonomy::make<taxonomy::functor_item>(length, fn);
|
||||
}
|
||||
}
|
||||
|
||||
void set_spiral_function(double s, std::function<double(double)> fnX, std::function<double(double)> fnY) {
|
||||
@@ -224,7 +382,7 @@ class curve_segment_evaluator {
|
||||
};
|
||||
}
|
||||
|
||||
parent_curve_fn_ = [start=start_, s, convert_u, fnX, fnY](double u) {
|
||||
parent_curve_fn_ = std::make_shared<spiral_parent_curve>([start=start_, s, convert_u, fnX, fnY](double u) {
|
||||
u = convert_u(u+start);
|
||||
|
||||
// integration limits, integrate from a to b
|
||||
@@ -241,20 +399,20 @@ class curve_segment_evaluator {
|
||||
m.col(1) = Eigen::Vector4d(-dy, dx, 0, 0);
|
||||
m.col(3) = Eigen::Vector4d(x, y, 0, 1);
|
||||
return m;
|
||||
};
|
||||
});
|
||||
} else if (segment_type_ == ST_CANT) {
|
||||
Logger::Error(std::runtime_error("Unexpected segment type encountered - cant is handled in set_cant_spiral_function - should never get here"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
} else {
|
||||
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
|
||||
// defines the parent_curve_fn_ functor for cant segments.
|
||||
void set_cant_spiral_function(std::function<double(double)> Superelevation, std::function<double(double)> SuperelevationSlope, std::function<double(double)> Cant) {
|
||||
auto dy = (*placement_)(1, 2); // placement dy
|
||||
auto dz = (*placement_)(2, 2); // placement dz
|
||||
auto dy = (*curve_segment_placement_)(1, 2); // placement dy
|
||||
auto dz = (*curve_segment_placement_)(2, 2); // placement dz
|
||||
auto start_angle = atan2(dz, dy);
|
||||
|
||||
dy = (next_segment_placement_.has_value() ? (*next_segment_placement_)(1, 2) : 0.0);
|
||||
@@ -266,7 +424,7 @@ class curve_segment_evaluator {
|
||||
auto end_cant = Cant(/* start_ + */ length_);
|
||||
auto delta_cant = end_cant - start_cant;
|
||||
|
||||
parent_curve_fn_ = [start_angle,delta_angle,start_cant,delta_cant,Superelevation, SuperelevationSlope, Cant](double u) -> Eigen::Matrix4d {
|
||||
parent_curve_fn_ = std::make_shared<spiral_parent_curve>([start_angle,delta_angle,start_cant,delta_cant,Superelevation, SuperelevationSlope, Cant](double u) -> Eigen::Matrix4d {
|
||||
// departure of the curve segment from the base curve (superelevation)
|
||||
auto super_elevation = Superelevation(u);
|
||||
auto slope = SuperelevationSlope(u);
|
||||
@@ -292,7 +450,7 @@ class curve_segment_evaluator {
|
||||
m.col(2) = axis;
|
||||
m.col(3) = Eigen::Vector4d(u, super_elevation, 0.0, 1.0);
|
||||
return m;
|
||||
};
|
||||
});
|
||||
|
||||
parent_curve_start_point_ = (*parent_curve_fn_)(0.0);
|
||||
}
|
||||
@@ -304,8 +462,8 @@ class curve_segment_evaluator {
|
||||
boost::optional<std::function<double(double)>> superelevation_fn;
|
||||
boost::optional<std::function<double(double)>> superelevation_slope_fn;
|
||||
|
||||
if (placement_.has_value() && next_segment_placement_.has_value()) {
|
||||
double y1 = (*placement_)(1, 3);
|
||||
if (curve_segment_placement_.has_value() && next_segment_placement_.has_value()) {
|
||||
double y1 = (*curve_segment_placement_)(1, 3);
|
||||
double y2 = (*next_segment_placement_)(1, 3);
|
||||
|
||||
// if y2-y1 = 0, the super elevation is constant
|
||||
@@ -390,10 +548,10 @@ class curve_segment_evaluator {
|
||||
set_cant_spiral_function(*super, *slope, cant);
|
||||
} else if (segment_type_ == ST_VERTICAL) {
|
||||
Logger::Error(std::runtime_error("IfcCosineSpiral cannot be used for vertical alignment"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
} else {
|
||||
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -447,10 +605,10 @@ class curve_segment_evaluator {
|
||||
set_cant_spiral_function(*super, *slope, cant);
|
||||
} else if (segment_type_ == ST_VERTICAL) {
|
||||
Logger::Error(std::runtime_error("IfcSineSpiral cannot be used for vertical alignment"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
} else {
|
||||
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -623,7 +781,7 @@ class curve_segment_evaluator {
|
||||
};
|
||||
}
|
||||
|
||||
parent_curve_fn_ = [segment_type = segment_type_, R, pcCenterX, pcCenterY, start_angle, sign_l, convert_u](double u) {
|
||||
parent_curve_fn_ = std::make_shared<circle_parent_curve>([segment_type = segment_type_, R, pcCenterX, pcCenterY, start_angle, sign_l, convert_u](double u) {
|
||||
u = convert_u(u);
|
||||
|
||||
// u is measured along the circle
|
||||
@@ -645,7 +803,7 @@ class curve_segment_evaluator {
|
||||
m.col(1) = Eigen::Vector4d(-pcDy, pcDx, 0, 0);
|
||||
m.col(3) = Eigen::Vector4d(pcX, pcY, 0.0, 1.0);
|
||||
return m;
|
||||
};
|
||||
});
|
||||
|
||||
if (segment_type_ == ST_HORIZONTAL) {
|
||||
parent_curve_start_point_ = (*parent_curve_fn_)(start_);
|
||||
@@ -675,10 +833,10 @@ class curve_segment_evaluator {
|
||||
|
||||
} else if (segment_type_ == ST_CANT) {
|
||||
Logger::Warning(std::runtime_error("Use of IfcCircle for cant is not supported"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
} else {
|
||||
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,12 +864,12 @@ class curve_segment_evaluator {
|
||||
auto pcDx = dr[0];
|
||||
auto pcDy = dr[1];
|
||||
|
||||
if (segment_type_ == ST_VERTICAL && placement_) {
|
||||
if (segment_type_ == ST_VERTICAL && curve_segment_placement_) {
|
||||
// the general algorithm for mapping parent curve onto curve segment doesn't
|
||||
// exactly work for IfcLine. This is easily overcome by using the curve segment
|
||||
// placement for the IfcLine direction
|
||||
pcDx = (*placement_)(0, 0);
|
||||
pcDy = (*placement_)(1, 0);
|
||||
pcDx = (*curve_segment_placement_)(0, 0);
|
||||
pcDy = (*curve_segment_placement_)(1, 0);
|
||||
}
|
||||
|
||||
if (segment_type_ == ST_HORIZONTAL || segment_type_ == ST_VERTICAL || segment_type_ == ST_CANT) {
|
||||
@@ -723,7 +881,7 @@ class curve_segment_evaluator {
|
||||
convert_u = [pcDx](double u) { return u/pcDx; };
|
||||
}
|
||||
|
||||
parent_curve_fn_ = [pcX, pcY, pcDx, pcDy, convert_u](double u) {
|
||||
parent_curve_fn_ = std::make_shared<line_parent_curve>([pcX, pcY, pcDx, pcDy, convert_u](double u) {
|
||||
u = convert_u(u);
|
||||
|
||||
auto x = pcX + pcDx * u;
|
||||
@@ -734,13 +892,13 @@ class curve_segment_evaluator {
|
||||
m.col(1) = Eigen::Vector4d(-pcDy, pcDx, 0, 0);
|
||||
m.col(3) = Eigen::Vector4d(x, y, 0.0, 1.0);
|
||||
return m;
|
||||
};
|
||||
});
|
||||
|
||||
parent_curve_start_point_ = (*parent_curve_fn_)(start_);
|
||||
} else {
|
||||
Logger::Warning(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
}
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const IfcSchema::IfcPolynomialCurve* pc) {
|
||||
@@ -755,7 +913,7 @@ class curve_segment_evaluator {
|
||||
if (segment_type_ == ST_HORIZONTAL || segment_type_ == ST_VERTICAL) {
|
||||
projected_length_ = length_;
|
||||
|
||||
// There is one significant difference between IfcPolynomalCurve used for horizontal and vertical alignments.
|
||||
// There is one significant difference between IfcPolynomialCurve used for horizontal and vertical alignments.
|
||||
// For horizontal alignment, u is the distance along the curve. For vertical alignment, u is the horizontal distance.
|
||||
// From 4.2.2.2.8 the polynomial curve equation is in the form of y = Ax^3 for horizontal parabolic transition segments.
|
||||
// To evaluate the horizontal function, the value of x that corresponds to the distance along the curve u is needed.
|
||||
@@ -775,7 +933,11 @@ class curve_segment_evaluator {
|
||||
for (; iter != end; iter++) {
|
||||
auto exp = std::distance(begin, iter);
|
||||
auto coeff = (*iter);
|
||||
value += (double)exp * coeff * pow(lu, lu_exp--) * pow(x, exp - 1);
|
||||
double a = (double)exp * coeff * pow(lu, lu_exp--);
|
||||
double b = x ? pow(x, exp - 1) : 0; // when x and exp are zero? 0^-1 is infinite and the result is undefined
|
||||
double v = a * b;
|
||||
//double v = (double)exp * coeff * pow(lu, lu_exp--) * pow(x, exp - 1);
|
||||
value += v;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
@@ -815,7 +977,7 @@ class curve_segment_evaluator {
|
||||
}
|
||||
|
||||
// This functor evaluates the polynomial at a distance u along the curve
|
||||
parent_curve_fn_ = [start = start_, lu = length_unit_, coeffX, coeffY, convert_u](double u) -> Eigen::Matrix4d {
|
||||
parent_curve_fn_ = std::make_shared<polynomial_parent_curve>([start = start_, lu = length_unit_, coeffX, coeffY, convert_u](double u)->Eigen::Matrix4d {
|
||||
auto x = convert_u(u + start); // find x for u
|
||||
// evaluate the polynomial at x
|
||||
std::array<const std::vector<double>*, 2> coefficients{&coeffX, &coeffY};
|
||||
@@ -851,131 +1013,24 @@ class curve_segment_evaluator {
|
||||
m.col(1) = Eigen::Vector4d(-Dy, Dx, 0, 0);
|
||||
m.col(3) = Eigen::Vector4d(X, Y, 0.0, 1.0);
|
||||
return m;
|
||||
};
|
||||
});
|
||||
|
||||
parent_curve_start_point_ = (*parent_curve_fn_)(0.0); // start is added to u in parent_curve_fn_, so use 0.0 here
|
||||
} else if (segment_type_ == ST_CANT) {
|
||||
Logger::Warning(std::runtime_error("Use of IfcPolynomialCurve for cant is not supported"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
} else {
|
||||
Logger::Error(std::runtime_error("Unexpected segment type encountered"));
|
||||
parent_curve_fn_ = [](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); };
|
||||
parent_curve_fn_ = std::make_shared<parent_curve_function>([](double /*u*/) -> Eigen::Matrix4d { return Eigen::Matrix4d::Identity(); });
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCurveSegment* inst) {
|
||||
auto composite_curves = inst->UsingCurves();
|
||||
|
||||
// Find the next segment after inst
|
||||
const IfcSchema::IfcCurveSegment* next_inst = nullptr;
|
||||
if (composite_curves) {
|
||||
if (composite_curves->size() == 1) {
|
||||
auto segments = (*composite_curves->begin())->as<IfcSchema::IfcCompositeCurve>()->Segments();
|
||||
bool emit_next = false;
|
||||
for (auto& s : *segments) {
|
||||
if (emit_next) {
|
||||
next_inst = s->as<IfcSchema::IfcCurveSegment>();
|
||||
break;
|
||||
}
|
||||
if (s == inst) {
|
||||
emit_next = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger::Warning("IfcCurveSegment belongs to multiple IfcCompositeCurve instances. Cannot determine the next segment.");
|
||||
}
|
||||
}
|
||||
|
||||
bool is_horizontal = false;
|
||||
bool is_vertical = false;
|
||||
bool is_cant = false;
|
||||
|
||||
if (composite_curves) {
|
||||
for (auto& cc : *composite_curves) {
|
||||
if (cc->as<IfcSchema::IfcSegmentedReferenceCurve>()) {
|
||||
is_cant = true;
|
||||
} else if (cc->as<IfcSchema::IfcGradientCurve>()) {
|
||||
is_vertical = true;
|
||||
} else {
|
||||
is_horizontal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((is_horizontal + is_vertical + is_cant) != 1) {
|
||||
// We have to choose the correct functor based on usage. We can't
|
||||
// support multiple, because we don't know the caller at this point.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto segment_type = is_horizontal ? ST_HORIZONTAL : is_vertical ? ST_VERTICAL : ST_CANT;
|
||||
|
||||
curve_segment_evaluator cse(this, inst, next_inst, length_unit_, segment_type);
|
||||
curve_segment_evaluator cse(this, inst, length_unit_);
|
||||
boost::mpl::for_each<curve_seg_types, boost::type<boost::mpl::_>>(std::ref(cse));
|
||||
const auto& parent_curve_fn = cse.parent_curve_function();
|
||||
const auto& parent_curve_start_point = cse.parent_curve_start_point();
|
||||
|
||||
if (!parent_curve_fn || !parent_curve_start_point) {
|
||||
Logger::Error(std::runtime_error(inst->ParentCurve()->declaration().name() + " not implemented"), inst);
|
||||
}
|
||||
|
||||
const auto& curve_segment_placement = cse.segment_placement();
|
||||
|
||||
std::function<Eigen::Matrix4d(double u)> fn;
|
||||
if (segment_type == ST_CANT)
|
||||
{
|
||||
fn = [curve_segment_placement, parent_curve_start_point, parent_curve_fn](double u) -> Eigen::Matrix4d {
|
||||
// The parent curve function returns the cant rotation and superelevation for the parent curve.
|
||||
// Subtract the parent_curve_start_point to get the incremental cant rotation and superelevation
|
||||
// Add the incremental cant rotation and superelevation to curve_segment_placement to get the curve_segment_point
|
||||
Eigen::Matrix4d parent_curve_point = (*parent_curve_fn)(u);
|
||||
Eigen::Matrix4d cant_increment = parent_curve_point - (*parent_curve_start_point);
|
||||
Eigen::Matrix4d curve_segment_point = (*curve_segment_placement) + cant_increment;
|
||||
return curve_segment_point;
|
||||
};
|
||||
} else {
|
||||
// The parent curve function returns the 4x4 matrix for the parent curve.
|
||||
// Subtract the parent curve start point (remove the translation and rotation)
|
||||
// to get the incremental translation and rotation. Apply the incremental
|
||||
// translation and rotation to the curve_segment_placement to get the curve_segment_point
|
||||
|
||||
// Do a negative translation of the parent curve point relative to the start of the parent curve.
|
||||
// This moves parent_curve_fn(u=0.0) to coordinate (0,0).
|
||||
// This is done so the curve_segment_placement is applied relative to (0,0)
|
||||
Eigen::Matrix4d remove_parent_curve_translation = Eigen::Matrix4d::Identity();
|
||||
remove_parent_curve_translation.col(3) = -1.0 * (*parent_curve_start_point).col(3);
|
||||
remove_parent_curve_translation(3, 3) = 1.0;
|
||||
|
||||
// Do a rotation so that the tangent of the parent curve is in the direction (1,0)
|
||||
// Example: if the parent curve IfcLine is at a 30 degree clockwise angle, this does
|
||||
// a 30 degree counter-clockwise rotation
|
||||
// Clockwise rotation matrix = [cos(angle) -sin(angle)]
|
||||
// [sin(angle) cos(angle)]
|
||||
//
|
||||
// Counter-clockwise rotation = [ cos(angle) sin(angle)]
|
||||
// [-sin(angle) cos(angle)]
|
||||
//
|
||||
// That's just a sign flip in positions (0,1) and (1,0)
|
||||
Eigen::Matrix4d remove_parent_curve_rotation = *parent_curve_start_point;
|
||||
remove_parent_curve_rotation(0, 1) *= -1.0;
|
||||
remove_parent_curve_rotation(1, 0) *= -1.0;
|
||||
remove_parent_curve_rotation.col(3) = Eigen::Vector4d(0, 0, 0, 1); // remove the parent curve placement point
|
||||
|
||||
fn = [curve_segment_placement, remove_parent_curve_rotation, remove_parent_curve_translation, parent_curve_fn](double u) -> Eigen::Matrix4d {
|
||||
Eigen::Matrix4d parent_curve_point = (*parent_curve_fn)(u);
|
||||
Eigen::Matrix4d curve_segment_point = (*curve_segment_placement) * remove_parent_curve_rotation * remove_parent_curve_translation * parent_curve_point;
|
||||
return curve_segment_point;
|
||||
};
|
||||
}
|
||||
|
||||
auto length = cse.length();
|
||||
|
||||
taxonomy::piecewise_function::spans_t spans;
|
||||
spans.emplace_back(fabs(length), fn);
|
||||
auto pwf = taxonomy::make<taxonomy::piecewise_function>(0.0, spans,inst);
|
||||
return pwf;
|
||||
return cse.get_segment_curve_function();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "mapping.h"
|
||||
#include "../piecewise_function_evaluator.h"
|
||||
#include "../function_item_evaluator.h"
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
@@ -34,10 +34,10 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcFixedReferenceSweptAreaSolid
|
||||
loft->axis = nullptr;
|
||||
|
||||
// @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_);
|
||||
if (auto fn = taxonomy::dcast<taxonomy::function_item>(dir)) {
|
||||
function_item_evaluator evaluator(settings_,fn);
|
||||
double start = 0;
|
||||
double end = pwf->length();
|
||||
double end = fn->length();
|
||||
#ifdef SCHEMA_HAS_IfcDirectrixCurveSweptAreaSolid
|
||||
// IfcDirectrixCurveSweptAreaSolid introduced in 4.3 changed attribute type
|
||||
// from optional IfcParamValue to optional IfcCurveMeasureSelect.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "mapping.h"
|
||||
#include "../piecewise_function_evaluator.h"
|
||||
#include "../function_item_evaluator.h"
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
@@ -30,15 +30,17 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) {
|
||||
|
||||
auto segments = inst->Segments();
|
||||
|
||||
std::vector<taxonomy::piecewise_function::ptr> pwfs;
|
||||
taxonomy::piecewise_function::spans_t spans;
|
||||
|
||||
for (auto& segment : *segments) {
|
||||
if (segment->as<IfcSchema::IfcCurveSegment>()) {
|
||||
// @todo check that we don't get a mixture of implicit and explicit definitions
|
||||
auto crv = map(segment->as<IfcSchema::IfcCurveSegment>());
|
||||
if (crv && crv->kind() == taxonomy::PIECEWISE_FUNCTION) {
|
||||
pwfs.push_back(taxonomy::cast<taxonomy::piecewise_function>(crv));
|
||||
} else {
|
||||
if (auto fi = taxonomy::dcast<taxonomy::function_item>(crv); crv && fi /*crv->kind() == taxonomy::FUNCTION_ITEM*/) {
|
||||
// crv->kind() is polymorphic and the kind of the actual function_item is returned. PWF can have spans of any FUNCTION_ITEM
|
||||
// for this reason, a dynamic cast is used and if crv is a function_item it is added to the span
|
||||
spans.push_back(fi);
|
||||
} else {
|
||||
Logger::Error("Unsupported");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -56,40 +58,21 @@ 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);
|
||||
auto vertical = taxonomy::make<taxonomy::piecewise_function>(gradient_start, spans);
|
||||
|
||||
// Determine the valid domain of the PWF... the valid domain is where both
|
||||
// the base curve and gradient curves are defined
|
||||
// create the horizontal pwf
|
||||
auto horizontal = taxonomy::cast<taxonomy::piecewise_function>(map(inst->BaseCurve()));
|
||||
double start = std::max(horizontal->start(),vertical->start());
|
||||
double end = std::min(horizontal->end(), vertical->end());
|
||||
double length = end - start;
|
||||
|
||||
if (!(0 < length)) {
|
||||
// create the composite gradient curve function
|
||||
auto gradient_function = taxonomy::make<taxonomy::gradient_function>(horizontal, vertical, inst);
|
||||
|
||||
// check to see if there is valid overlap of the horizontal and vertical domains
|
||||
if (!(0 < gradient_function->length())) {
|
||||
Logger::Error("IfcGradientCurve does not have a common domain with BaseCurve");
|
||||
gradient_function = nullptr; // not valid
|
||||
}
|
||||
|
||||
// define the callback function for the gradient curve
|
||||
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_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
|
||||
uz.row(1).swap(uz.row(2));
|
||||
|
||||
Eigen::Matrix4d m;
|
||||
m = xy * uz; // combine horizontal and vertical
|
||||
return m;
|
||||
};
|
||||
|
||||
taxonomy::piecewise_function::spans_t spans;
|
||||
spans.emplace_back(length, composition);
|
||||
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start, spans, inst);
|
||||
return pwf;
|
||||
return gradient_function;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "mapping.h"
|
||||
#include "../profile_helper.h"
|
||||
#include "../piecewise_function_evaluator.h"
|
||||
#include "../function_item_evaluator.h"
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
@@ -39,10 +39,10 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
auto first_offset_value = *(offset_values->begin());
|
||||
|
||||
auto basis_curve = inst->BasisCurve();
|
||||
auto pw_curve = taxonomy::dcast<taxonomy::piecewise_function>(map(basis_curve));
|
||||
auto curve = taxonomy::dcast<taxonomy::piecewise_function>(map(basis_curve));
|
||||
|
||||
double start = pw_curve->start();
|
||||
double basis_curve_length = pw_curve->length();
|
||||
double start = curve->start();
|
||||
double basis_curve_length = curve->length();
|
||||
|
||||
taxonomy::piecewise_function::spans_t offset_spans;
|
||||
|
||||
@@ -70,7 +70,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
m.col(3)(1) = py;
|
||||
m.col(3)(2) = pz;
|
||||
return m; };
|
||||
offset_spans.emplace_back(first_distance, fn);
|
||||
offset_spans.emplace_back(taxonomy::make<taxonomy::functor_item>(first_distance, fn));
|
||||
}
|
||||
|
||||
auto iter = offset_values->begin();
|
||||
@@ -114,7 +114,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
m.col(3)(2) = (l == 0.0 ? zp : (zp + (zn - zp) * u / l));
|
||||
return m;
|
||||
};
|
||||
offset_spans.emplace_back(l, fn);
|
||||
offset_spans.emplace_back(taxonomy::make<taxonomy::functor_item>(l, fn));
|
||||
}
|
||||
|
||||
// at this point, next == end and prev == end-1
|
||||
@@ -142,25 +142,13 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
|
||||
m.col(3)(2) = pz;
|
||||
return m; };
|
||||
|
||||
offset_spans.emplace_back(l, fn);
|
||||
offset_spans.emplace_back(taxonomy::make<taxonomy::functor_item>(l, fn));
|
||||
}
|
||||
|
||||
auto offsets = taxonomy::make<taxonomy::piecewise_function>(start,offset_spans);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// current implementation assumes that composition is equal to the full length of basis curve
|
||||
// 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,inst);
|
||||
return pwf;
|
||||
auto fn = taxonomy::make<taxonomy::offset_function>(curve, offsets);
|
||||
return fn;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "mapping.h"
|
||||
#include "../profile_helper.h"
|
||||
#include "../piecewise_function_evaluator.h"
|
||||
#include "../function_item_evaluator.h"
|
||||
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
@@ -28,11 +28,15 @@ using namespace ifcopenshell::geometry;
|
||||
|
||||
taxonomy::ptr mapping::map_impl(const IfcSchema::IfcPointByDistanceExpression* inst) {
|
||||
auto u = (*inst->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>()) * length_unit_;
|
||||
//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()));
|
||||
piecewise_function_evaluator evaluator(pw_curve,&settings_);
|
||||
auto basis_curve = map(inst->BasisCurve());
|
||||
taxonomy::function_item::ptr curve = taxonomy::dcast<taxonomy::function_item>(basis_curve);
|
||||
if (!curve) {
|
||||
// if the basis curve is not a function_item, the cast it to piecewise_function. the casting operator
|
||||
// calls loop_to_piecewise_function_upgrade and will convert loops to a piecewise function
|
||||
curve = taxonomy::dcast<taxonomy::piecewise_function>(basis_curve);
|
||||
}
|
||||
|
||||
function_item_evaluator evaluator(settings_,curve);
|
||||
auto m = evaluator.evaluate(u);
|
||||
|
||||
auto o = m.col(3).head<3>();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#define mapping POSTFIX_SCHEMA(mapping)
|
||||
using namespace ifcopenshell::geometry;
|
||||
|
||||
#include "../piecewise_function_evaluator.h"
|
||||
#include "../function_item_evaluator.h"
|
||||
|
||||
#ifdef SCHEMA_HAS_IfcSegmentedReferenceCurve
|
||||
|
||||
@@ -31,14 +31,16 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins
|
||||
|
||||
auto segments = inst->Segments();
|
||||
|
||||
std::vector<taxonomy::piecewise_function::ptr> pwfs;
|
||||
taxonomy::piecewise_function::spans_t spans;
|
||||
for (auto& segment : *segments) {
|
||||
if (segment->as<IfcSchema::IfcCurveSegment>()) {
|
||||
// @todo check that we don't get a mixture of implicit and explicit definitions
|
||||
auto crv = map(segment->as<IfcSchema::IfcCurveSegment>());
|
||||
if (crv && crv->kind() == taxonomy::PIECEWISE_FUNCTION) {
|
||||
pwfs.push_back(taxonomy::cast<taxonomy::piecewise_function>(crv));
|
||||
} else {
|
||||
if (auto fi = taxonomy::dcast<taxonomy::function_item>(crv); crv && fi /*crv->kind() == taxonomy::FUNCTION_ITEM*/) {
|
||||
// crv->kind() is polymorphic and the kind of the actual function_item is returned. PWF can have spans of any FUNCTION_ITEM
|
||||
// for this reason, a dynamic cast is used and if crv is a function_item it is added to the span
|
||||
spans.push_back(fi);
|
||||
} else {
|
||||
Logger::Error("Unsupported");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -55,61 +57,15 @@ 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);
|
||||
auto cant = taxonomy::make<taxonomy::piecewise_function>(cant_start,spans);
|
||||
auto gradient = taxonomy::cast<taxonomy::gradient_function>(map(inst->BaseCurve()));
|
||||
|
||||
// Determine the valid domain of the PWF... the valid domain is where
|
||||
// horizontal, gradient and cant curves are defined
|
||||
auto gradient = taxonomy::cast<taxonomy::piecewise_function>(map(inst->BaseCurve()));
|
||||
auto horizontal = taxonomy::cast<taxonomy::piecewise_function>(map(inst->BaseCurve()->as<IfcSchema::IfcGradientCurve>()->BaseCurve()));
|
||||
double start = std::max(std::max(cant->start(), gradient->start()), horizontal->start());
|
||||
double end = std::min(std::min(cant->end(), gradient->end()), horizontal->end());
|
||||
double length = end - start;
|
||||
|
||||
if (!(0 < length)) {
|
||||
Logger::Error("IfcSegmentedReferenceCurve does not have a common domain with BaseCurve");
|
||||
}
|
||||
|
||||
// define the callback function for the segmented reference curve
|
||||
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_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
|
||||
// they are relative to the gradient curve coordinate system
|
||||
//
|
||||
// However, the coordinate points don't need to have the rotations
|
||||
// of g applied. Save off the x,y,z and cant values
|
||||
auto x = g(0, 3);
|
||||
auto y = g(1, 3);
|
||||
auto z = g(2, 3);
|
||||
auto s = c(1, 3); // superelevation
|
||||
|
||||
// change column 3 to (0,0,0,1)
|
||||
Eigen::Vector4d p(0, 0, 0, 1);
|
||||
g.col(3) = p;
|
||||
c.col(3) = p;
|
||||
|
||||
// multiply g and c to get the axes in the correct orientation
|
||||
Eigen::Matrix4d m = g * c;
|
||||
|
||||
// reinstate the values for x and y.
|
||||
// z is the gradient curve z value plus the superelevation
|
||||
// that comes from the cant.
|
||||
m(0, 3) = x;
|
||||
m(1, 3) = y;
|
||||
m(2, 3) = z + s;
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
taxonomy::piecewise_function::spans_t spans;
|
||||
spans.emplace_back(length, composition);
|
||||
auto pwf = taxonomy::make<taxonomy::piecewise_function>(start, spans, inst);
|
||||
return pwf;
|
||||
auto cant_function = taxonomy::make<taxonomy::cant_function>(gradient, cant, inst);
|
||||
if (!(0 < cant_function->length())) {
|
||||
Logger::Error("IfcSegmentedReferenceCurve does not have a common domain with BaseCurve");
|
||||
cant_function = nullptr;
|
||||
}
|
||||
return cant_function;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
#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, const 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};
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#include "piecewise_function_impl.h"
|
||||
#include "profile_helper.h"
|
||||
|
||||
namespace ifcopenshell {
|
||||
|
||||
namespace geometry {
|
||||
|
||||
namespace taxonomy {
|
||||
|
||||
piecewise_function_impl::piecewise_function_impl(double start, const spans_t& s) : start_(start), spans_(s) {
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
const piecewise_function_impl::spans_t& piecewise_function_impl::spans() const { return spans_; }
|
||||
|
||||
bool piecewise_function_impl::is_empty() const { return spans_.empty(); }
|
||||
|
||||
double piecewise_function_impl::start() const {
|
||||
return start_;
|
||||
}
|
||||
|
||||
double piecewise_function_impl::end() const {
|
||||
return start_ + length();
|
||||
}
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
piecewise_function_impl* piecewise_function_impl::clone_() const { return new piecewise_function_impl(*this); }
|
||||
|
||||
} // namespace taxonomy
|
||||
|
||||
} // namespace geometry
|
||||
|
||||
} // namespace ifcopenshell
|
||||
@@ -1,37 +0,0 @@
|
||||
#ifndef PIECEWISE_FUNCTION_IMPL
|
||||
#define PIECEWISE_FUNCTION_IMPL
|
||||
|
||||
#include "taxonomy.h"
|
||||
|
||||
namespace ifcopenshell {
|
||||
|
||||
namespace geometry {
|
||||
|
||||
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);
|
||||
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 spans_t& spans() const;
|
||||
bool is_empty() const;
|
||||
double start() const;
|
||||
double end() const;
|
||||
double length() const;
|
||||
piecewise_function_impl* clone_() const;
|
||||
|
||||
private:
|
||||
double start_ = 0.0; // starting value of the pwf
|
||||
spans_t spans_;
|
||||
|
||||
//mutable boost::optional<double> length_; // used for length() method
|
||||
};
|
||||
|
||||
} // namespace taxonomy
|
||||
} // namespace geometry
|
||||
} // namespace ifcopenshell
|
||||
#endif PIECEWISE_FUNCTION_IMPL
|
||||
+100
-17
@@ -1,7 +1,7 @@
|
||||
#include "../ifcparse/IfcLogger.h"
|
||||
#include "taxonomy.h"
|
||||
#include "profile_helper.h"
|
||||
#include "piecewise_function_impl.h"
|
||||
#include "function_item_evaluator.h"
|
||||
|
||||
using namespace ifcopenshell::geometry::taxonomy;
|
||||
|
||||
@@ -163,10 +163,30 @@ namespace {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const function_item&, const function_item&) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const functor_item&, const functor_item&) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const piecewise_function&, const piecewise_function&) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const gradient_function&, const gradient_function&) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const cant_function&, const cant_function&) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const offset_function&, const offset_function&) {
|
||||
throw std::runtime_error("not implemented");
|
||||
}
|
||||
|
||||
bool compare(const style& a, const style& b) {
|
||||
const int order[5] = {
|
||||
less_to_order(a.name, b.name),
|
||||
@@ -464,27 +484,58 @@ ifcopenshell::geometry::taxonomy::solid::ptr ifcopenshell::geometry::create_box(
|
||||
}
|
||||
|
||||
///////////////////
|
||||
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 spans_t& s, const IfcUtil::IfcBaseInterface* instance) : function_item(instance), start_(start), spans_(s) {
|
||||
}
|
||||
|
||||
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(double start, const std::vector<piecewise_function::ptr>& pwfs, const IfcUtil::IfcBaseInterface* instance) : function_item(instance), start_(start) {
|
||||
for (auto& pwf : pwfs) {
|
||||
spans_.insert(spans_.end(), pwf->spans().begin(), pwf->spans().end());
|
||||
}
|
||||
};
|
||||
|
||||
piecewise_function::piecewise_function(const piecewise_function& other) : implicit_item(other) {
|
||||
impl_ = other.impl_->clone_();
|
||||
const piecewise_function::spans_t& piecewise_function::spans() const { return spans_; }
|
||||
bool piecewise_function::is_empty() const { return spans_.empty(); }
|
||||
double piecewise_function::start() const { return start_; }
|
||||
double piecewise_function::end() const { return start_ + length(); }
|
||||
double piecewise_function::length() const {
|
||||
return std::accumulate(spans_.begin(), spans_.end(), 0.0, [](const auto& v, const auto& s) { return v + s->length(); });
|
||||
|
||||
// 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->length(); });
|
||||
//}
|
||||
//return *length_;
|
||||
}
|
||||
|
||||
piecewise_function::~piecewise_function() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
const piecewise_function::spans_t& piecewise_function::spans() const { return impl_->spans(); }
|
||||
bool piecewise_function::is_empty() const { return impl_->is_empty(); }
|
||||
double piecewise_function::start() const { return impl_->start(); }
|
||||
double piecewise_function::end() const { return impl_->end(); }
|
||||
double piecewise_function::length() const { return impl_->length(); }
|
||||
gradient_function::gradient_function(piecewise_function::const_ptr horizontal, piecewise_function::const_ptr vertical, const IfcUtil::IfcBaseInterface* instance) :
|
||||
function_item(instance), horizontal_(horizontal), vertical_(vertical) {
|
||||
}
|
||||
double gradient_function::start() const { return std::max(horizontal_->start(), vertical_->start()); }
|
||||
double gradient_function::end() const { return std::min(horizontal_->end(), vertical_->end()); }
|
||||
piecewise_function::const_ptr gradient_function::get_horizontal() const { return horizontal_; }
|
||||
piecewise_function::const_ptr gradient_function::get_vertical() const { return vertical_; }
|
||||
|
||||
|
||||
cant_function::cant_function(gradient_function::const_ptr gradient, piecewise_function::const_ptr cant, const IfcUtil::IfcBaseInterface* instance) :
|
||||
function_item(instance), gradient_(gradient), cant_(cant) {
|
||||
}
|
||||
double cant_function::start() const { return std::max(gradient_->start(), cant_->start()); }
|
||||
double cant_function::end() const { return std::min(gradient_->end(), cant_->end()); }
|
||||
gradient_function::const_ptr cant_function::get_gradient() const { return gradient_; }
|
||||
piecewise_function::const_ptr cant_function::get_cant() const { return cant_; }
|
||||
|
||||
|
||||
offset_function::offset_function(function_item::const_ptr basis, piecewise_function::const_ptr offset, const IfcUtil::IfcBaseInterface* instance) : function_item(instance),
|
||||
basis_(basis),
|
||||
offset_(offset) {
|
||||
}
|
||||
double offset_function::start() const { return basis_->start(); }
|
||||
double offset_function::end() const { return basis_->end(); }
|
||||
function_item::const_ptr offset_function::get_basis() const { return basis_; }
|
||||
piecewise_function::const_ptr offset_function::get_offset() const { return offset_; }
|
||||
|
||||
|
||||
ifcopenshell::geometry::taxonomy::collection::ptr ifcopenshell::geometry::flatten(const taxonomy::collection::ptr& deep) {
|
||||
@@ -499,7 +550,39 @@ const std::string& ifcopenshell::geometry::taxonomy::kind_to_string(kinds k) {
|
||||
using namespace std::string_literals;
|
||||
|
||||
static std::string values[] = {
|
||||
"matrix4"s, "point3"s, "direction3"s, "line"s, "circle"s, "ellipse"s, "bspline_curve"s, "offset_curve"s, "plane"s, "cylinder"s, "sphere"s, "torus"s, "bspline_surface"s, "edge"s, "loop"s, "face"s, "shell"s, "solid"s, "loft"s, "extrusion"s, "revolve"s, "sweep_along_curve"s, "node"s, "collection"s, "boolean_result"s, "piecewise_function"s, "colour"s, "style"s,
|
||||
"matrix4"s,
|
||||
"point3"s,
|
||||
"direction3"s,
|
||||
"line"s,
|
||||
"circle"s,
|
||||
"ellipse"s,
|
||||
"bspline_curve"s,
|
||||
"offset_curve"s,
|
||||
"plane"s,
|
||||
"cylinder"s,
|
||||
"sphere"s,
|
||||
"torus"s,
|
||||
"bspline_surface"s,
|
||||
"edge"s,
|
||||
"loop"s,
|
||||
"face"s,
|
||||
"shell"s,
|
||||
"solid"s,
|
||||
"loft"s,
|
||||
"extrusion"s,
|
||||
"revolve"s,
|
||||
"sweep_along_curve"s,
|
||||
"node"s,
|
||||
"collection"s,
|
||||
"boolean_result"s,
|
||||
"function_item"s,
|
||||
"functor_item"s,
|
||||
"piecewise_function"s,
|
||||
"gradient_function"s,
|
||||
"cant_function"s,
|
||||
"offset_function"s,
|
||||
"colour"s,
|
||||
"style"s,
|
||||
};
|
||||
|
||||
return values[k];
|
||||
@@ -743,7 +826,7 @@ boost::optional<piecewise_function::ptr> ifcopenshell::geometry::taxonomy::loop_
|
||||
axis = refDirection.cross(Y).normalized();
|
||||
return make<matrix4>(o, axis, refDirection)->components();
|
||||
};
|
||||
spans.emplace_back(l, fn);
|
||||
spans.emplace_back(taxonomy::make<taxonomy::functor_item>(l, fn));
|
||||
}
|
||||
pwf_ = make<piecewise_function>(0.0,spans);
|
||||
loop_->pwf = pwf_;
|
||||
|
||||
+185
-16
@@ -93,7 +93,50 @@ typedef item const* ptr;
|
||||
topology_error(const char* const s) : std::runtime_error(s) {}
|
||||
};
|
||||
|
||||
enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE_CURVE, OFFSET_CURVE, PLANE, CYLINDER, SPHERE, TORUS, BSPLINE_SURFACE, EDGE, LOOP, FACE, SHELL, SOLID, LOFT, EXTRUSION, REVOLVE, SWEEP_ALONG_CURVE, NODE, COLLECTION, BOOLEAN_RESULT, PIECEWISE_FUNCTION, COLOUR, STYLE };
|
||||
// Implementer note: If you add a new item type, be sure to do the following
|
||||
// 1) Add a new kind to this list
|
||||
// 2) Update the values array used by kind_to_string()
|
||||
// 3) Update the KindsTuple with the class name of the new item
|
||||
// 4) Add compare function (see compare functions in taxonomy.cpp starting around line 9)
|
||||
// 4) Update Python bindings
|
||||
// a) update list of assign_repr in IfcGeomWrapper.i
|
||||
// b) update inheritance list in IfcGeomWrapper.i (around line 120 in the file)
|
||||
// c) update item_to_pyobject function definition in type_conversion.i
|
||||
enum kinds {
|
||||
MATRIX4,
|
||||
POINT3,
|
||||
DIRECTION3,
|
||||
LINE,
|
||||
CIRCLE,
|
||||
ELLIPSE,
|
||||
BSPLINE_CURVE,
|
||||
OFFSET_CURVE,
|
||||
PLANE,
|
||||
CYLINDER,
|
||||
SPHERE,
|
||||
TORUS,
|
||||
BSPLINE_SURFACE,
|
||||
EDGE,
|
||||
LOOP,
|
||||
FACE,
|
||||
SHELL,
|
||||
SOLID,
|
||||
LOFT,
|
||||
EXTRUSION,
|
||||
REVOLVE,
|
||||
SWEEP_ALONG_CURVE,
|
||||
NODE,
|
||||
COLLECTION,
|
||||
BOOLEAN_RESULT,
|
||||
FUNCTION_ITEM,
|
||||
FUNCTOR_ITEM,
|
||||
PIECEWISE_FUNCTION,
|
||||
GRADIENT_FUNCTION,
|
||||
CANT_FUNCTION,
|
||||
OFFSET_FUNCTION,
|
||||
COLOUR,
|
||||
STYLE
|
||||
};
|
||||
|
||||
const std::string& kind_to_string(kinds k);
|
||||
|
||||
@@ -358,25 +401,73 @@ typedef item const* ptr;
|
||||
using geom_item::geom_item;
|
||||
};
|
||||
|
||||
struct piecewise_function_impl; // forward declaration
|
||||
struct piecewise_function : public implicit_item {
|
||||
struct function_item : public implicit_item {
|
||||
DECLARE_PTR(function_item)
|
||||
|
||||
function_item(const IfcUtil::IfcBaseInterface* instance = nullptr) : implicit_item(instance) {}
|
||||
function_item(function_item&&) = default;
|
||||
function_item(const function_item&) = default;
|
||||
|
||||
virtual ~function_item() = default;
|
||||
virtual double start() const = 0;
|
||||
virtual double end() const = 0;
|
||||
virtual double length() const {
|
||||
return end() - start();
|
||||
}
|
||||
|
||||
virtual kinds kind() const { return FUNCTION_ITEM; }
|
||||
virtual size_t calc_hash() const {
|
||||
auto v = std::make_tuple(static_cast<size_t>(FUNCTION_ITEM), 0);
|
||||
return boost::hash<decltype(v)>{}(v);
|
||||
};
|
||||
};
|
||||
|
||||
struct functor_item : public function_item {
|
||||
DECLARE_PTR(functor_item)
|
||||
|
||||
functor_item(double length, std::function<Eigen::Matrix4d(double u)> fn, const IfcUtil::IfcBaseInterface* instance = nullptr) : function_item(instance),
|
||||
length_(length), fn_(fn) {}
|
||||
functor_item(functor_item&&) = default;
|
||||
functor_item(const functor_item&) = default;
|
||||
virtual ~functor_item() = default;
|
||||
|
||||
double start() const override { return 0.0; }
|
||||
double end() const override { return length_; }
|
||||
|
||||
Eigen::Matrix4d operator()(double u) const { return fn_(u); }
|
||||
|
||||
functor_item* clone_() const override { return new functor_item(*this); }
|
||||
virtual kinds kind() const { return FUNCTOR_ITEM; }
|
||||
virtual size_t calc_hash() const {
|
||||
auto v = std::make_tuple(static_cast<size_t>(FUNCTOR_ITEM), 0);
|
||||
return boost::hash<decltype(v)>{}(v);
|
||||
}
|
||||
|
||||
private:
|
||||
double length_;
|
||||
std::function<Eigen::Matrix4d(double u)> fn_;
|
||||
};
|
||||
|
||||
struct piecewise_function : public function_item {
|
||||
DECLARE_PTR(piecewise_function)
|
||||
|
||||
using spans_t = std::vector<std::pair<double, std::function<Eigen::Matrix4d(double u)>>>;
|
||||
using spans_t = std::vector<function_item::const_ptr>;
|
||||
|
||||
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();
|
||||
piecewise_function(const piecewise_function&) = default;
|
||||
virtual ~piecewise_function() = default;
|
||||
|
||||
const spans_t& spans() const;
|
||||
size_t span_count() const {return spans_.size();}
|
||||
function_item::const_ptr span_fn(size_t i) { return spans_[i]; }
|
||||
bool is_empty() const;
|
||||
double start() const;
|
||||
double end() const;
|
||||
double length() const;
|
||||
double start() const override;
|
||||
double end() const override;
|
||||
double length() const override;
|
||||
|
||||
virtual piecewise_function* clone_() const { return new piecewise_function(*this); }
|
||||
piecewise_function* clone_() const override { return new piecewise_function(*this); }
|
||||
virtual kinds kind() const { return PIECEWISE_FUNCTION; }
|
||||
|
||||
virtual size_t calc_hash() const {
|
||||
@@ -385,11 +476,89 @@ typedef item const* ptr;
|
||||
}
|
||||
|
||||
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.
|
||||
// if this is a std::unique_ptr, then the _ifcopenshell_wrapper library doesn't compile
|
||||
piecewise_function_impl* impl_ = nullptr;
|
||||
};
|
||||
double start_ = 0.0; // starting value of the pwf
|
||||
spans_t spans_;
|
||||
};
|
||||
|
||||
struct gradient_function : public function_item {
|
||||
DECLARE_PTR(gradient_function)
|
||||
gradient_function(piecewise_function::const_ptr horizontal, piecewise_function::const_ptr vertical, const IfcUtil::IfcBaseInterface* instance = nullptr);
|
||||
gradient_function(gradient_function&&) = default;
|
||||
gradient_function(const gradient_function&) = default;
|
||||
virtual ~gradient_function() = default;
|
||||
|
||||
virtual double start() const override;
|
||||
virtual double end() const override;
|
||||
|
||||
piecewise_function::const_ptr get_horizontal() const;
|
||||
piecewise_function::const_ptr get_vertical() const;
|
||||
|
||||
gradient_function* clone_() const override { return new gradient_function(*this); }
|
||||
|
||||
virtual kinds kind() const { return GRADIENT_FUNCTION; }
|
||||
|
||||
virtual size_t calc_hash() const {
|
||||
auto v = std::make_tuple(static_cast<size_t>(GRADIENT_FUNCTION), 0);
|
||||
return boost::hash<decltype(v)>{}(v);
|
||||
}
|
||||
|
||||
private:
|
||||
piecewise_function::const_ptr horizontal_, vertical_;
|
||||
};
|
||||
|
||||
struct cant_function : public function_item {
|
||||
DECLARE_PTR(cant_function)
|
||||
cant_function(gradient_function::const_ptr gradient, piecewise_function::const_ptr cant, const IfcUtil::IfcBaseInterface* instance = nullptr);
|
||||
cant_function(cant_function&&) = default;
|
||||
cant_function(const cant_function&) = default;
|
||||
virtual ~cant_function() = default;
|
||||
|
||||
virtual double start() const override;
|
||||
virtual double end() const override;
|
||||
|
||||
gradient_function::const_ptr get_gradient() const;
|
||||
piecewise_function::const_ptr get_cant() const;
|
||||
|
||||
cant_function* clone_() const override { return new cant_function(*this); }
|
||||
|
||||
virtual kinds kind() const { return CANT_FUNCTION; }
|
||||
|
||||
virtual size_t calc_hash() const {
|
||||
auto v = std::make_tuple(static_cast<size_t>(CANT_FUNCTION), 0);
|
||||
return boost::hash<decltype(v)>{}(v);
|
||||
}
|
||||
|
||||
private:
|
||||
gradient_function::const_ptr gradient_;
|
||||
piecewise_function::const_ptr cant_;
|
||||
};
|
||||
|
||||
struct offset_function : public function_item {
|
||||
DECLARE_PTR(offset_function)
|
||||
offset_function(function_item::const_ptr basis, piecewise_function::const_ptr offset, const IfcUtil::IfcBaseInterface* instance = nullptr);
|
||||
offset_function(offset_function&&) = default;
|
||||
offset_function(const offset_function&) = default;
|
||||
virtual ~offset_function() = default;
|
||||
|
||||
virtual double start() const override;
|
||||
virtual double end() const override;
|
||||
|
||||
function_item::const_ptr get_basis() const;
|
||||
piecewise_function::const_ptr get_offset() const;
|
||||
|
||||
offset_function* clone_() const override { return new offset_function(*this); }
|
||||
|
||||
virtual kinds kind() const { return OFFSET_FUNCTION; }
|
||||
|
||||
virtual size_t calc_hash() const {
|
||||
auto v = std::make_tuple(static_cast<size_t>(OFFSET_FUNCTION), 0);
|
||||
return boost::hash<decltype(v)>{}(v);
|
||||
}
|
||||
|
||||
private:
|
||||
function_item::const_ptr basis_;
|
||||
piecewise_function::const_ptr offset_;
|
||||
};
|
||||
|
||||
#ifdef TAXONOMY_USE_SHARED_PTR
|
||||
typedef std::shared_ptr<item> ptr;
|
||||
@@ -1041,7 +1210,7 @@ typedef item const* ptr;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, offset_curve, plane, cylinder, sphere, torus, bspline_surface, edge, loop, face, shell, solid, loft, extrusion, revolve, sweep_along_curve, node, collection, boolean_result, piecewise_function> KindsTuple;
|
||||
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, offset_curve, plane, cylinder, sphere, torus, bspline_surface, edge, loop, face, shell, solid, loft, extrusion, revolve, sweep_along_curve, node, collection, boolean_result, function_item, functor_item, piecewise_function, gradient_function, cant_function,offset_function> KindsTuple;
|
||||
typedef std::tuple<line, circle, ellipse, bspline_curve, offset_curve, loop, edge> CurvesTuple;
|
||||
typedef std::tuple<plane, cylinder, sphere, torus, bspline_surface, extrusion, revolve> SurfacesTuple;
|
||||
typedef std::tuple<edge, loop, face, piecewise_function> UpgradesTuple;
|
||||
|
||||
@@ -135,7 +135,12 @@ std::pair<char const*, size_t> vector_to_buffer(const T& t) {
|
||||
if (!$1) $1 = try_upcast<matrix4>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__matrix4_t);
|
||||
if (!$1) $1 = try_upcast<node>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__node_t);
|
||||
if (!$1) $1 = try_upcast<offset_curve>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__offset_curve_t);
|
||||
if (!$1) $1 = try_upcast<function_item>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__function_item_t);
|
||||
if (!$1) $1 = try_upcast<functor_item>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__functor_item_t);
|
||||
if (!$1) $1 = try_upcast<piecewise_function>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__piecewise_function_t);
|
||||
if (!$1) $1 = try_upcast<gradient_function>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__gradient_function_t);
|
||||
if (!$1) $1 = try_upcast<cant_function>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__cant_function_t);
|
||||
if (!$1) $1 = try_upcast<offset_function>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__offset_function_t);
|
||||
if (!$1) $1 = try_upcast<plane>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__plane_t);
|
||||
if (!$1) $1 = try_upcast<point3>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__point3_t);
|
||||
if (!$1) $1 = try_upcast<revolve>($input, SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__revolve_t);
|
||||
@@ -199,7 +204,12 @@ namespace {
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::boolean_result);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::item);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::implicit_item);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::function_item);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::functor_item);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::piecewise_function);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::gradient_function);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::cant_function);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::offset_function);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::less_functor);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::eigen_base);
|
||||
%shared_ptr(ifcopenshell::geometry::taxonomy::matrix4);
|
||||
@@ -246,7 +256,7 @@ namespace {
|
||||
%include "../ifcgeom/Iterator.h"
|
||||
%include "../ifcgeom/GeometrySerializer.h"
|
||||
%include "../ifcgeom/taxonomy.h"
|
||||
%include "../ifcgeom/piecewise_function_evaluator.h"
|
||||
%include "../ifcgeom/function_item_evaluator.h"
|
||||
|
||||
%include "../serializers/SvgSerializer.h"
|
||||
%include "../serializers/HdfSerializer.h"
|
||||
@@ -358,7 +368,7 @@ assign_matrix_access(revolve);
|
||||
void set_(const std::string& name, ifcopenshell::geometry::settings::IteratorOutputOptions val) {
|
||||
return $self->set(name, val);
|
||||
}
|
||||
void set_(const std::string& name, ifcopenshell::geometry::settings::PiecewiseStepMethod val) {
|
||||
void set_(const std::string& name, ifcopenshell::geometry::settings::FunctionStepMethod val) {
|
||||
return $self->set(name, val);
|
||||
}
|
||||
void set_(const std::string& name, ifcopenshell::geometry::settings::OutputDimensionalityTypes val) {
|
||||
@@ -1291,7 +1301,12 @@ assign_repr(ifcopenshell::geometry::taxonomy::loop)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::matrix4)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::node)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::offset_curve)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::function_item)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::functor_item)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::piecewise_function)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::gradient_function)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::cant_function)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::offset_function)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::plane)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::point3)
|
||||
assign_repr(ifcopenshell::geometry::taxonomy::revolve)
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
%{
|
||||
#include "../ifcgeom/Iterator.h"
|
||||
#include "../ifcgeom/taxonomy.h"
|
||||
#include "../ifcgeom/piecewise_function_evaluator.h"
|
||||
#include "../ifcgeom/function_item_evaluator.h"
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
#include "../ifcgeom/Serialization/Serialization.h"
|
||||
#include "../ifcgeom/kernels/opencascade/IfcGeomTree.h"
|
||||
@@ -265,7 +265,7 @@ constexpr bool is_std_vector_vector_v = is_std_vector_vector<T>::value;
|
||||
%module ifcopenshell_wrapper %{
|
||||
#include "../ifcgeom/Converter.h"
|
||||
#include "../ifcgeom/taxonomy.h"
|
||||
#include "../ifcgeom/piecewise_function_evaluator.h"
|
||||
#include "../ifcgeom/function_item_evaluator.h"
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
#include "../ifcgeom/Serialization/Serialization.h"
|
||||
#include "../ifcgeom/kernels/opencascade/IfcGeomTree.h"
|
||||
|
||||
@@ -261,7 +261,12 @@ PyObject* item_to_pyobject(const ifcopenshell::geometry::taxonomy::item::ptr& i)
|
||||
else if (kind == MATRIX4) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<matrix4>(std::static_pointer_cast<matrix4>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__matrix4_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == NODE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<node>(std::static_pointer_cast<node>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__node_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == OFFSET_CURVE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<offset_curve>(std::static_pointer_cast<offset_curve>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__offset_curve_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == FUNCTION_ITEM) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<function_item>(std::static_pointer_cast<function_item>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__function_item_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == FUNCTOR_ITEM) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<functor_item>(std::static_pointer_cast<functor_item>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__functor_item_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == PIECEWISE_FUNCTION) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<piecewise_function>(std::static_pointer_cast<piecewise_function>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__piecewise_function_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == GRADIENT_FUNCTION) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<gradient_function>(std::static_pointer_cast<gradient_function>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__gradient_function_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == CANT_FUNCTION) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<cant_function>(std::static_pointer_cast<cant_function>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__cant_function_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == OFFSET_FUNCTION) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<offset_function>(std::static_pointer_cast<offset_function>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__offset_function_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == PLANE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<plane>(std::static_pointer_cast<plane>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__plane_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == POINT3) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<point3>(std::static_pointer_cast<point3>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__point3_t, 0 | SWIG_POINTER_OWN); }
|
||||
else if (kind == REVOLVE) { return SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<revolve>(std::static_pointer_cast<revolve>(i))), SWIGTYPE_p_std__shared_ptrT_ifcopenshell__geometry__taxonomy__revolve_t, 0 | SWIG_POINTER_OWN); }
|
||||
|
||||
Reference in New Issue
Block a user