From 1a6fd2530f7da9a8870ae6625ddb538f67048cc7 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 14 Mar 2026 14:44:47 +0100 Subject: [PATCH] Remove dependency on Standard_failure #7788 --- src/ifcgeom/Iterator.cpp | 25 +- src/ifcgeom/Iterator.h | 4 - .../kernels/opencascade/OpenCascadeKernel.cpp | 1140 +---------------- .../kernels/opencascade/OpenCascadeKernel.h | 15 + .../kernels/opencascade/boolean_result.cpp | 2 + src/ifcgeom/kernels/opencascade/extrusion.cpp | 4 + src/ifcgeom/kernels/opencascade/face.cpp | 4 + src/ifcgeom/kernels/opencascade/loft.cpp | 4 + src/ifcgeom/kernels/opencascade/loop.cpp | 8 + src/ifcgeom/kernels/opencascade/shell.cpp | 4 + src/ifcgeom/kernels/opencascade/solid.cpp | 4 + .../kernels/opencascade/sweep_along_curve.cpp | 4 + 12 files changed, 72 insertions(+), 1146 deletions(-) diff --git a/src/ifcgeom/Iterator.cpp b/src/ifcgeom/Iterator.cpp index a7f700f4de..4db7db8946 100644 --- a/src/ifcgeom/Iterator.cpp +++ b/src/ifcgeom/Iterator.cpp @@ -620,17 +620,7 @@ const IfcGeom::Element* IfcGeom::Iterator::get_object(int id) { } } catch (const std::exception& e) { Logger::Error(e); - } -#ifdef IFOPSH_WITH_OPENCASCADE - catch (const Standard_Failure& e) { - if (e.GetMessageString() && strlen(e.GetMessageString())) { - Logger::Error(e.GetMessageString()); - } else { - Logger::Error("Unknown error returning product"); - } - } -#endif - catch (...) { + } catch (...) { Logger::Error("Unknown error returning product"); } @@ -645,18 +635,7 @@ const IfcUtil::IfcBaseClass* IfcGeom::Iterator::create() { } catch (const std::exception& e) { Logger::Error(e); had_error_processing_elements_ = true; - } -#ifdef IFOPSH_WITH_OPENCASCADE - catch (const Standard_Failure& e) { - if (e.GetMessageString() && strlen(e.GetMessageString())) { - Logger::Error(e.GetMessageString()); - } else { - Logger::Error("Unknown error creating geometry"); - } - had_error_processing_elements_ = true; - } -#endif - catch (...) { + } catch (...) { Logger::Error("Unknown error creating geometry"); had_error_processing_elements_ = true; } diff --git a/src/ifcgeom/Iterator.h b/src/ifcgeom/Iterator.h index 3f5f90a350..fc9e542d60 100644 --- a/src/ifcgeom/Iterator.h +++ b/src/ifcgeom/Iterator.h @@ -68,10 +68,6 @@ #include "../ifcgeom/abstract_mapping.h" #include "../ifcgeom/GeometrySerializer.h" -#ifdef IFOPSH_WITH_OPENCASCADE -#include -#endif - #include #include diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.cpp index a5a9d94149..e8b672906e 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.cpp @@ -255,1126 +255,28 @@ bool IfcGeom::OpenCascadeKernel::unify_shapes(const IfcGeom::ConversionResults& } bool IfcGeom::OpenCascadeKernel::convert_impl(const taxonomy::revolve::ptr r, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + gp_Ax1 ax( + convert_xyz(*r->axis_origin), + convert_xyz(*r->direction)); + TopoDS_Shape face; + if (!convert(taxonomy::cast(r->basis), face)) { + return false; + } - gp_Ax1 ax( - convert_xyz(*r->axis_origin), - convert_xyz(*r->direction)); + TopoDS_Shape shape; + if (r->angle) { + shape = BRepPrimAPI_MakeRevol(face, ax, *r->angle); + } else { + shape = BRepPrimAPI_MakeRevol(face, ax); + } - TopoDS_Shape face; - if (!convert(taxonomy::cast(r->basis), face)) { - return false; - } - - TopoDS_Shape shape; - if (r->angle) { - shape = BRepPrimAPI_MakeRevol(face, ax, *r->angle); - } else { - shape = BRepPrimAPI_MakeRevol(face, ax); - } - - results.emplace_back(ConversionResult( - r->instance->as()->id(), - r->matrix, - new OpenCascadeShape(shape), - r->surface_style - )); - return true; + results.emplace_back(ConversionResult( + r->instance->as()->id(), + r->matrix, + new OpenCascadeShape(shape), + r->surface_style)); + return true; + }); } - -// IfcSchema::IfcRelVoidsElement::list::ptr IfcGeom::Kernel::find_openings(IfcSchema::IfcProduct* product) { -// std::vector rs; -// -// if (product->declaration().is(IfcSchema::IfcElement::Class()) && !product->declaration().is(IfcSchema::IfcOpeningElement::Class())) { -// IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)product; -// auto rels = element->HasOpenings(); -// rs.insert(rs.end(), rels->begin(), rels->end()); -// } -// -// // Is the IfcElement a decomposition of an IfcElement with any IfcOpeningElements? -// IfcSchema::IfcObjectDefinition* obdef = product->as(); -// for (;;) { -// auto decomposes = obdef->Decomposes(); -// if (decomposes->size() != 1) break; -// IfcSchema::IfcObjectDefinition* rel_obdef = (*decomposes->begin())->RelatingObject(); -// if (rel_obdef->declaration().is(IfcSchema::IfcElement::Class()) && !rel_obdef->declaration().is(IfcSchema::IfcOpeningElement::Class())) { -// IfcSchema::IfcElement* element = (IfcSchema::IfcElement*)rel_obdef; -// auto rels = element->HasOpenings(); -// rs.insert(rs.end(), rels->begin(), rels->end()); -// } -// -// obdef = rel_obdef; -// } -// -// // Filter openings in Reference view, solely marked as Reference. -// IfcSchema::IfcRelVoidsElement::list::ptr openings(new IfcSchema::IfcRelVoidsElement::list); -// std::for_each(rs.begin(), rs.end(), [&openings](IfcSchema::IfcRelVoidsElement* rel) { -// if (rel->RelatedOpeningElement()->ObjectPlacement() && rel->RelatedOpeningElement()->Representation()) { -// auto reps = rel->RelatedOpeningElement()->Representation()->Representations(); -// if (!(reps->size() == 1 && (*reps->begin())->RepresentationIdentifier().get_value_or("") == "Reference")) { -// openings->push(rel); -// } -// } -// }); -// -// return openings; -// } -// -// const IfcSchema::IfcMaterial* IfcGeom::Kernel::get_single_material_association(const IfcSchema::IfcProduct* product) { -// IfcSchema::IfcMaterial* single_material = 0; -// IfcSchema::IfcRelAssociatesMaterial::list::ptr associated_materials = product->HasAssociations()->as(); -// if (associated_materials->size() == 1) { -// IfcSchema::IfcMaterialSelect* associated_material = (*associated_materials->begin())->RelatingMaterial(); -// single_material = associated_material->as(); -// -// // NB: IfcMaterialLayerSets are also considered, regardless of --enable-layerset-slicing. Picking -// // the first material (in accordance with other viewers) when layerset-slicing is disabled. -// if (!single_material && associated_material->as()) { -// IfcSchema::IfcMaterialLayerSet* layerset = associated_material->as()->ForLayerSet(); -// if (getValue(GV_LAYERSET_FIRST) > 0.0 ? layerset->MaterialLayers()->size() >= 1 : layerset->MaterialLayers()->size() == 1) { -// IfcSchema::IfcMaterialLayer* layer = (*layerset->MaterialLayers()->begin()); -// if (layer->Material()) { -// single_material = layer->Material(); -// } -// } -// } -// } -// return single_material; -// } -// -// IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_representation_and_product( -// const IteratorSettings& settings, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product) -// { -// std::stringstream representation_id_builder; -// -// representation_id_builder << representation->data().id(); -// -// IfcGeom::Representation::BRep* shape; -// IfcGeom::ConversionResults shapes, shapes2; -// -// if (!convert_shapes(representation, shapes)) { -// return 0; -// } -// -// if (settings.get(IteratorSettings::APPLY_LAYERSETS)) { -// TopoDS_Shape merge; -// if (util::flatten_shape_list(shapes, merge, false, getValue(GV_PRECISION))) { -// if (util::count(merge, TopAbs_FACE) > 0) { -// std::vector thickness; -// std::vector layers; -// std::vector< std::vector > folded_layers; -// std::vector> styles; -// if (convert_layerset(product, layers, styles, thickness)) { -// -// IfcSchema::IfcRelAssociates::list::ptr associations = product->HasAssociations(); -// for (IfcSchema::IfcRelAssociates::list::it it = associations->begin(); it != associations->end(); ++it) { -// IfcSchema::IfcRelAssociatesMaterial* associates_material = (**it).as(); -// if (associates_material) { -// unsigned layerset_id = associates_material->RelatingMaterial()->data().id(); -// representation_id_builder << "-layerset-" << layerset_id; -// break; -// } -// } -// -// if (styles.size() > 1) { -// // If there's only a single layer there is no need to manipulate geometries. -// bool success = true; -// if (product->as() && fold_layers(product->as(), shapes, layers, thickness, folded_layers)) { -// if (util::apply_folded_layerset(shapes, folded_layers, styles, shapes2, getValue(GV_PRECISION))) { -// std::swap(shapes, shapes2); -// success = true; -// } -// } else { -// if (util::apply_layerset(shapes, layers, styles, shapes2, getValue(GV_PRECISION))) { -// std::swap(shapes, shapes2); -// success = true; -// } -// } -// -// if (!success) { -// Logger::Error("Failed processing layerset"); -// } -// } -// } -// } -// } -// } -// -// bool material_style_applied = false; -// -// const IfcSchema::IfcMaterial* single_material = get_single_material_association(product); -// if (single_material) { -// auto s = get_style(single_material); -// for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) { -// if (!it->hasStyle() && s) { -// it->setStyle(s); -// material_style_applied = true; -// } -// } -// } else { -// bool some_items_without_style = false; -// for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) { -// if (!it->hasStyle() && util::count(it->Shape(), TopAbs_FACE)) { -// some_items_without_style = true; -// break; -// } -// } -// if (some_items_without_style) { -// Logger::Warning("No material and surface styles for:", product); -// } -// } -// -// if (material_style_applied) { -// representation_id_builder << "-material-" << single_material->data().id(); -// } -// -// if (settings.force_space_transparency() >= 0. && product->declaration().is("IfcSpace")) { -// for (auto& s : shapes) { -// if (s.hasStyle()) { -// for (auto& p : style_cache) { -// if (p.second == s.StylePtr()) { -// std::const_pointer_cast(p.second)->Transparency() = settings.force_space_transparency(); -// } -// } -// } -// } -// } -// -// int parent_id = -1; -// try { -// IfcUtil::IfcBaseEntity* parent_object = get_decomposing_entity(product); -// if (parent_object && parent_object->as()) { -// parent_id = parent_object->data().id(); -// } -// } catch (const std::exception& e) { -// Logger::Error(e); -// } -// -// const std::string name = product->Name().get_value_or(""); -// const std::string guid = product->GlobalId(); -// -// gp_Trsf trsf; -// try { -// if (product->ObjectPlacement()) { -// convert(product->ObjectPlacement(), trsf); -// } -// } catch (const std::exception& e) { -// Logger::Error(e); -// } catch (...) { -// Logger::Error("Failed to construct placement"); -// } -// -// // Does the IfcElement have any IfcOpenings? -// // Note that openings for IfcOpeningElements are not processed -// IfcSchema::IfcRelVoidsElement::list::ptr openings = find_openings(product); -// -// const std::string product_type = product->declaration().name(); -// ElementSettings element_settings(settings, getValue(GV_LENGTH_UNIT), product_type); -// -// if (!settings.get(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS) && openings && openings->size()) { -// representation_id_builder << "-openings"; -// for (IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++it) { -// representation_id_builder << "-" << (*it)->data().id(); -// } -// -// IfcGeom::ConversionResults opened_shapes; -// bool caught_error = false; -// try { -// convert_openings(product, openings, shapes, trsf, opened_shapes); -// } catch (const std::exception& e) { -// Logger::Message(Logger::LOG_ERROR, std::string("Error processing openings for: ") + e.what() + ":", product); -// caught_error = true; -// } catch (...) { -// Logger::Message(Logger::LOG_ERROR, "Error processing openings for:", product); -// } -// -// if (caught_error && opened_shapes.size() < shapes.size()) { -// opened_shapes = shapes; -// } -// -// if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { -// for (IfcGeom::ConversionResults::iterator it = opened_shapes.begin(); it != opened_shapes.end(); ++it) { -// it->prepend(trsf); -// } -// trsf = gp_Trsf(); -// representation_id_builder << "-world-coords"; -// } -// shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), opened_shapes); -// } else if (settings.get(IteratorSettings::USE_WORLD_COORDS)) { -// for (IfcGeom::ConversionResults::iterator it = shapes.begin(); it != shapes.end(); ++it) { -// it->prepend(trsf); -// } -// trsf = gp_Trsf(); -// representation_id_builder << "-world-coords"; -// shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), shapes); -// } else { -// shape = new IfcGeom::Representation::BRep(element_settings, representation_id_builder.str(), shapes); -// } -// -// std::string context_string = ""; -// if (representation->RepresentationIdentifier()) { -// context_string = *representation->RepresentationIdentifier(); -// } else if (representation->ContextOfItems()->ContextType()) { -// context_string = *representation->ContextOfItems()->ContextType(); -// } -// -// auto elem = new BRepElement( -// product->data().id(), -// parent_id, -// name, -// product_type, -// guid, -// context_string, -// trsf, -// boost::shared_ptr(shape), -// product -// ); -// -// if (settings.get(IteratorSettings::VALIDATE_QUANTITIES)) { -// auto rels = product->IsDefinedBy(); -// for (auto& rel : *rels) { -// if (rel->as()) { -// auto pdef = rel->as()->RelatingPropertyDefinition(); -// if (pdef->as()) { -// std::string organization_name; -// try { -// // A couple of files are not according to the schema here. -// organization_name = pdef->as()->OwnerHistory()->OwningApplication()->ApplicationDeveloper()->Name(); -// } catch (...) {} -// if (organization_name == "IfcOpenShell") { -// auto qs = pdef->as()->Quantities(); -// for (auto& q : *qs) { -// if (q->as() && q->Name() == "Total Surface Area") { -// double a_calc; -// double a_file = q->as()->AreaValue(); -// if (elem->geometry().calculate_surface_area(a_calc)) { -// double diff = std::abs(a_calc - a_file); -// if (diff / std::sqrt(a_file) > getValue(GV_PRECISION)) { -// Logger::Error("Validation of surface area failed for:", product); -// } else { -// Logger::Notice("Validation of surface area succeeded for:", product); -// } -// } else { -// Logger::Error("Validation of surface area failed for:", product); -// } -// } else if (q->as() && q->Name() == "Volume") { -// double v_calc; -// double v_file = q->as()->VolumeValue(); -// if (elem->geometry().calculate_volume(v_calc)) { -// double diff = std::abs(v_calc - v_file); -// if (diff / std::sqrt(v_file) > getValue(GV_PRECISION)) { -// Logger::Error("Validation of volume failed for:", product); -// } else { -// Logger::Notice("Validation of volume succeeded for:", product); -// } -// } else { -// Logger::Error("Validation of volume failed for:", product); -// } -// } else if (q->as() && q->Name() == "Shape Validation Properties") { -// auto qs2 = q->as()->HasQuantities(); -// bool all_succeeded = qs2->size() > 0; -// for (auto& q2 : *qs2) { -// if (q2->as() && q2->Name() == "Surface Genus" && q2->Description()) { -// int item_id = boost::lexical_cast((*q2->Description()).substr(1)); -// int genus = (int)q2->as()->CountValue(); -// for (auto& part : elem->geometry()) { -// if (part.ItemId() == item_id) { -// if (util::surface_genus(part.Shape()) != genus) { -// all_succeeded = false; -// } -// } -// } -// } -// } -// if (!all_succeeded) { -// Logger::Error("Validation of surface genus failed for:", product); -// } else { -// Logger::Notice("Validation of surface genus succeeded for:", product); -// } -// } -// } -// } -// } -// } -// } -// } -// -// return elem; -// } -// -// IfcSchema::IfcRepresentation* IfcGeom::Kernel::representation_mapped_to(const IfcSchema::IfcRepresentation* representation) { -// IfcSchema::IfcRepresentation* representation_mapped_to = 0; -// try { -// IfcSchema::IfcRepresentationItem::list::ptr items = representation->Items(); -// if (items->size() == 1) { -// IfcSchema::IfcRepresentationptr item = *items->begin(); -// if (item->declaration().is(IfcSchema::IfcMappedItem::Class())) { -// if (item->StyledByItem()->size() == 0) { -// IfcSchema::IfcMappedptr mapped_item = item->as(); -// if (is_identity_transform(mapped_item->MappingTarget())) { -// IfcSchema::IfcRepresentationMap* map = mapped_item->MappingSource(); -// if (is_identity_transform(map->MappingOrigin())) { -// representation_mapped_to = map->MappedRepresentation(); -// } -// } -// } -// } -// } -// } catch (const IfcParse::IfcException& e) { -// Logger::Error(e); -// // @todo reset representation_mapped_to to zero? -// } -// return representation_mapped_to; -// } -// -// IfcSchema::IfcProduct::list::ptr IfcGeom::Kernel::products_represented_by(const IfcSchema::IfcRepresentation* representation) { -// IfcSchema::IfcProduct::list::ptr products(new IfcSchema::IfcProduct::list); -// -// IfcSchema::IfcProductRepresentation::list::ptr prodreps = representation->OfProductRepresentation(); -// -// for (IfcSchema::IfcProductRepresentation::list::it it = prodreps->begin(); it != prodreps->end(); ++it) { -// // http://buildingsmart-tech.org/ifc/IFC2x3/TC1/html/ifcrepresentationresource/lexical/ifcproductrepresentation.htm -// // IFC2x Edition 3 NOTE Users should not instantiate the entity IfcProductRepresentation from IFC2x Edition 3 onwards. -// // It will be changed into an ABSTRACT supertype in future releases of IFC. -// -// // IfcProductRepresentation also lacks the INVERSE relation to IfcProduct -// // Let's find the IfcProducts that reference the IfcProductRepresentation anyway -// products->push((*it)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as()); -// } -// -// IfcSchema::IfcRepresentationMap::list::ptr maps = representation->RepresentationMap(); -// -// if (products->size() && maps->size()) { -// Logger::Warning("Representation used by IfcRepresentationMap and IfcProductDefinitionShape", representation); -// } -// -// if (prodreps->size() > 1) { -// Logger::Warning("Multiple IfcProductDefinitionShapes for representation", representation); -// } -// -// if (maps->size() > 1) { -// Logger::Warning("Multiple IfcRepresentationMaps for representation", representation); -// } -// -// if (maps->size() == 1) { -// IfcSchema::IfcRepresentationMap* map = *maps->begin(); -// if (is_identity_transform(map->MappingOrigin())) { -// IfcSchema::IfcMappedItem::list::ptr items = map->MapUsage(); -// for (IfcSchema::IfcMappedItem::list::it it = items->begin(); it != items->end(); ++it) { -// IfcSchema::IfcMappedptr item = *it; -// if (item->StyledByItem()->size() != 0) continue; -// -// if (!is_identity_transform(item->MappingTarget())) { -// continue; -// } -// -// IfcSchema::IfcRepresentation::list::ptr reps = item->data().getInverse((&IfcSchema::IfcRepresentation::Class()), -1)->as(); -// for (IfcSchema::IfcRepresentation::list::it jt = reps->begin(); jt != reps->end(); ++jt) { -// IfcSchema::IfcRepresentation* rep = *jt; -// if (rep->Items()->size() != 1) continue; -// IfcSchema::IfcProductRepresentation::list::ptr prodreps_mapped = rep->OfProductRepresentation(); -// for (IfcSchema::IfcProductRepresentation::list::it kt = prodreps_mapped->begin(); kt != prodreps_mapped->end(); ++kt) { -// IfcSchema::IfcProduct::list::ptr ps = (*kt)->data().getInverse((&IfcSchema::IfcProduct::Class()), -1)->as(); -// products->push(ps); -// } -// } -// } -// } -// } -// -// return products; -// } -// -// IfcGeom::BRepElement* IfcGeom::Kernel::create_brep_for_processed_representation( -// const IteratorSettings& /*settings*/, IfcSchema::IfcRepresentation* representation, IfcSchema::IfcProduct* product, -// IfcGeom::BRepElement* brep) -// { -// int parent_id = -1; -// try { -// IfcUtil::IfcBaseEntity* parent_object = get_decomposing_entity(product); -// if (parent_object && parent_object->as()) { -// parent_id = parent_object->data().id(); -// } -// } catch (const std::exception& e) { -// Logger::Error(e); -// } -// -// const std::string name = product->Name().get_value_or(""); -// const std::string guid = product->GlobalId(); -// -// gp_Trsf trsf; -// try { -// if (product->ObjectPlacement()) { -// convert(product->ObjectPlacement(), trsf); -// } -// } catch (const std::exception& e) { -// Logger::Error(e); -// } catch (...) { -// Logger::Error("Failed to construct placement"); -// } -// -// std::string context_string = ""; -// if (representation->RepresentationIdentifier()) { -// context_string = *representation->RepresentationIdentifier(); -// } else if (representation->ContextOfItems()->ContextType()) { -// context_string = *representation->ContextOfItems()->ContextType(); -// } -// -// const std::string product_type = product->declaration().name(); -// -// return new BRepElement( -// product->data().id(), -// parent_id, -// name, -// product_type, -// guid, -// context_string, -// trsf, -// brep->geometry_pointer(), -// product -// ); -// } -// -// bool IfcGeom::Kernel::convert_layerset(const IfcSchema::IfcProduct* product, std::vector& surfaces, std::vector>& styles, std::vector& thicknesses) { -// -// } -// -// bool IfcGeom::Kernel::find_wall_end_points(const IfcSchema::IfcWall* wall, gp_Pnt& start, gp_Pnt& end) { -// IfcSchema::IfcRepresentation* axis_representation = find_representation(wall, "Axis"); -// if (!axis_representation) { -// return false; -// } -// -// ConversionResults items; -// { -// Kernel temp = *this; -// temp.setValue(GV_DIMENSIONALITY, -1.); -// temp.convert_shapes(axis_representation, items); -// } -// -// TopoDS_Vertex a, b; -// for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { -// TopExp_Explorer exp(it->Shape(), TopAbs_VERTEX); -// for (; exp.More(); exp.Next()) { -// b = TopoDS::Vertex(exp.Current()); -// if (a.IsNull()) { -// a = b; -// } -// } -// } -// -// if (a.IsNull() || b.IsNull()) { -// return false; -// } -// -// start = BRep_Tool::Pnt(a); -// end = BRep_Tool::Pnt(b); -// -// return true; -// } -// -// bool IfcGeom::Kernel::fold_layers(const IfcSchema::IfcWall* wall, const ConversionResults& items, const std::vector& surfaces, const std::vector& thicknesses, std::vector< std::vector >& result) { -// /* -// * @todo isn't it easier to do this based on the non-folded surfaces of -// * the connected walls and fold both pairs of layersets simultaneously? -// */ -// -// bool folds_made = false; -// -// IfcSchema::IfcRelConnectsPathElements::list::ptr connections(new IfcSchema::IfcRelConnectsPathElements::list); -// connections->push(wall->ConnectedFrom()->as()); -// connections->push(wall->ConnectedTo()->as()); -// -// typedef std::vector surfaces_t; -// typedef std::pair curve_on_surface; -// typedef std::vector curves_on_surfaces_t; -// typedef std::vector< std::pair< std::pair, const IfcSchema::IfcProduct*> > endpoint_connections_t; -// typedef std::vector< std::vector > result_t; -// endpoint_connections_t endpoint_connections; -// -// // Find the semantic connections to other wall elements when they are not connected 'AT_PATH' because -// // in that latter case no folds need to be made. -// for (IfcSchema::IfcRelConnectsPathElements::list::it it = connections->begin(); it != connections->end(); ++it) { -// IfcSchema::IfcRelConnectsPathElements* connection = *it; -// IfcSchema::IfcConnectionTypeEnum::Value own_type = connection->RelatedElement() == wall -// ? connection->RelatedConnectionType() -// : connection->RelatingConnectionType(); -// IfcSchema::IfcConnectionTypeEnum::Value other_type = connection->RelatedElement() == wall -// ? connection->RelatingConnectionType() -// : connection->RelatedConnectionType(); -// if (other_type != IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATPATH && -// (own_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATEND || -// own_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART)) { -// IfcSchema::IfcElement* other = connection->RelatedElement() == wall -// ? connection->RelatingElement() -// : connection->RelatedElement(); -// if (other->as()) { -// endpoint_connections.push_back(std::make_pair(std::make_pair(own_type, other_type), other)); -// } -// } -// } -// -// if (endpoint_connections.size() == 0) { -// return false; -// } -// -// // Count how many connections are made AT_START and AT_END respectively -// int connection_type_count[2] = { 0,0 }; -// for (endpoint_connections_t::const_iterator it = endpoint_connections.begin(); it != endpoint_connections.end(); ++it) { -// const int idx = it->first.first == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART; -// connection_type_count[idx] ++; -// } -// -// gp_Trsf local; -// if (wall->ObjectPlacement()) { -// if (!convert(wall->ObjectPlacement(), local)) { -// return false; -// } -// } -// local.Invert(); -// -// { -// // Copy the unfolded surfaces -// result.resize(surfaces.size()); -// std::vector< std::vector >::iterator result_it = result.begin() + 1; -// std::vector::const_iterator input_it = surfaces.begin() + 1; -// for (; input_it != surfaces.end() - 1; ++result_it, ++input_it) { -// result_it->push_back(*input_it); -// } -// } -// -// const double total_thickness = std::accumulate(thicknesses.begin(), thicknesses.end(), 0.); -// -// gp_Pnt own_axis_start, own_axis_end; -// find_wall_end_points(wall, own_axis_start, own_axis_end); -// -// // Sometimes duplicate IfcRelConnectsPathElements exist. These are detected -// // and the counts of connections are decremented accordingly. -// for (int idx = 0; idx < 2; ++idx) { -// if (connection_type_count[idx] <= 1) { -// continue; -// } -// -// /* -// IfcSchema::IfcConnectionTypeEnum::Value connection_type = idx == 1 -// ? IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART -// : IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATEND; -// */ -// -// std::set others; -// endpoint_connections_t::iterator it = endpoint_connections.begin(); -// while (it != endpoint_connections.end()) { -// const IfcSchema::IfcProduct* other = it->second; -// if (others.find(other) != others.end()) { -// it = endpoint_connections.erase(it); -// --connection_type_count[idx]; -// } else { -// others.insert(other); -// ++it; -// } -// } -// } -// -// // Check whether the end points are of the wall are really ~1 LayerThickness away from each other -// /* -// for (endpoint_connections_t::const_iterator it = endpoint_connections.begin(); it != endpoint_connections.end(); ++it) { -// IfcSchema::IfcConnectionTypeEnum::Value own_type = it->first.first; -// IfcSchema::IfcConnectionTypeEnum::Value other_type = it->first.second; -// -// gp_Pnt other_axis_start, other_axis_end; -// find_wall_end_points(it->second->as(), other_axis_start, other_axis_end); -// -// gp_Trsf other; -// if (!convert(it->second->ObjectPlacement(), other)) { -// continue; -// } -// -// other.Transforms(other_axis_start.ChangeCoord()); -// local.Transforms(other_axis_start.ChangeCoord()); -// other.Transforms(other_axis_end.ChangeCoord()); -// local.Transforms(other_axis_end.ChangeCoord()); -// -// const gp_Pnt& a = own_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART -// ? own_axis_start -// : own_axis_end; -// -// const gp_Pnt& b = other_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART -// ? other_axis_start -// : other_axis_end; -// -// const double d = a.Distance(b); -// } -// */ -// -// const double length_required = endpoint_connections.size() * total_thickness; -// // @todo this is not precisely the distance in case of curved walls. Also, it's safer -// // to first reproject the body onto the axis to get the precise curve parametrization -// // range. It's only a safeguard though, so can probably be approximated. -// const double axis_length = own_axis_start.Distance(own_axis_end); -// if (length_required > axis_length) { -// Logger::Warning("The wall axis is not long enough to accommodate the fold points"); -// return false; -// } -// -// for (endpoint_connections_t::const_iterator it = endpoint_connections.begin(); it != endpoint_connections.end(); ++it) { -// IfcSchema::IfcConnectionTypeEnum::Value connection_type = it->first.first; -// -// // If more than one wall connects to this start/end -point assume layers do not need to be folded -// const int idx = connection_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATSTART; -// if (connection_type_count[idx] > 1) continue; -// -// // Pick the corresponding point from the axis -// const gp_Pnt& own_end_point = connection_type == IfcSchema::IfcConnectionTypeEnum::IfcConnectionType_ATEND -// ? own_axis_end -// : own_axis_start; -// const IfcSchema::IfcProduct* other_wall = it->second; -// -// gp_Trsf other; -// if (other_wall->ObjectPlacement()) { -// if (!convert(other_wall->ObjectPlacement(), other)) { -// Logger::Error("Failed to convert placement", other_wall); -// continue; -// } -// } -// -// IfcSchema::IfcRepresentation* axis_representation = find_representation(other_wall, "Axis"); -// -// if (!axis_representation) { -// Logger::Warning("Joined wall has no axis representation", other_wall); -// continue; -// } -// -// ConversionResults axis_items; -// { -// Kernel temp = *this; -// temp.setValue(GV_DIMENSIONALITY, -1.); -// temp.convert_shapes(axis_representation, axis_items); -// } -// -// TopoDS_Shape axis_shape; -// util::flatten_shape_list(axis_items, axis_shape, false, getValue(GV_PRECISION)); -// -// // local and other are IfcLocalPlacements and therefore have a unit -// // scale factor that can be applied by means of TopoDS_Shape::Move() -// axis_shape.Move(other); -// axis_shape.Move(local); -// -// TopoDS_Shape body_shape; -// util::flatten_shape_list(items, body_shape, false, getValue(GV_PRECISION)); -// -// // Create a single paremetric range over a single curve -// // that represents the entire 1d domain of the other wall -// // Sometimes there are multiple edges in the Axis shape -// // but it is assumed these are colinear. -// Handle_Geom_Curve other_axis_curve; -// double axis_u1, axis_u2; -// { -// TopExp_Explorer exp(axis_shape, TopAbs_EDGE); -// if (!exp.More()) { -// return false; -// } -// -// TopoDS_Edge axis_edge = TopoDS::Edge(exp.Current()); -// other_axis_curve = BRep_Tool::Curve(axis_edge, axis_u1, axis_u2); -// -// gp_Pnt other_a_1, other_a_2; -// other_axis_curve->D0(axis_u1, other_a_1); -// other_axis_curve->D0(axis_u2, other_a_2); -// -// if (axis_u2 < axis_u1) { -// std::swap(axis_u1, axis_u2); -// } -// exp.Next(); -// -// for (; exp.More(); exp.Next()) { -// TopoDS_Edge axis_edge2 = TopoDS::Edge(exp.Current()); -// TopExp_Explorer exp2(axis_edge2, TopAbs_VERTEX); -// for (; exp2.More(); exp2.Next()) { -// gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(exp2.Current())); -// gp_Pnt pp; -// double u, d; -// if (util::project(other_axis_curve, p, pp, u, d)) { -// if (u < axis_u1) axis_u1 = u; -// if (u > axis_u2) axis_u2 = u; -// } -// } -// } -// } -// -// double layer_offset = 0; -// -// std::vector::const_iterator thickness = thicknesses.begin(); -// result_t::iterator result_vector = result.begin() + 1; -// -// // nb The first layer is never folded, because it corresponds -// // to one of the longitudinal faces of the wall. Hence the +1 -// for (surfaces_t::const_iterator jt = surfaces.begin() + 1; jt != surfaces.end() - 1; ++jt, ++result_vector) { -// layer_offset += *thickness++; -// -// bool found_intersection = false, parallel = false; -// boost::optional point_outside_param_range; -// -// const Handle_Geom_Surface& surface = *jt; -// -// // Find the intersection point between the layerset surface -// // and the other axis curve. If it's within the parametric -// // range of the other wall it means the walls are connected -// // with an angle. -// GeomAPI_IntCS intersections(other_axis_curve, surface); -// if (intersections.IsDone() && intersections.NbPoints() == 1) { -// const gp_Pnt& p = intersections.Point(1); -// -// double u, v, w; -// intersections.Parameters(1, u, v, w); -// -// gp_Pnt Pc, Ps; -// gp_Vec Vc, Vs1, Vs2; -// other_axis_curve->D1(w, Pc, Vc); -// surface->D1(u, v, Ps, Vs1, Vs2); -// Vs1.Cross(Vs2); -// -// if (Vs1.IsNormal(Vc, 1.e-5)) { -// Logger::Warning("Connected walls are parallel"); -// parallel = true; -// } else if (w < axis_u1 || w > axis_u2) { -// point_outside_param_range = p; -// } else { -// // Found an intersection. Layer end point is covered by connecting wall -// found_intersection = true; -// break; -// } -// } -// -// if (!parallel && !found_intersection && point_outside_param_range) { -// -// /* -// Is there a bug in Open Cascade related to the intersection -// of offset surfaces constructed from linear extrusions? -// Handle_Geom_Surface xy = new Geom_Plane(gp::Origin(), gp::DZ()); -// // Handle_Geom_Surface yz = new Geom_Plane(gp::Origin(), gp::DX()); -// // Handle_Geom_Surface yz2 = new Geom_OffsetSurface(yz, 1.); -// Handle_Geom_Curve ln = new Geom_Line(gp::Origin(), gp::DX()); -// Handle_Geom_Surface yz = new Geom_SurfaceOfLinearExtrusion(ln, gp::DZ()); -// Handle_Geom_Surface yz2 = new Geom_OffsetSurface(yz, 1.); -// intersect(xy, yz2); -// */ -// -// Handle_Geom_Surface plane = new Geom_Plane(*point_outside_param_range, gp::DZ()); -// -// // vertical edges at wall end point face. -// curves_on_surfaces_t layer_ends; -// util::intersect(surface, body_shape, layer_ends); -// -// Handle_Geom_Curve layer_body_intersection; -// Handle_Geom_Surface body_surface; -// double mind = std::numeric_limits::infinity(); -// for (curves_on_surfaces_t::const_iterator kt = layer_ends.begin(); kt != layer_ends.end(); ++kt) { -// gp_Pnt p; -// gp_Vec v; -// double u, d; -// kt->second->D1(0., p, v); -// if (ALMOST_THE_SAME(0., v.Dot(gp::DZ()))) { -// // Filter horizontal curves -// continue; -// } -// // Find vertical wall end point edge closest to end point associated with semantic connection -// if (util::project(kt->second, own_end_point, p, u, d)) { -// // In addition to closest, there is a length threshold based on thickness. -// // @todo ideally, first, the point closest to end-point is selected, and -// // after that the parallel check is performed. But threshold probably -// // functions good enough. -// if (d < total_thickness * 3 && d < mind) { -// GeomAdaptor_Curve GAC(other_axis_curve); -// GeomAdaptor_Surface GAS(kt->first); -// -// Extrema_ExtCS x(GAC, GAS, getValue(GV_PRECISION), getValue(GV_PRECISION)); -// -// if (x.IsParallel()) { -// body_surface = kt->first; -// layer_body_intersection = kt->second; -// mind = d; -// } -// } -// } -// } -// -// if (body_surface.IsNull()) { -// continue; -// } -// -// // Intersect vertical edge with ground plane for point. -// GeomAPI_IntCS intersection2(layer_body_intersection, plane); -// if (intersection2.IsDone() && intersection2.NbPoints() == 1) { -// const gp_Pnt& layer_end_point = intersection2.Point(1); -// -// // Intersect layerset surface with ground plane -// GeomAPI_IntSS intersection3(surface, plane, 1.e-7); -// if (intersection3.IsDone() && intersection3.NbLines() == 1) { -// Handle_Geom_Curve layer_line = intersection3.Line(1); -// GeomAdaptor_Curve layer_line_adaptor(layer_line); -// ShapeAnalysis_Curve sac; -// gp_Pnt layer_end_point_projected; double layer_end_point_param; -// sac.Project(layer_line, layer_end_point, 1e-3, layer_end_point_projected, layer_end_point_param, false); -// -// // Move point inwards by distance from other layerset -// GCPnts_AbscissaPoint dst(layer_line_adaptor, layer_offset, layer_end_point_param); -// if (dst.IsDone()) { -// // Convert parameter to point -// gp_Pnt layer_fold_point; -// layer_line->D0(dst.Parameter(), layer_fold_point); -// -// GeomAPI_IntSS intersection4(body_surface, plane, 1.e-7); -// if (intersection4.IsDone() && intersection4.NbLines() == 1) { -// Handle_Geom_Curve body_trim_curve = intersection4.Line(1); -// ShapeAnalysis_Curve sac2; -// gp_Pnt layer_fold_point_projected; double layer_fold_point_param; -// sac2.Project(body_trim_curve, layer_fold_point, 1.e-7, layer_fold_point_projected, layer_fold_point_param, false); -// Handle_Geom_Curve fold_curve = new Geom_OffsetCurve(body_trim_curve->Reversed(), layer_fold_point_projected.Distance(layer_fold_point), gp::DZ()); -// -// Handle_Geom_Surface fold_surface = new Geom_SurfaceOfLinearExtrusion(fold_curve, gp::DZ()); -// result_vector->push_back(fold_surface); -// folds_made = true; -// } -// } -// } -// } -// -// } -// -// } -// } -// -// return folds_made; -// } -// -// IfcSchema::IfcRepresentation* IfcGeom::Kernel::find_representation(const IfcSchema::IfcProduct* product, const std::string& identifier) { -// if (!product->Representation()) return 0; -// IfcSchema::IfcProductRepresentation* prod_rep = product->Representation(); -// IfcSchema::IfcRepresentation::list::ptr reps = prod_rep->Representations(); -// for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { -// if ((**it).RepresentationIdentifier() && (*(**it).RepresentationIdentifier()) == identifier) { -// return *it; -// } -// } -// return 0; -// } -// -// const IfcSchema::IfcRepresentationptr IfcGeom::Kernel::find_item_carrying_style(const IfcSchema::IfcRepresentationptr item) { -// if (item->StyledByItem()->size()) { -// return item; -// } -// -// while (item->declaration().is(IfcSchema::IfcBooleanResult::Class())) { -// // All instantiations of IfcBooleanOperand (type of FirstOperand) are subtypes of -// // IfcGeometricRepresentationItem -// item = item->as()->FirstOperand()->as(); -// if (item && item->StyledByItem()->size()) { -// return item; -// } -// } -// -// // TODO: Ideally this would be done for other entities (such as IfcCsgSolid) as well. -// // But neither are these very prevalent, nor does the current IfcOpenShell style -// // mechanism enable to conveniently style subshapes, which would be necessary for -// // distinctly styled union operands. -// -// return item; -// } -// -// bool IfcGeom::Kernel::is_identity_transform(IfcUtil::IfcBaseInterface* l) { -// IfcSchema::IfcAxis2Placement2D* ax2d; -// IfcSchema::IfcAxis2Placement3D* ax3d; -// -// IfcSchema::IfcCartesianTransformationOperator2D* op2d; -// IfcSchema::IfcCartesianTransformationOperator3D* op3d; -// IfcSchema::IfcCartesianTransformationOperator2DnonUniform* op2dnonu; -// IfcSchema::IfcCartesianTransformationOperator3DnonUniform* op3dnonu; -// -// if ((op2dnonu = l->as()) != 0) { -// gp_GTrsf2d gtrsf2d; -// convert(op2dnonu, gtrsf2d); -// return gtrsf2d.Form() == gp_Identity; -// } else if ((op2d = l->as()) != 0) { -// gp_Trsf2d trsf2d; -// convert(op2d, trsf2d); -// return trsf2d.Form() == gp_Identity; -// } else if ((op3dnonu = l->as()) != 0) { -// gp_GTrsf gtrsf; -// convert(op3dnonu, gtrsf); -// return gtrsf.Form() == gp_Identity; -// } else if ((op3d = l->as()) != 0) { -// gp_Trsf trsf; -// convert(op3d, trsf); -// return trsf.Form() == gp_Identity; -// } else if ((ax2d = l->as()) != 0) { -// gp_Trsf2d trsf2d; -// convert(ax2d, trsf2d); -// return trsf2d.Form() == gp_Identity; -// } else if ((ax3d = l->as()) != 0) { -// gp_Trsf trsf; -// convert(ax3d, trsf); -// return trsf.Form() == gp_Identity; -// } else { -// throw IfcParse::IfcException("Invalid valuation for IfcAxis2Placement / IfcCartesianTransformationOperator"); -// } -// } -// -// void IfcGeom::Kernel::set_conversion_placement_rel_to_type(const IfcParse::declaration* type) { -// placement_rel_to_type_ = type; -// } -// -// void IfcGeom::Kernel::set_conversion_placement_rel_to_instance(const IfcUtil::IfcBaseEntity* instance) { -// placement_rel_to_instance_ = instance; -// } -// -// -// namespace { -// -// bool process_colour(IfcSchema::IfcColourRgb* colour, double* rgb) { -// if (colour != 0) { -// rgb[0] = colour->Red(); -// rgb[1] = colour->Green(); -// rgb[2] = colour->Blue(); -// } -// return colour != 0; -// } -// -// bool process_colour(IfcSchema::IfcNormalisedRatioMeasure* factor, double* rgb) { -// if (factor != 0) { -// const double f = *factor; -// rgb[0] = rgb[1] = rgb[2] = f; -// } -// return factor != 0; -// } -// -// bool process_colour(IfcSchema::IfcColourOrFactor* colour_or_factor, double* rgb) { -// if (colour_or_factor == 0) { -// return false; -// } else if (colour_or_factor->declaration().is(IfcSchema::IfcColourRgb::Class())) { -// return process_colour(static_cast(colour_or_factor), rgb); -// } else if (colour_or_factor->declaration().is(IfcSchema::IfcNormalisedRatioMeasure::Class())) { -// return process_colour(static_cast(colour_or_factor), rgb); -// } else { -// return false; -// } -// } -// -// } -// -// #define Kernel POSTFIX_SCHEMA(Kernel) -// -// std::shared_ptr IfcGeom::Kernel::internalize_surface_style(const std::pair& shading_styles) { -// if (shading_styles.second == 0) { -// return 0; -// } -// int surface_style_id = shading_styles.first->data().id(); -// auto it = style_cache.find(surface_style_id); -// if (it != style_cache.end()) { -// return it->second; -// } -// -// -// IfcSchema::IfcSurfaceStyle* style = shading_styles.first->as(); -// IfcSchema::IfcSurfaceStyleShading* shading = shading_styles.second->as(); -// -// std::shared_ptr surface_style_ptr; -// -// if (style->Name()) { -// surface_style_ptr.reset(new SurfaceStyle(surface_style_id, *style->Name())); -// } else { -// surface_style_ptr.reset(new SurfaceStyle(surface_style_id)); -// } -// -// std::shared_ptr surface_style_ptr_const = std::const_pointer_cast(surface_style_ptr); -// SurfaceStyle& surface_style = *surface_style_ptr; -// -// double rgb[3]; -// if (process_colour(shading->SurfaceColour(), rgb)) { -// surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); -// } -// if (shading_styles.second->declaration().is(IfcSchema::IfcSurfaceStyleRendering::Class())) { -// IfcSchema::IfcSurfaceStyleRendering* rendering_style = static_cast(shading_styles.second); -// if (rendering_style->DiffuseColour() && process_colour(rendering_style->DiffuseColour(), rgb)) { -// SurfaceStyle::ColorComponent diffuse = surface_style.Diffuse().get_value_or(SurfaceStyle::ColorComponent(1, 1, 1)); -// surface_style.Diffuse().reset(SurfaceStyle::ColorComponent(diffuse.R() * rgb[0], diffuse.G() * rgb[1], diffuse.B() * rgb[2])); -// } -// if (rendering_style->DiffuseTransmissionColour()) { -// // Not supported -// } -// if (rendering_style->ReflectionColour()) { -// // Not supported -// } -// if (rendering_style->SpecularColour() && process_colour(rendering_style->SpecularColour(), rgb)) { -// surface_style.Specular().reset(SurfaceStyle::ColorComponent(rgb[0], rgb[1], rgb[2])); -// } -// if (rendering_style->SpecularHighlight()) { -// IfcSchema::IfcSpecularHighlightSelect* highlight = rendering_style->SpecularHighlight(); -// if (highlight->declaration().is(IfcSchema::IfcSpecularRoughness::Class())) { -// double roughness = *((IfcSchema::IfcSpecularRoughness*)highlight); -// if (roughness >= 1e-9) { -// surface_style.Specularity().reset(1.0 / roughness); -// } -// } else if (highlight->declaration().is(IfcSchema::IfcSpecularExponent::Class())) { -// surface_style.Specularity().reset(*((IfcSchema::IfcSpecularExponent*)highlight)); -// } -// } -// if (rendering_style->TransmissionColour()) { -// // Not supported -// } -// if (rendering_style->Transparency()) { -// const double d = *rendering_style->Transparency(); -// surface_style.Transparency().reset(d); -// } -// } -// return style_cache[surface_style_id] = surface_style_ptr_const; -// } -// -// std::shared_ptr IfcGeom::Kernel::get_style(const IfcSchema::IfcRepresentationptr item) { -// return internalize_surface_style(get_surface_style(item)); -// } -// -// std::shared_ptr IfcGeom::Kernel::get_style(const IfcSchema::IfcMaterial* material) { -// IfcSchema::IfcMaterialDefinitionRepresentation::list::ptr defs = material->HasRepresentation(); -// for (IfcSchema::IfcMaterialDefinitionRepresentation::list::it jt = defs->begin(); jt != defs->end(); ++jt) { -// IfcSchema::IfcRepresentation::list::ptr reps = (*jt)->Representations(); -// IfcSchema::IfcStyledItem::list::ptr styles(new IfcSchema::IfcStyledItem::list); -// for (IfcSchema::IfcRepresentation::list::it it = reps->begin(); it != reps->end(); ++it) { -// styles->push((**it).Items()->as()); -// } -// for (IfcSchema::IfcStyledItem::list::it it = styles->begin(); it != styles->end(); ++it) { -// const std::pair ss = get_surface_style(*it); -// if (ss.second) { -// return internalize_surface_style(ss); -// } -// } -// } -// auto material_style = std::make_shared(material->data().id(), material->Name()); -// return style_cache[material->data().id()] = material_style; -// } -// -// void IfcGeom::Kernel::apply_layerset(IfcGeom::ConversionResults& r, const ifcopenshell::geometry::layerset_information& info) { -// convert(info.layers); -// -// if (info.layers.empty()) { -// return; -// } -// -// if (axis_curve->DynamicType() == STANDARD_TYPE(Geom_Line)) { -// Handle_Geom_Line axis_line = Handle_Geom_Line::DownCast(axis_curve); -// // @todo note that this creates an offset into the wrong order, the cross product arguments should be -// // reversed. This causes some inversions later on, e.g. if(positive) { reverse(); } -// reference_surface = new Geom_Plane(axis_line->Lin().Location(), axis_line->Lin().Direction() ^ gp::DZ()); -// } else if (axis_curve->DynamicType() == STANDARD_TYPE(Geom_Circle)) { -// // @todo note that in this branch this inversion does not seem to take place. -// Handle_Geom_Circle axis_line = Handle_Geom_Circle::DownCast(axis_curve); -// reference_surface = new Geom_CylindricalSurface(axis_li->Position(), axis_line->Radius()); -// } else { -// Logger::Message(Logger::LOG_ERROR, "Unsupported underlying curve of Axis representation:", product); -// return false; -// } -// -// IfcGeom::ConversionResults r2; -// if (IfcGeom::util::apply_layerset(r, const std::vector&, ConversionResults& r2, double tol)) { -// std::swap(r, r2) -// } -// } \ No newline at end of file diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h index 61b1a2c548..add0c15a25 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h @@ -56,6 +56,21 @@ #include "../../../ifcgeom/taxonomy.h" #include "../../../ifcgeom/ConversionSettings.h" +namespace { +template +bool handle_occt_exception(Fn&& fn) { + try { + return std::forward(fn)(); + } catch (const Standard_Failure& e) { + if (e.GetMessageString() && strlen(e.GetMessageString())) { + throw std::runtime_error(e.GetMessageString()); + } else { + throw std::runtime_error("Unknown error creating geometry"); + } + } +} +} + namespace IfcGeom { class IFC_GEOMLIBRARY_API OpenCascadeKernel : public ifcopenshell::geometry::kernels::AbstractKernel { diff --git a/src/ifcgeom/kernels/opencascade/boolean_result.cpp b/src/ifcgeom/kernels/opencascade/boolean_result.cpp index 6750108a90..64b65f5f2a 100644 --- a/src/ifcgeom/kernels/opencascade/boolean_result.cpp +++ b/src/ifcgeom/kernels/opencascade/boolean_result.cpp @@ -84,6 +84,7 @@ namespace { } bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, ConversionResults& results) { + return handle_occt_exception([&]() -> bool { bool valid_result = false; bool first = true; const double tol = settings_.get().get(); @@ -196,4 +197,5 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con )); return true; + }); } diff --git a/src/ifcgeom/kernels/opencascade/extrusion.cpp b/src/ifcgeom/kernels/opencascade/extrusion.cpp index b1152a4158..631c382bf8 100644 --- a/src/ifcgeom/kernels/opencascade/extrusion.cpp +++ b/src/ifcgeom/kernels/opencascade/extrusion.cpp @@ -72,6 +72,8 @@ bool OpenCascadeKernel::convert(const taxonomy::extrusion::ptr extrusion, TopoDS } bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Shape shape; if (!convert(extrusion, shape)) { return false; @@ -84,4 +86,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::extrusion::ptr extrusion, I extrusion->surface_style )); return true; + + }); } diff --git a/src/ifcgeom/kernels/opencascade/face.cpp b/src/ifcgeom/kernels/opencascade/face.cpp index b2313487c1..661b725c1d 100644 --- a/src/ifcgeom/kernels/opencascade/face.cpp +++ b/src/ifcgeom/kernels/opencascade/face.cpp @@ -599,6 +599,8 @@ bool OpenCascadeKernel::convert(const taxonomy::face::ptr face, TopoDS_Shape& re } bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Shape shape; if (!convert(face, shape)) { return false; @@ -609,4 +611,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::face::ptr face, IfcGeom::Co face->surface_style )); return true; + + }); } diff --git a/src/ifcgeom/kernels/opencascade/loft.cpp b/src/ifcgeom/kernels/opencascade/loft.cpp index b055b7743b..719e089278 100644 --- a/src/ifcgeom/kernels/opencascade/loft.cpp +++ b/src/ifcgeom/kernels/opencascade/loft.cpp @@ -427,6 +427,8 @@ bool OpenCascadeKernel::convert(const taxonomy::loft::ptr loft, TopoDS_Shape& re } bool OpenCascadeKernel::convert_impl(const taxonomy::loft::ptr loft, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Shape shape; if (!convert(loft, shape)) { return false; @@ -438,4 +440,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::loft::ptr loft, IfcGeom::Co loft->surface_style )); return true; + + }); } diff --git a/src/ifcgeom/kernels/opencascade/loop.cpp b/src/ifcgeom/kernels/opencascade/loop.cpp index 581cbf8567..5d8a538716 100644 --- a/src/ifcgeom/kernels/opencascade/loop.cpp +++ b/src/ifcgeom/kernels/opencascade/loop.cpp @@ -378,6 +378,8 @@ bool OpenCascadeKernel::convert(const taxonomy::loop::ptr loop, TopoDS_Wire& wir } bool OpenCascadeKernel::convert_impl(const taxonomy::loop::ptr loop, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Wire shape; if (!convert(loop, shape)) { return false; @@ -389,9 +391,13 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::loop::ptr loop, IfcGeom::Co loop->surface_style )); return true; + + }); } bool OpenCascadeKernel::convert_impl(const taxonomy::edge::ptr edge, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Wire shape = boost::get(convert_curve(edge)); results.emplace_back(ConversionResult( @@ -400,4 +406,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::edge::ptr edge, IfcGeom::Co edge->surface_style )); return true; + + }); } diff --git a/src/ifcgeom/kernels/opencascade/shell.cpp b/src/ifcgeom/kernels/opencascade/shell.cpp index eacc87e12b..4456895b12 100644 --- a/src/ifcgeom/kernels/opencascade/shell.cpp +++ b/src/ifcgeom/kernels/opencascade/shell.cpp @@ -107,6 +107,8 @@ bool OpenCascadeKernel::convert(const taxonomy::shell::ptr l, TopoDS_Shape& shap } bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Shape shape; if (!convert(shell, shape)) { return false; @@ -118,4 +120,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::shell::ptr shell, IfcGeom:: shell->surface_style )); return true; + + }); } diff --git a/src/ifcgeom/kernels/opencascade/solid.cpp b/src/ifcgeom/kernels/opencascade/solid.cpp index 4f308b0b06..fb38c29789 100644 --- a/src/ifcgeom/kernels/opencascade/solid.cpp +++ b/src/ifcgeom/kernels/opencascade/solid.cpp @@ -102,6 +102,8 @@ bool OpenCascadeKernel::convert(const taxonomy::solid::ptr solid, TopoDS_Shape& } bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Shape shape; if (!convert(solid, shape)) { return false; @@ -113,4 +115,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::solid::ptr solid, IfcGeom:: solid->surface_style )); return true; + + }); } diff --git a/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp b/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp index c971291868..510c8f182d 100644 --- a/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp +++ b/src/ifcgeom/kernels/opencascade/sweep_along_curve.cpp @@ -308,6 +308,8 @@ bool OpenCascadeKernel::convert(const taxonomy::sweep_along_curve::ptr scs, Topo } bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, IfcGeom::ConversionResults& results) { + return handle_occt_exception([&]() -> bool { + TopoDS_Shape shape; // For tiny radii occt will fail building the sweep, in which case we enlarge the inputs to occt, and add a scale matrix to the output bool enlarged = false; @@ -352,4 +354,6 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::sweep_along_curve::ptr scs, scs->surface_style )); return true; + + }); }