mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 10:32:42 +00:00
Use multiple argument boolean operands for IfcOpeningElement subtractions
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
#include "../ifcconvert/SvgSerializer.h"
|
#include "../ifcconvert/SvgSerializer.h"
|
||||||
|
|
||||||
#include <IGESControl_Controller.hxx>
|
#include <IGESControl_Controller.hxx>
|
||||||
|
#include <Standard_Version.hxx>
|
||||||
|
|
||||||
static std::string DEFAULT_EXTENSION = "obj";
|
static std::string DEFAULT_EXTENSION = "obj";
|
||||||
|
|
||||||
@@ -123,11 +124,17 @@ int main(int argc, char** argv) {
|
|||||||
"This is a potentially time consuming operation, but guarantees a "
|
"This is a potentially time consuming operation, but guarantees a "
|
||||||
"consistent orientation of surface normals, even if the faces are not "
|
"consistent orientation of surface normals, even if the faces are not "
|
||||||
"properly oriented in the IFC file.")
|
"properly oriented in the IFC file.")
|
||||||
|
#if OCC_VERSION_HEX < 0x60900
|
||||||
|
// In Open CASCADE version prior to 6.9.0 boolean operations with multiple
|
||||||
|
// arguments where not introduced yet and a work-around was implemented to
|
||||||
|
// subtract multiple openings as a single compound. This hack is obsolete
|
||||||
|
// for newer versions of Open CASCADE.
|
||||||
("merge-boolean-operands",
|
("merge-boolean-operands",
|
||||||
"Specifies whether to merge all IfcOpeningElement operands into a single "
|
"Specifies whether to merge all IfcOpeningElement operands into a single "
|
||||||
"operand before applying the subtraction operation. This may "
|
"operand before applying the subtraction operation. This may "
|
||||||
"introduce a performance improvement at the risk of failing, in "
|
"introduce a performance improvement at the risk of failing, in "
|
||||||
"which case the subtraction is applied one-by-one.")
|
"which case the subtraction is applied one-by-one.")
|
||||||
|
#endif
|
||||||
("disable-opening-subtractions",
|
("disable-opening-subtractions",
|
||||||
"Specifies whether to disable the boolean subtraction of "
|
"Specifies whether to disable the boolean subtraction of "
|
||||||
"IfcOpeningElement Representations from their RelatingElements.")
|
"IfcOpeningElement Representations from their RelatingElements.")
|
||||||
@@ -179,7 +186,9 @@ int main(int argc, char** argv) {
|
|||||||
const bool use_world_coords = vmap.count("use-world-coords") != 0;
|
const bool use_world_coords = vmap.count("use-world-coords") != 0;
|
||||||
const bool convert_back_units = vmap.count("convert-back-units") != 0;
|
const bool convert_back_units = vmap.count("convert-back-units") != 0;
|
||||||
const bool sew_shells = vmap.count("sew-shells") != 0;
|
const bool sew_shells = vmap.count("sew-shells") != 0;
|
||||||
|
#if OCC_VERSION_HEX < 0x60900
|
||||||
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
|
const bool merge_boolean_operands = vmap.count("merge-boolean-operands") != 0;
|
||||||
|
#endif
|
||||||
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
|
const bool disable_opening_subtractions = vmap.count("disable-opening-subtractions") != 0;
|
||||||
bool include_entities = vmap.count("include") != 0;
|
bool include_entities = vmap.count("include") != 0;
|
||||||
const bool include_plan = vmap.count("plan") != 0;
|
const bool include_plan = vmap.count("plan") != 0;
|
||||||
@@ -257,7 +266,9 @@ int main(int argc, char** argv) {
|
|||||||
settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, weld_vertices);
|
settings.set(IfcGeom::IteratorSettings::WELD_VERTICES, weld_vertices);
|
||||||
settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, sew_shells);
|
settings.set(IfcGeom::IteratorSettings::SEW_SHELLS, sew_shells);
|
||||||
settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units);
|
settings.set(IfcGeom::IteratorSettings::CONVERT_BACK_UNITS, convert_back_units);
|
||||||
|
#if OCC_VERSION_HEX < 0x60900
|
||||||
settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands);
|
settings.set(IfcGeom::IteratorSettings::FASTER_BOOLEANS, merge_boolean_operands);
|
||||||
|
#endif
|
||||||
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
|
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
|
||||||
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan);
|
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan);
|
||||||
settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model);
|
settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model);
|
||||||
|
|||||||
@@ -105,6 +105,10 @@
|
|||||||
#include "../ifcparse/IfcSIPrefix.h"
|
#include "../ifcparse/IfcSIPrefix.h"
|
||||||
#include "../ifcgeom/IfcGeom.h"
|
#include "../ifcgeom/IfcGeom.h"
|
||||||
|
|
||||||
|
#if OCC_VERSION_HEX < 0x60900
|
||||||
|
#pragma message("warning: You are linking against Open CASCADE version " OCC_VERSION_COMPLETE ". Version 6.9.0 introduces various improvements with relation to boolean operations. You are advised to upgrade.")
|
||||||
|
#endif
|
||||||
|
|
||||||
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
|
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
|
||||||
BRepOffsetAPI_Sewing builder;
|
BRepOffsetAPI_Sewing builder;
|
||||||
builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
|
builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
|
||||||
@@ -323,6 +327,7 @@ bool IfcGeom::Kernel::convert_openings(const IfcSchema::IfcProduct* entity, cons
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OCC_VERSION_HEX < 0x60900
|
||||||
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
||||||
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
|
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
|
||||||
|
|
||||||
@@ -382,19 +387,7 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OCC_VERSION_HEX < 0x60900
|
|
||||||
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_compound);
|
BRepAlgoAPI_Cut brep_cut(entity_shape,opening_compound);
|
||||||
#else
|
|
||||||
BRepAlgoAPI_Cut brep_cut;
|
|
||||||
TopTools_ListOfShape s1s;
|
|
||||||
s1s.Append(entity_shape);
|
|
||||||
TopTools_ListOfShape s2s;
|
|
||||||
s2s.Append(opening_compound);
|
|
||||||
brep_cut.SetFuzzyValue(getValue(GV_PRECISION));
|
|
||||||
brep_cut.SetArguments(s1s);
|
|
||||||
brep_cut.SetTools(s2s);
|
|
||||||
brep_cut.Build();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool is_valid = false;
|
bool is_valid = false;
|
||||||
if ( brep_cut.IsDone() ) {
|
if ( brep_cut.IsDone() ) {
|
||||||
@@ -417,6 +410,93 @@ bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
bool IfcGeom::Kernel::convert_openings_fast(const IfcSchema::IfcProduct* entity, const IfcSchema::IfcRelVoidsElement::list::ptr& openings,
|
||||||
|
const IfcGeom::IfcRepresentationShapeItems& entity_shapes, const gp_Trsf& entity_trsf, IfcGeom::IfcRepresentationShapeItems& cut_shapes) {
|
||||||
|
|
||||||
|
TopTools_ListOfShape opening_shapelist;
|
||||||
|
|
||||||
|
for ( IfcSchema::IfcRelVoidsElement::list::it it = openings->begin(); it != openings->end(); ++ it ) {
|
||||||
|
IfcSchema::IfcRelVoidsElement* v = *it;
|
||||||
|
IfcSchema::IfcFeatureElementSubtraction* fes = v->RelatedOpeningElement();
|
||||||
|
if ( fes->is(IfcSchema::Type::IfcOpeningElement) ) {
|
||||||
|
if (!fes->hasRepresentation()) continue;
|
||||||
|
|
||||||
|
// Convert the IfcRepresentation of the IfcOpeningElement
|
||||||
|
gp_Trsf opening_trsf;
|
||||||
|
if (fes->hasObjectPlacement()) {
|
||||||
|
try {
|
||||||
|
convert(fes->ObjectPlacement(),opening_trsf);
|
||||||
|
} catch (...) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the opening into the coordinate system of the IfcProduct
|
||||||
|
opening_trsf.PreMultiply(entity_trsf.Inverted());
|
||||||
|
|
||||||
|
IfcSchema::IfcProductRepresentation* prodrep = fes->Representation();
|
||||||
|
IfcSchema::IfcRepresentation::list::ptr reps = prodrep->Representations();
|
||||||
|
|
||||||
|
IfcGeom::IfcRepresentationShapeItems opening_shapes;
|
||||||
|
|
||||||
|
for ( IfcSchema::IfcRepresentation::list::it it2 = reps->begin(); it2 != reps->end(); ++ it2 ) {
|
||||||
|
convert_shapes(*it2,opening_shapes);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < opening_shapes.size(); ++ i ) {
|
||||||
|
gp_GTrsf gtrsf = opening_shapes[i].Placement();
|
||||||
|
gtrsf.PreMultiply(opening_trsf);
|
||||||
|
const TopoDS_Shape& opening_shape = gtrsf.Form() == gp_Other
|
||||||
|
? BRepBuilderAPI_GTransform(opening_shapes[i].Shape(),gtrsf,true).Shape()
|
||||||
|
: (opening_shapes[i].Shape()).Moved(gtrsf.Trsf());
|
||||||
|
opening_shapelist.Append(opening_shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over the shapes of the IfcProduct
|
||||||
|
for ( IfcGeom::IfcRepresentationShapeItems::const_iterator it3 = entity_shapes.begin(); it3 != entity_shapes.end(); ++ it3 ) {
|
||||||
|
TopoDS_Shape entity_shape_solid;
|
||||||
|
const TopoDS_Shape& entity_shape_unlocated = ensure_fit_for_subtraction(it3->Shape(),entity_shape_solid);
|
||||||
|
const gp_GTrsf& entity_shape_gtrsf = it3->Placement();
|
||||||
|
TopoDS_Shape entity_shape;
|
||||||
|
if ( entity_shape_gtrsf.Form() == gp_Other ) {
|
||||||
|
Logger::Message(Logger::LOG_WARNING,"Applying non uniform transformation to:",entity->entity);
|
||||||
|
entity_shape = BRepBuilderAPI_GTransform(entity_shape_unlocated,entity_shape_gtrsf,true).Shape();
|
||||||
|
} else {
|
||||||
|
entity_shape = entity_shape_unlocated.Moved(entity_shape_gtrsf.Trsf());
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepAlgoAPI_Cut brep_cut;
|
||||||
|
TopTools_ListOfShape s1s;
|
||||||
|
s1s.Append(entity_shape);
|
||||||
|
brep_cut.SetFuzzyValue(getValue(GV_PRECISION));
|
||||||
|
brep_cut.SetArguments(s1s);
|
||||||
|
brep_cut.SetTools(opening_shapelist);
|
||||||
|
brep_cut.Build();
|
||||||
|
|
||||||
|
bool is_valid = false;
|
||||||
|
if ( brep_cut.IsDone() ) {
|
||||||
|
TopoDS_Shape brep_cut_result = brep_cut;
|
||||||
|
|
||||||
|
BRepCheck_Analyzer analyser(brep_cut_result);
|
||||||
|
is_valid = analyser.IsValid() != 0;
|
||||||
|
if ( is_valid ) {
|
||||||
|
cut_shapes.push_back(IfcGeom::IfcRepresentationShapeItem(brep_cut_result, &it3->Style()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !is_valid ) {
|
||||||
|
// Apparently processing the boolean operation failed or resulted in an invalid result
|
||||||
|
// in which case the original shape without the subtractions is returned instead
|
||||||
|
// we try convert the openings in the original way, one by one.
|
||||||
|
Logger::Message(Logger::LOG_WARNING, "Subtracting combined openings compound failed:", entity->entity);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
|
bool IfcGeom::Kernel::convert_wire_to_face(const TopoDS_Wire& wire, TopoDS_Face& face) {
|
||||||
BRepBuilderAPI_MakeFace mf(wire, false);
|
BRepBuilderAPI_MakeFace mf(wire, false);
|
||||||
@@ -919,7 +999,7 @@ void IfcGeom::Kernel::remove_collinear_points_from_loop(TColgp_SequenceOfPnt& po
|
|||||||
to_remove[i-1] = true;
|
to_remove[i-1] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = to_remove.size() - 1; i >= 0; --i) {
|
for (int i = (int) to_remove.size() - 1; i >= 0; --i) {
|
||||||
if (to_remove[i]) {
|
if (to_remove[i]) {
|
||||||
polygon.Remove(i+1);
|
polygon.Remove(i+1);
|
||||||
}
|
}
|
||||||
@@ -1020,7 +1100,12 @@ IfcGeom::BRepElement<P>* IfcGeom::Kernel::create_brep_for_representation_and_pro
|
|||||||
if ( !settings.disable_opening_subtractions() && openings && openings->size() ) {
|
if ( !settings.disable_opening_subtractions() && openings && openings->size() ) {
|
||||||
IfcGeom::IfcRepresentationShapeItems opened_shapes;
|
IfcGeom::IfcRepresentationShapeItems opened_shapes;
|
||||||
try {
|
try {
|
||||||
if ( settings.faster_booleans() ) {
|
#if OCC_VERSION_HEX < 0x60900
|
||||||
|
const bool faster_booleans = settings.faster_booleans();
|
||||||
|
#else
|
||||||
|
const bool faster_booleans = true;
|
||||||
|
#endif
|
||||||
|
if (faster_booleans) {
|
||||||
bool succes = convert_openings_fast(product,openings,shapes,trsf,opened_shapes);
|
bool succes = convert_openings_fast(product,openings,shapes,trsf,opened_shapes);
|
||||||
if ( ! succes ) {
|
if ( ! succes ) {
|
||||||
opened_shapes.clear();
|
opened_shapes.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user