@@ -179,12 +179,14 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
179179 ? BRepBuilderAPI_GTransform (opening_shape_unlocated,opening_shape_gtrsf,true ).Shape ()
180180 : opening_shape_unlocated.Moved (opening_shape_gtrsf.Trsf ());
181181
182- const double opening_volume = shape_volume (opening_shape);
183- if ( opening_volume <= ALMOST_ZERO )
184- Ifc::LogMessage (" Warning" ," Empty opening for:" ,entity->entity );
185-
186- const double original_shape_volume = shape_volume (entity_shape);
187-
182+ double opening_volume, original_shape_volume;
183+ if ( Ifc::Verbosity > 1 ) {
184+ opening_volume = shape_volume (opening_shape);
185+ if ( opening_volume <= ALMOST_ZERO )
186+ Ifc::LogMessage (" Warning" ," Empty opening for:" ,entity->entity );
187+ original_shape_volume = shape_volume (entity_shape);
188+ }
189+
188190 BRepAlgoAPI_Cut brep_cut (entity_shape,opening_shape);
189191
190192 if ( brep_cut.IsDone () ) {
@@ -194,11 +196,12 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
194196 bool is_valid = analyser.IsValid () != 0 ;
195197 if ( is_valid ) {
196198 entity_shape = brep_cut;
197- const double volume_after_subtraction = shape_volume (entity_shape);
199+ if ( Ifc::Verbosity > 1 ) {
200+ const double volume_after_subtraction = shape_volume (entity_shape);
198201
199- if ( ALMOST_THE_SAME (original_shape_volume,volume_after_subtraction) )
200- Ifc::LogMessage (" Warning" ," Subtraction yields unchanged volume:" ,entity->entity );
201-
202+ if ( ALMOST_THE_SAME (original_shape_volume,volume_after_subtraction) )
203+ Ifc::LogMessage (" Warning" ," Subtraction yields unchanged volume:" ,entity->entity );
204+ }
202205 } else {
203206 Ifc::LogMessage (" Error" ," Invalid result from subtraction:" ,entity->entity );
204207 }
@@ -217,6 +220,87 @@ bool IfcGeom::convert_openings(const Ifc2x3::IfcProduct::ptr entity, const Ifc2x
217220
218221 return true ;
219222}
223+
224+ bool IfcGeom::convert_openings_fast (const Ifc2x3::IfcProduct::ptr entity, const Ifc2x3::IfcRelVoidsElement::list& openings,
225+ const ShapeList& entity_shapes, const gp_Trsf& entity_trsf, ShapeList& cut_shapes) {
226+
227+ // Create a compound of all opening shapes in order to speed up the boolean operations
228+ TopoDS_Compound opening_compound;
229+ BRep_Builder builder;
230+ builder.MakeCompound (opening_compound);
231+
232+ for ( Ifc2x3::IfcRelVoidsElement::it it = openings->begin (); it != openings->end (); ++ it ) {
233+ Ifc2x3::IfcRelVoidsElement::ptr v = *it;
234+ Ifc2x3::IfcFeatureElementSubtraction::ptr fes = v->RelatedOpeningElement ();
235+ if ( fes->is (Ifc2x3::Type::IfcOpeningElement) ) {
236+
237+ // Convert the IfcRepresentation of the IfcOpeningElement
238+ gp_Trsf opening_trsf;
239+ IfcGeom::convert (fes->ObjectPlacement (),opening_trsf);
240+
241+ // Move the opening into the coordinate system of the IfcProduct
242+ opening_trsf.PreMultiply (entity_trsf.Inverted ());
243+
244+ Ifc2x3::IfcProductRepresentation::ptr prodrep = fes->Representation ();
245+ Ifc2x3::IfcRepresentation::list reps = prodrep->Representations ();
246+
247+ IfcGeom::ShapeList opening_shapes;
248+
249+ for ( Ifc2x3::IfcRepresentation::it it2 = reps->begin (); it2 != reps->end (); ++ it2 ) {
250+ IfcGeom::convert_shapes (*it2,opening_shapes);
251+ }
252+
253+ for ( unsigned int i = 0 ; i < opening_shapes.size (); ++ i ) {
254+ gp_GTrsf& gtrsf = *opening_shapes[i].first ;
255+ gtrsf.PreMultiply (opening_trsf);
256+ const TopoDS_Shape& opening_shape = gtrsf.Form () == gp_Other
257+ ? BRepBuilderAPI_GTransform (*opening_shapes[i].second ,gtrsf,true ).Shape ()
258+ : (*opening_shapes[i].second ).Moved (gtrsf.Trsf ());
259+ builder.Add (opening_compound,opening_shape);
260+ }
261+
262+ for ( IfcGeom::ShapeList::const_iterator it5 = opening_shapes.begin (); it5 != opening_shapes.end (); ++ it5 ) {
263+ delete it5->first ;
264+ }
265+ }
266+ }
267+
268+ // Iterate over the shapes of the IfcProduct
269+ for ( IfcGeom::ShapeList::const_iterator it3 = entity_shapes.begin (); it3 != entity_shapes.end (); ++ it3 ) {
270+ TopoDS_Shape entity_shape_solid;
271+ const TopoDS_Shape& entity_shape_unlocated = IfcGeom::ensure_fit_for_subtraction (*(it3->second ),entity_shape_solid);
272+ const gp_GTrsf& entity_shape_gtrsf = *(it3->first );
273+ TopoDS_Shape entity_shape;
274+ if ( entity_shape_gtrsf.Form () == gp_Other ) {
275+ Ifc::LogMessage (" Warning" ," Applying non uniform transformation to:" ,entity->entity );
276+ entity_shape = BRepBuilderAPI_GTransform (entity_shape_unlocated,entity_shape_gtrsf,true ).Shape ();
277+ } else {
278+ entity_shape = entity_shape_unlocated.Moved (entity_shape_gtrsf.Trsf ());
279+ }
280+
281+ BRepAlgoAPI_Cut brep_cut (entity_shape,opening_compound);
282+ bool is_valid = false ;
283+ if ( brep_cut.IsDone () ) {
284+ TopoDS_Shape brep_cut_result = brep_cut;
285+
286+ BRepCheck_Analyzer analyser (brep_cut_result);
287+ is_valid = analyser.IsValid () != 0 ;
288+ if ( is_valid ) {
289+ cut_shapes.push_back (IfcGeom::LocationShape (new gp_GTrsf (),new TopoDS_Shape (brep_cut_result)));
290+ }
291+ }
292+ if ( !is_valid ) {
293+ // Apparently processing the boolean operation failed or resulted in an invalid result
294+ // in which case the original shape without the subtractions is returned instead
295+ // we try convert the openings in the original way, one by one.
296+ Ifc::LogMessage (" Warning" ," Subtracting combined openings compound failed:" ,entity->entity );
297+ return false ;
298+ }
299+
300+ }
301+ return true ;
302+ }
303+
220304bool IfcGeom::convert_wire_to_face (const TopoDS_Wire& wire, TopoDS_Face& face) {
221305 BRepBuilderAPI_MakeFace mf (wire, false );
222306 BRepBuilderAPI_FaceError er = mf.Error ();
0 commit comments