diff --git a/src/ifcgeom/function_item_evaluator.cpp b/src/ifcgeom/function_item_evaluator.cpp index f924dae4a6..9bacf94ac0 100644 --- a/src/ifcgeom/function_item_evaluator.cpp +++ b/src/ifcgeom/function_item_evaluator.cpp @@ -122,7 +122,7 @@ struct gradient_fn_evaluator : public fn_evaluator { // Put curvature back into the solution matrix // curvature for vertical is in column 0, need it to be in column 1 // so it doesn't add to curvature for horizontal - std::swap(vertical_curvature(3, 0), vertical_curvature(3, 1)); + std::swap(vertical_curvature(0), vertical_curvature(1)); m.row(3) = horizontal_curvature + vertical_curvature; return m; diff --git a/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp b/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp index e42cc840a6..a506049a95 100644 --- a/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp +++ b/src/ifcgeom/mapping/IfcOffsetCurveByDistance.cpp @@ -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(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()) { +// basis_curve = offset_curve; +// } +// +//#if defined SCHEMA_HAS_IfcGradientCurve +// if (auto gc = basis_curve->as()) { +// basis_curve = gc->BaseCurve(); +// } +//#endif + + auto basis_curve_fn = taxonomy::dcast(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(); #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(); double dp = *(*prev)->DistanceAlong()->as(); + double dn = *(*next)->DistanceAlong()->as(); #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(start,offset_spans); - auto fn = taxonomy::make(curve, offsets); + auto fn = taxonomy::make(basis_curve_fn, offsets); return fn; } diff --git a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py index 1667a7b352..c41fe12c28 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py +++ b/src/ifcopenshell-python/ifcopenshell/api/alignment/create_as_offset_curve.py @@ -54,9 +54,9 @@ def create_as_offset_curve( _create_offset_curve_representation(file, alignment, offsets) # define stationing - name = ifcopenshell.util.alignment.station_as_string(file, start_station) - referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, start_station, name) - ifcopenshell.api.nest.reorder_nesting(file, referent, -1, 0) + #name = ifcopenshell.util.alignment.station_as_string(file, start_station) + #referent = ifcopenshell.api.alignment.add_stationing_referent(file, alignment, 0.0, start_station, name) + #ifcopenshell.api.nest.reorder_nesting(file, referent, -1, 0) # IFC 4.1.4.1.1 Alignment Aggregation To Project project = file.by_type("IfcProject")[0]