Fix boolean results on non-solid shells #4832

This commit is contained in:
Thomas Krijnen
2024-06-18 21:30:00 +02:00
parent 0e42130e9d
commit a3d4642ea9
7 changed files with 17 additions and 19 deletions
@@ -248,9 +248,8 @@ bool IfcGeom::OpenCascadeKernel::convert_openings(const IfcUtil::IfcBaseEntity*
AbstractKernel::convert(op.first, opening_shapes); AbstractKernel::convert(op.first, opening_shapes);
for (unsigned int i = 0; i < opening_shapes.size(); ++i) { for (unsigned int i = 0; i < opening_shapes.size(); ++i) {
TopoDS_Shape opening_shape_solid;
auto opening_shape_i = std::static_pointer_cast<OpenCascadeShape>(opening_shapes[i].Shape())->shape(); auto opening_shape_i = std::static_pointer_cast<OpenCascadeShape>(opening_shapes[i].Shape())->shape();
const TopoDS_Shape& opening_shape_unlocated = util::ensure_fit_for_subtraction(opening_shape_i, opening_shape_solid, settings_.get<settings::Precision>().get()); const TopoDS_Shape& opening_shape_unlocated = util::ensure_fit_for_subtraction(opening_shape_i, settings_.get<settings::Precision>().get());
auto gtrsf = opening_shapes[i].Placement(); auto gtrsf = opening_shapes[i].Placement();
// @todo check // @todo check
@@ -306,13 +305,11 @@ bool IfcGeom::OpenCascadeKernel::convert_openings(const IfcUtil::IfcBaseEntity*
TopoDS_Shape entity_part_result; TopoDS_Shape entity_part_result;
for (int as_shell = 0; as_shell < 2; ++as_shell) { for (int as_shell = 0; as_shell < 2; ++as_shell) {
TopoDS_Shape entity_shape_solid;
TopoDS_Shape entity_shape_unlocated; TopoDS_Shape entity_shape_unlocated;
if (as_shell) { if (as_shell) {
entity_shape_unlocated = entity_part; entity_shape_unlocated = entity_part;
} else { } else {
entity_shape_unlocated = util::ensure_fit_for_subtraction(entity_part, entity_shape_solid, settings_.get<settings::Precision>().get()); entity_shape_unlocated = util::ensure_fit_for_subtraction(entity_part, settings_.get<settings::Precision>().get());
} }
const auto& m = it3->Placement()->ccomponents(); const auto& m = it3->Placement()->ccomponents();
// @todo // @todo
@@ -762,7 +762,7 @@ bool IfcGeom::util::create_solid_from_faces(const TopTools_ListOfShape& face_lis
return valid_shell; return valid_shell;
} }
bool IfcGeom::util::flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse, double tol) { bool IfcGeom::util::flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse, bool create_shell, double tol) {
TopoDS_Compound compound; TopoDS_Compound compound;
BRep_Builder builder; BRep_Builder builder;
builder.MakeCompound(compound); builder.MakeCompound(compound);
@@ -772,8 +772,8 @@ bool IfcGeom::util::flatten_shape_list(const IfcGeom::ConversionResults& shapes,
for (IfcGeom::ConversionResults::const_iterator it = shapes.begin(); it != shapes.end(); ++it) { for (IfcGeom::ConversionResults::const_iterator it = shapes.begin(); it != shapes.end(); ++it) {
TopoDS_Shape merged; TopoDS_Shape merged;
const TopoDS_Shape& s = std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape())->shape(); const TopoDS_Shape& s = std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape())->shape();
if (fuse) { if (fuse || create_shell) {
util::ensure_fit_for_subtraction(s, merged, tol); merged = util::ensure_fit_for_subtraction(s, tol);
} else { } else {
merged = s; merged = s;
} }
+1 -1
View File
@@ -73,7 +73,7 @@ namespace IfcGeom {
TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&); TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&);
TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&); TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&);
bool flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse, double tol); bool flatten_shape_list(const IfcGeom::ConversionResults& shapes, TopoDS_Shape& result, bool fuse, bool create_shell, double tol);
bool validate_shape(const TopoDS_Shape&); bool validate_shape(const TopoDS_Shape&);
} }
} }
@@ -98,7 +98,7 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
AbstractKernel::convert(c, cr); AbstractKernel::convert(c, cr);
if (first && br->operation == taxonomy::boolean_result::SUBTRACTION) { if (first && br->operation == taxonomy::boolean_result::SUBTRACTION) {
// @todo A will be null on union/intersection, intended? // @todo A will be null on union/intersection, intended?
IfcGeom::util::flatten_shape_list(cr, a, false, settings_.get<settings::Precision>().get()); IfcGeom::util::flatten_shape_list(cr, a, false, true, settings_.get<settings::Precision>().get());
first_item_style = c->surface_style; first_item_style = c->surface_style;
if (!first_item_style && c->kind() == taxonomy::COLLECTION) { if (!first_item_style && c->kind() == taxonomy::COLLECTION) {
// @todo recursively right? // @todo recursively right?
@@ -144,6 +144,8 @@ bool OpenCascadeKernel::convert_impl(const taxonomy::boolean_result::ptr br, Con
} else { } else {
S = result; S = result;
} }
} else {
S = util::ensure_fit_for_subtraction(S, tol);
} }
b.Append(S); b.Append(S);
@@ -1430,14 +1430,15 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To
return boolean_operation(settings, a, bs, op, result, fuzziness); return boolean_operation(settings, a, bs, op, result, fuzziness);
} }
const TopoDS_Shape& IfcGeom::util::ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid, double tol) { TopoDS_Shape IfcGeom::util::ensure_fit_for_subtraction(const TopoDS_Shape& shape, double tol) {
const bool is_comp = is_compound(shape); const bool is_comp = is_compound(shape);
if (!is_comp) { if (!is_comp) {
return solid = shape; return shape;
} }
TopoDS_Solid solid;
if (!create_solid_from_compound(shape, solid, tol)) { if (!create_solid_from_compound(shape, solid, tol)) {
return solid = shape; return shape;
} }
return solid; return solid;
@@ -96,7 +96,7 @@ namespace IfcGeom {
bool boolean_operation(const boolean_settings& settings, const TopoDS_Shape&, const TopoDS_Shape&, BOPAlgo_Operation, TopoDS_Shape&, double fuzziness = -1.); bool boolean_operation(const boolean_settings& settings, const TopoDS_Shape&, const TopoDS_Shape&, BOPAlgo_Operation, TopoDS_Shape&, double fuzziness = -1.);
const TopoDS_Shape& ensure_fit_for_subtraction(const TopoDS_Shape& shape, TopoDS_Shape& solid, double tol); TopoDS_Shape ensure_fit_for_subtraction(const TopoDS_Shape& shape, double tol);
} }
} }
+3 -5
View File
@@ -167,7 +167,7 @@ namespace {
bool IfcGeom::util::apply_folded_layerset(const ConversionResults& items, const std::vector< std::vector<Handle_Geom_Surface> >& surfaces, const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& styles, ConversionResults& result, double tol) { bool IfcGeom::util::apply_folded_layerset(const ConversionResults& items, const std::vector< std::vector<Handle_Geom_Surface> >& surfaces, const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& styles, ConversionResults& result, double tol) {
Bnd_Box bb; Bnd_Box bb;
TopoDS_Shape input; TopoDS_Shape input;
flatten_shape_list(items, input, false, tol); flatten_shape_list(items, input, false, false, tol);
typedef std::vector< std::vector<Handle_Geom_Surface> > folded_surfaces_t; typedef std::vector< std::vector<Handle_Geom_Surface> > folded_surfaces_t;
typedef std::vector< std::pair< TopoDS_Face, std::pair<gp_Pnt, gp_Pnt> > > faces_with_mass_t; typedef std::vector< std::pair< TopoDS_Face, std::pair<gp_Pnt, gp_Pnt> > > faces_with_mass_t;
@@ -263,8 +263,7 @@ bool IfcGeom::util::apply_folded_layerset(const ConversionResults& items, const
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
const TopoDS_Shape& s = std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape(); const TopoDS_Shape& s = std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape();
TopoDS_Solid sld; TopoDS_Shape sld = ensure_fit_for_subtraction(s, tol);
ensure_fit_for_subtraction(s, sld, tol);
std::vector<TopoDS_Shape> slices; std::vector<TopoDS_Shape> slices;
if (split(s, shells, tol, slices) && slices.size() == styles.size()) { if (split(s, shells, tol, slices) && slices.size() == styles.size()) {
@@ -335,8 +334,7 @@ bool IfcGeom::util::apply_layerset(const ConversionResults& items, const std::ve
for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) { for (ConversionResults::const_iterator it = items.begin(); it != items.end(); ++it) {
const TopoDS_Shape& s = std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape(); const TopoDS_Shape& s = std::static_pointer_cast<OpenCascadeShape>(it->Shape())->shape();
TopoDS_Solid sld; TopoDS_Shape sld = ensure_fit_for_subtraction(s, tol);
ensure_fit_for_subtraction(s, sld, tol);
TopTools_ListOfShape operands; TopTools_ListOfShape operands;
for (unsigned i = 1; i < surfaces.size() - 1; ++i) { for (unsigned i = 1; i < surfaces.size() - 1; ++i) {