diff --git a/src/ifcgeom/ConversionSettings.cpp b/src/ifcgeom/ConversionSettings.cpp index e2fc14175d..36669c7971 100644 --- a/src/ifcgeom/ConversionSettings.cpp +++ b/src/ifcgeom/ConversionSettings.cpp @@ -37,3 +37,17 @@ std::istream& ifcopenshell::geometry::settings::operator>>(std::istream& in, Ite } return in; } + +std::istream& ifcopenshell::geometry::settings::operator>>(std::istream& in, PiecewiseStepMethod& ioo) { + std::string token; + in >> token; + boost::to_upper(token); + if (token == "MAXSTEPSIZE") { + ioo = MAXSTEPSIZE; + } else if (token == "MINSTEPS") { + ioo = MINSTEPS; + } else { + in.setstate(std::ios_base::failbit); + } + return in; +} diff --git a/src/ifcgeom/ConversionSettings.h b/src/ifcgeom/ConversionSettings.h index 18195f2f75..2a8e8115c5 100644 --- a/src/ifcgeom/ConversionSettings.h +++ b/src/ifcgeom/ConversionSettings.h @@ -300,12 +300,29 @@ namespace ifcopenshell { static constexpr const char* const description = "Overrides transparency of spaces in geometry output."; }; + enum PiecewiseStepMethod { + MAXSTEPSIZE, + MINSTEPS }; + + std::istream& operator>>(std::istream& in, PiecewiseStepMethod& ioo); + + struct PiecewiseStepType : public SettingBase { + 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 PiecewiseStepParam : public SettingBase { + 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 + }; } template class IFC_GEOM_API SettingsContainer { public: - typedef boost::variant, IteratorOutputOptions> value_variant_t; + typedef boost::variant, IteratorOutputOptions, PiecewiseStepMethod> value_variant_t; private: settings_t settings; @@ -385,7 +402,7 @@ namespace ifcopenshell { }; class IFC_GEOM_API Settings : public SettingsContainer< - std::tuple + std::tuple > {}; } diff --git a/src/ifcgeom/mapping/IfcCompositeCurve.cpp b/src/ifcgeom/mapping/IfcCompositeCurve.cpp index 7d73741a9c..be5e723785 100644 --- a/src/ifcgeom/mapping/IfcCompositeCurve.cpp +++ b/src/ifcgeom/mapping/IfcCompositeCurve.cpp @@ -23,7 +23,7 @@ using namespace ifcopenshell::geometry; taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCompositeCurve* inst) { auto loop = taxonomy::make(); - auto pwf = taxonomy::make(); + auto pwf = taxonomy::make(&settings_); #ifdef SCHEMA_HAS_IfcSegment // 4x3 diff --git a/src/ifcgeom/mapping/IfcCurveSegment.cpp b/src/ifcgeom/mapping/IfcCurveSegment.cpp index dd6a856761..db36841328 100644 --- a/src/ifcgeom/mapping/IfcCurveSegment.cpp +++ b/src/ifcgeom/mapping/IfcCurveSegment.cpp @@ -942,7 +942,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcCurveSegment* inst) { auto length = fabs(cse.length()); // @todo it might be suboptimal that we no longer have the spans now - auto pwf = taxonomy::make(); + auto pwf = taxonomy::make(&settings_); pwf->spans.push_back({ length, fn }); pwf->instance = inst; return pwf; diff --git a/src/ifcgeom/mapping/IfcGradientCurve.cpp b/src/ifcgeom/mapping/IfcGradientCurve.cpp index a01d42f488..56c42c69be 100644 --- a/src/ifcgeom/mapping/IfcGradientCurve.cpp +++ b/src/ifcgeom/mapping/IfcGradientCurve.cpp @@ -28,7 +28,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) { Logger::Warning("Expected IfcGradientCurve.BaseCurve to be IfcCompositeCurve", inst); // CT 4.1.7.1.1.2 auto horizontal = taxonomy::cast(map(inst->BaseCurve())); - auto vertical = taxonomy::make(); + auto vertical = taxonomy::make(&settings_); auto segments = inst->Segments(); @@ -73,7 +73,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcGradientCurve* inst) { } } - auto pwf = taxonomy::make(); + auto pwf = taxonomy::make(&settings_); pwf->spans.emplace_back( min_length, composition ); pwf->instance = inst; return pwf; diff --git a/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp b/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp index 32c6ff03cc..390db1ee71 100644 --- a/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp +++ b/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp @@ -46,7 +46,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst basis_curve_length += s.first; } - auto offsets = taxonomy::make(); + auto offsets = taxonomy::make(&settings_); #if defined SCHEMA_HAS_IfcDistanceExpression double first_distance = first_offset_value->DistanceAlong(); @@ -153,7 +153,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst // current implementation assumes that offsets is equal to the full length of basis curve // this may change depending on decisions in the bSI-IF - auto pwf = taxonomy::make(); + auto pwf = taxonomy::make(&settings_); pwf->spans.emplace_back( basis_curve_length, composition ); pwf->instance = inst; return pwf; diff --git a/src/ifcgeom/mapping/IfcSegmentedReferenceCurve.cpp b/src/ifcgeom/mapping/IfcSegmentedReferenceCurve.cpp index 7a94c68296..095b41e9c9 100644 --- a/src/ifcgeom/mapping/IfcSegmentedReferenceCurve.cpp +++ b/src/ifcgeom/mapping/IfcSegmentedReferenceCurve.cpp @@ -28,7 +28,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins Logger::Warning("Expected IfcSegmentedReferenceCurve.BaseCurve to be IfcGradient", inst); // CT 4.1.7.1.1.3 auto gradient = taxonomy::cast(map(inst->BaseCurve())); - auto cant = taxonomy::make(); + auto cant = taxonomy::make(&settings_); auto segments = inst->Segments(); @@ -76,7 +76,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcSegmentedReferenceCurve* ins } } - auto pwf = taxonomy::make(); + auto pwf = taxonomy::make(&settings_); pwf->spans.emplace_back( min_length, composition ); pwf->instance = inst; return pwf; diff --git a/src/ifcgeom/taxonomy.cpp b/src/ifcgeom/taxonomy.cpp index 45b0b1ad9d..f206e91501 100644 --- a/src/ifcgeom/taxonomy.cpp +++ b/src/ifcgeom/taxonomy.cpp @@ -459,11 +459,20 @@ ifcopenshell::geometry::taxonomy::item::ptr ifcopenshell::geometry::taxonomy::pi length += s.first; std::vector polygon; + + auto param_type = settings_ ? settings_->get().get() : ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE; + auto param = settings_ ? settings_->get().get() : 0.5; + int num_steps = 0; + if (param_type == ifcopenshell::geometry::settings::PiecewiseStepMethod::MAXSTEPSIZE) { + // parameter is max step size + num_steps = (int)std::ceil(length / param); + } else { + // parameter is minimum number of steps + num_steps = (int)std::ceil(param); + } + auto resolution = length / num_steps; - static const double target_resolution = 0.5; - int num_steps = (int)std::ceil(length / target_resolution); - auto resolution = length / num_steps; - for (int i = 0; i <= num_steps; ++i) { + for (int i = 0; i <= num_steps; ++i) { auto u = resolution * i; Eigen::Matrix4d m = evaluate(u); polygon.push_back(taxonomy::make(m.col(3)(0), m.col(3)(1), m.col(3)(2))); diff --git a/src/ifcgeom/taxonomy.h b/src/ifcgeom/taxonomy.h index 8d1358351c..b0392d73ce 100644 --- a/src/ifcgeom/taxonomy.h +++ b/src/ifcgeom/taxonomy.h @@ -3,6 +3,8 @@ #include "../ifcparse/IfcBaseClass.h" +#include "ConversionSettings.h" + #include #include @@ -127,6 +129,7 @@ typedef item const* ptr; struct implicit_item : public item { DECLARE_PTR(implicit_item) + using item::item; virtual item::ptr evaluate() const = 0; }; @@ -134,6 +137,13 @@ typedef item const* ptr; struct piecewise_function : public implicit_item { DECLARE_PTR(piecewise_function) + piecewise_function(const IfcUtil::IfcBaseInterface* instance = nullptr) : implicit_item(instance){}; + piecewise_function(ifcopenshell::geometry::Settings* settings) : settings_(settings){}; + piecewise_function(piecewise_function&&) = default; + piecewise_function(const piecewise_function&) = default; + + ifcopenshell::geometry::Settings* settings_ = nullptr; + // length of span, function to evaluate span std::vector>> spans;