ifcgeom: fall back to unsliced representation when layerset slicing fails #6607

--enable-layerset-slicing aborted the entire IfcConvert run (0 objects) on the
first element whose layerset could not be resolved. get_layerset_information
can throw (e.g. a wall Axis representation that is not castable to a curve ->
"Unexpected topology"), and apply_layerset / apply_folded_layerset resolve to
the AbstractKernel stubs that throw not_implemented on the OpenCascade kernel.
That exception was uncaught at the call site, so it propagated out and dropped
every element, not just the one that failed.

Wrap the layerset block in a try/catch: on failure, log GEO 260 and keep the
element's already-built unsliced body representation instead of letting the
exception abort the conversion. Elements that slice successfully are untouched
(the previous return values were already ignored).

Verified with a local OpenCascade build (OCC 7.9.2) on the reporter's
Cassiopae sample: --enable-layerset-slicing before the fix exits 1 with 0
objects (GEO060 Unexpected topology); after the fix it emits all 215 objects
(90 GEO260 fallback warnings), and default (no-slicing) output is byte-identical
before and after. Note: geometric slicing itself is not implemented on the
OpenCascade kernel on this line, so the recovered elements are emitted unsliced;
this change only stops the flag from silently dropping them.

Generated with the assistance of an AI coding tool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Petru Conduraru
2026-07-11 21:06:29 +03:00
parent a0f493b471
commit 1b57803d82
+21 -9
View File
@@ -55,17 +55,29 @@ IfcGeom::BRepElement* ifcopenshell::geometry::Converter::create_brep_for_represe
std::map<IfcUtil::IfcBaseEntity*, ifcopenshell::geometry::layerset_information> neigbour_layers;
int layerset_id, lid;
if (mapping_->get_layerset_information(product, layerinfo, layerset_id)) {
representation_id_builder << "-layerset-" << layerset_id;
if (mapping_->get_wall_neighbours(product, neighbours)) {
for (auto& n : neighbours) {
auto p = std::get<2>(n);
mapping_->get_layerset_information(p, neigbour_layers[p], lid);
// Layerset slicing is best-effort: gathering the layerset information or
// applying it may throw (e.g. when the axis representation cannot be cast
// to a curve, or when the active kernel does not implement slicing). In
// that case the element still has a perfectly valid unsliced body
// representation in `shapes`, so we fall back to that rather than letting
// the exception propagate and silently drop the element entirely (#6607).
try {
if (mapping_->get_layerset_information(product, layerinfo, layerset_id)) {
representation_id_builder << "-layerset-" << layerset_id;
if (mapping_->get_wall_neighbours(product, neighbours)) {
for (auto& n : neighbours) {
auto p = std::get<2>(n);
mapping_->get_layerset_information(p, neigbour_layers[p], lid);
}
kernel_->apply_folded_layerset(shapes, layerinfo, neigbour_layers);
} else {
kernel_->apply_layerset(shapes, layerinfo);
}
kernel_->apply_folded_layerset(shapes, layerinfo, neigbour_layers);
} else {
kernel_->apply_layerset(shapes, layerinfo);
}
} catch (const std::exception& e) {
logger_.Message(Logger::LOG_WARNING, "GEO", 260, std::string("Layerset slicing failed, falling back to unsliced representation: ") + e.what(), product);
} catch (...) {
logger_.Message(Logger::LOG_WARNING, "GEO", 260, "Layerset slicing failed, falling back to unsliced representation", product);
}
/*