From a34e42a519cf24848b0bc15b7f120b0d08fea59d Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 13 Nov 2025 12:43:41 +0100 Subject: [PATCH] Handle infra sweeps of open loops #7338 --- src/ifcgeom/infra_sweep_helper.cpp | 26 ++++++++++++------- .../mapping/IfcArbitraryOpenProfileDef.cpp | 8 +++++- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/ifcgeom/infra_sweep_helper.cpp b/src/ifcgeom/infra_sweep_helper.cpp index f9d50f5b00..b9c9e598d9 100644 --- a/src/ifcgeom/infra_sweep_helper.cpp +++ b/src/ifcgeom/infra_sweep_helper.cpp @@ -136,11 +136,11 @@ taxonomy::loft::ptr ifcopenshell::geometry::make_loft(const Settings& settings_, } auto interpolated_offset = lerp(offset_a, offset_b, relative_dist_along); - if (rotation_a && rotation_b) { - // @todo we don't support an overridden rotation on only one of the placements - // in which case we would need to lerp with the rotation component below in m4b. - interpolated_rotation = lerp(*rotation_a, *rotation_b, relative_dist_along); - } else { + if (rotation_a == rotation_b && rotation_a) { + // @todo we don't support an overridden rotation on only one of the placements + // in which case we would need to lerp with the rotation component below in m4b. + interpolated_rotation = lerp(*rotation_a, *rotation_b, relative_dist_along); + } else if (rotation_a != rotation_b) { Logger::Error("Direction vectors on cross section placements only supported when used consistently"); } taxonomy::loop::ptr w1, w2; @@ -165,10 +165,18 @@ taxonomy::loft::ptr ifcopenshell::geometry::make_loft(const Settings& settings_, // auto p4 = (interpolated_rotation * p3).eval(); points.push_back(taxonomy::make(p3)); } - if (!points.empty()) { - // close polygon by referencing first point - // @todo add a closed=true|false to polygon_from_points()? - points.push_back(points.front()); + if (!points.empty()) { + if (!w1->closed.get_value_or(true) && !w2->closed.get_value_or(true)) { + // open polygon, add last point + auto& p1 = boost::get(w1->children.back()->end); + auto& p2 = boost::get(w2->children.back()->end); + auto p3 = (lerp(p1->ccomponents(), p2->ccomponents(), relative_dist_along) + interpolated_offset).eval(); + points.push_back(taxonomy::make(p3)); + } else if (w1->closed.get_value_or(true) && w2->closed.get_value_or(true)) { + // close polygon by referencing first point + // @todo add a closed=true|false to polygon_from_points()? + points.push_back(points.front()); + } } auto interpolated_loop = polygon_from_points(points); diff --git a/src/ifcgeom/mapping/IfcArbitraryOpenProfileDef.cpp b/src/ifcgeom/mapping/IfcArbitraryOpenProfileDef.cpp index ef39550354..e65152cb7f 100644 --- a/src/ifcgeom/mapping/IfcArbitraryOpenProfileDef.cpp +++ b/src/ifcgeom/mapping/IfcArbitraryOpenProfileDef.cpp @@ -24,5 +24,11 @@ using namespace ifcopenshell::geometry; taxonomy::ptr mapping::map_impl(const IfcSchema::IfcArbitraryOpenProfileDef* inst) { - return map(inst->Curve()); + auto mapped = map(inst->Curve()); + if (mapped->kind() == taxonomy::LOOP) { + auto r = taxonomy::loop::ptr((taxonomy::loop*)mapped->clone_()); + r->closed = false; + return r; + } + return mapped; }