22
33#include " ../ifcgeom/IfcGeomElement.h"
44#include " ../ifcgeom/ConversionSettings.h"
5+ #include " ../ifcgeom/abstract_mapping.h"
56
67#ifdef IFOPSH_WITH_OPENCASCADE
78#include " ../ifcgeom/kernels/opencascade/OpenCascadeKernel.h"
@@ -38,8 +39,109 @@ const Settings& ifcopenshell::geometry::kernels::AbstractKernel::settings() cons
3839 return settings_;
3940}
4041
41- ifcopenshell::geometry::kernels::AbstractKernel* ifcopenshell::geometry::kernels::construct (const std::string& geometry_library, const Settings& conv_settings) {
42- const std::string geometry_library_lower = boost::to_lower_copy (geometry_library);
42+
43+ bool is_valid_for_kernel (const ifcopenshell::geometry::kernels::AbstractKernel* k, const IfcGeom::ConversionResult& shp) {
44+ #ifdef IFOPSH_WITH_OPENCASCADE
45+ if (k->geometry_library () == " opencascade" ) {
46+ return dynamic_cast <ifcopenshell::geometry::OpenCascadeShape*>(shp.Shape ().get ()) != nullptr ;
47+ }
48+ #endif
49+ #ifdef IFOPSH_WITH_CGAL
50+ if (k->geometry_library () == " cgal-simple" ) {
51+ return dynamic_cast <ifcopenshell::geometry::SimpleCgalShape*>(shp.Shape ().get ()) != nullptr ;
52+ }
53+ if (k->geometry_library () == " cgal" ) {
54+ return dynamic_cast <ifcopenshell::geometry::CgalShape*>(shp.Shape ().get ()) != nullptr ;
55+ }
56+ #endif
57+ }
58+
59+ class HybridKernel : public ifcopenshell ::geometry::kernels::AbstractKernel {
60+ std::vector<AbstractKernel*> kernels_;
61+ ifcopenshell::geometry::abstract_mapping* mapping_;
62+ public:
63+ HybridKernel (const std::string& name, IfcParse::IfcFile* file, Settings& settings, std::vector<AbstractKernel*> kernels)
64+ : AbstractKernel(name, settings)
65+ , kernels_(kernels)
66+ , mapping_(ifcopenshell::geometry::impl::mapping_implementations().construct(file, settings))
67+ {}
68+ virtual bool convert (const taxonomy::ptr item, IfcGeom::ConversionResults& rs) {
69+ auto ops = mapping_->find_openings (item->instance ->as <IfcUtil::IfcBaseEntity>());
70+ bool has_openings = ops && ops->size ();
71+ for (auto & k : kernels_) {
72+ #ifdef IFOPSH_WITH_CGAL
73+ if (has_openings && dynamic_cast <ifcopenshell::geometry::kernels::SimpleCgalKernel*>(k)) {
74+ // @todo this would fail later on in the find_openings() call, because we have a
75+ // SimpleCgalShape which cannot be used on a kernel that supports booleans.
76+ // @todo 1 implement the translation between various conversion result shapes
77+ // @todo 2 fold the boolean result openings into the taxonomy item. This should be possible
78+ // now that we have shared_ptr<item> and caching in place. So the inability
79+ // to instance wouldn't matter as much.
80+ continue ;
81+ }
82+ #endif
83+ bool success = false ;
84+ try {
85+ success = k->convert (item, rs);
86+ } catch (...) {}
87+ if (success) {
88+ return true ;
89+ }
90+ }
91+ return false ;
92+ }
93+ virtual bool apply_layerset (IfcGeom::ConversionResults& items, const ifcopenshell::geometry::layerset_information& layers) {
94+ for (auto & k : kernels_) {
95+ bool success = false ;
96+ try {
97+ success = k->apply_layerset (items, layers);
98+ } catch (...) {}
99+ if (success) {
100+ return true ;
101+ }
102+ }
103+ return false ;
104+ }
105+ virtual bool apply_folded_layerset (IfcGeom::ConversionResults& items, const ifcopenshell::geometry::layerset_information& layers, const std::map<IfcUtil::IfcBaseEntity*, ifcopenshell::geometry::layerset_information>& folds) {
106+ for (auto & k : kernels_) {
107+ bool success = false ;
108+ try {
109+ success = k->apply_folded_layerset (items, layers, folds);
110+ } catch (...) {}
111+ if (success) {
112+ return true ;
113+ }
114+ }
115+ return false ;
116+ }
117+ virtual bool convert_openings (const IfcUtil::IfcBaseEntity* entity, const std::vector<std::pair<taxonomy::ptr, ifcopenshell::geometry::taxonomy::matrix4>>& openings,
118+ const IfcGeom::ConversionResults& entity_shapes, const ifcopenshell::geometry::taxonomy::matrix4& entity_trsf, IfcGeom::ConversionResults& cut_shapes)
119+ {
120+ for (auto & k : kernels_) {
121+ bool is_valid = true ;
122+ for (auto & s : entity_shapes) {
123+ if (!is_valid_for_kernel (k, s)) {
124+ is_valid = false ;
125+ break ;
126+ }
127+ }
128+ if (!is_valid) {
129+ continue ;
130+ }
131+ bool success = false ;
132+ try {
133+ success = k->convert_openings (entity, openings, entity_shapes, entity_trsf, cut_shapes);
134+ } catch (...) {}
135+ if (success) {
136+ return true ;
137+ }
138+ }
139+ return false ;
140+ }
141+ };
142+
143+ ifcopenshell::geometry::kernels::AbstractKernel* ifcopenshell::geometry::kernels::construct (IfcParse::IfcFile* file, const std::string& geometry_library, Settings& conv_settings) {
144+ std::string geometry_library_lower = boost::to_lower_copy (geometry_library);
43145
44146#ifdef IFOPSH_WITH_OPENCASCADE
45147 if (geometry_library_lower == " opencascade" ) {
@@ -56,6 +158,44 @@ ifcopenshell::geometry::kernels::AbstractKernel* ifcopenshell::geometry::kernels
56158 return new SimpleCgalKernel (conv_settings);
57159 }
58160#endif
161+
162+ if (geometry_library_lower.rfind (" hybrid-" , 0 ) == 0 ) {
163+ geometry_library_lower = geometry_library_lower.substr (strlen (" hybrid" ));
164+ std::vector<AbstractKernel*> kernels;
165+ while (!geometry_library_lower.empty ()) {
166+ if (geometry_library_lower.find (" -" , 0 ) == 0 ) {
167+ geometry_library_lower = geometry_library_lower.substr (strlen (" -" ));
168+ } else {
169+ throw IfcParse::IfcException (" Invalid hybrid kernel " + geometry_library);
170+ }
171+ auto n = kernels.size ();
172+ #ifdef IFOPSH_WITH_OPENCASCADE
173+ if (geometry_library_lower.find (" opencascade" , 0 ) == 0 ) {
174+ kernels.push_back (new IfcGeom::OpenCascadeKernel (conv_settings));
175+ geometry_library_lower = geometry_library_lower.substr (strlen (" opencascade" ));
176+ }
177+ #endif
178+
179+ #ifdef IFOPSH_WITH_CGAL
180+ if (geometry_library_lower.find (" cgal-simple" , 0 ) == 0 ) {
181+ kernels.push_back (new SimpleCgalKernel (conv_settings));
182+ geometry_library_lower = geometry_library_lower.substr (strlen (" cgal-simple" ));
183+ }
184+
185+ if (geometry_library_lower.find (" cgal" , 0 ) == 0 ) {
186+ kernels.push_back (new CgalKernel (conv_settings));
187+ geometry_library_lower = geometry_library_lower.substr (strlen (" cgal" ));
188+ }
189+ #endif
190+ if (kernels.size () != n + 1 ) {
191+ throw IfcParse::IfcException (" Invalid hybrid kernel " + geometry_library);
192+ }
193+ }
194+
195+ if (!kernels.empty ()) {
196+ return new HybridKernel (geometry_library, file, conv_settings, kernels);
197+ }
198+ }
59199
60200 throw IfcParse::IfcException (" No geometry kernel registered for " + geometry_library);
61201}
0 commit comments