Fixes IfcOffsetCurveByDistance

This commit is contained in:
Richard Brice
2025-07-25 17:32:11 -07:00
parent bb56882879
commit a824141b90
3 changed files with 33 additions and 21 deletions
@@ -39,15 +39,29 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
auto first_offset_value = *(offset_values->begin());
auto basis_curve = inst->BasisCurve();
auto curve = taxonomy::dcast<taxonomy::function_item>(map(basis_curve));
if (!curve) {
// // IfcOffsetCurveByDistances can be based on another IfcOffsetCurveByDistances, an IfcGradientCurve, or an IfcCompositeCurve
// // When based on IfcOffsetCurveByDistances, it creates a chain of curves that we must navigate down to the base curve.
// // The source curve is IfcGradientCurve or IfcCompositeCurve. This loop drills down to the base curve.
// while (auto offset_curve = basis_curve->as<IfcSchema::IfcOffsetCurveByDistances>()) {
// basis_curve = offset_curve;
// }
//
//#if defined SCHEMA_HAS_IfcGradientCurve
// if (auto gc = basis_curve->as<IfcSchema::IfcGradientCurve>()) {
// basis_curve = gc->BaseCurve();
// }
//#endif
auto basis_curve_fn = taxonomy::dcast<taxonomy::function_item>(map(basis_curve));
if (!basis_curve_fn) {
// Only implement on alignment curves
Logger::Warning("IfcOffsetCurveByDistances is only implemented for BasisCurves curves based on taxonomy::function_item", inst);
return nullptr;
}
double start = curve->start();
double basis_curve_length = curve->length();
double start = basis_curve_fn->start();
double basis_curve_length = basis_curve_fn->length();
taxonomy::piecewise_function::spans_t offset_spans;
@@ -56,6 +70,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
#else
double first_distance = *first_offset_value->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
#endif
first_distance *= length_unit_;
if (first_distance < 0.0) {
Logger::Warning("IfcOffsetCurveByDistance first offset value is before the start of the curve.");
@@ -83,31 +98,28 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
auto prev = std::prev(next);
auto end = offset_values->end();
for (; next != end; prev++, next++) {
#if defined SCHEMA_HAS_IfcPointByDistanceExpression
if ((*prev)->BasisCurve() != basis_curve || (*next)->BasisCurve() != basis_curve) {
Logger::Error("All offsets from a IfcOffsetCurveByDistances must refer to the same BasisCurve");
}
#endif
#if defined SCHEMA_HAS_IfcDistanceExpression
double dn = (*next)->DistanceAlong();
double dp = (*prev)->DistanceAlong();
double dn = (*next)->DistanceAlong();
#else
double dn = *(*next)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
double dp = *(*prev)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
double dn = *(*next)->DistanceAlong()->as<IfcSchema::IfcLengthMeasure>();
#endif
if ((dp < 0.0 || basis_curve_length < dp)
dp *= length_unit_;
dn *= length_unit_;
if ((dp < 0.0 || basis_curve_length < dp) // previous is out of range
||
(dn < 0.0 || basis_curve_length < dn)
(dn < 0.0 || basis_curve_length < dn) // next is out of range
||
(dn < dp)
(dn < dp) // next is before previous
)
{
Logger::Warning("IfcOffsetCurveByDistance offset value is out of bounds.");
continue;
}
double l = (dn - dp)*length_unit_;
double l = (dn - dp);
double yn = (*next)->OffsetLateral().get_value_or(0.0) * length_unit_;
double yp = (*prev)->OffsetLateral().get_value_or(0.0) * length_unit_;
double zn = (*next)->OffsetVertical().get_value_or(0.0) * length_unit_;
@@ -152,7 +164,7 @@ taxonomy::ptr mapping::map_impl(const IfcSchema::IfcOffsetCurveByDistances* inst
auto offsets = taxonomy::make<taxonomy::piecewise_function>(start,offset_spans);
auto fn = taxonomy::make<taxonomy::offset_function>(curve, offsets);
auto fn = taxonomy::make<taxonomy::offset_function>(basis_curve_fn, offsets);
return fn;
}