diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 7ec5adb9f2..43b25669a2 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -282,6 +282,7 @@ namespace IfcGeom { virtual ConversionResultShape* halfspaces() = 0; virtual ConversionResultShape* box() = 0; virtual ConversionResultShape* solid() = 0; + virtual ConversionResultShape* wrap_in_compound() = 0; virtual std::vector vertices() = 0; virtual std::vector edges() = 0; diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp index 9ca210f6e6..48346b2831 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -68,7 +68,7 @@ IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::as_compound(bool delete accum; accum = n; } else { - accum = s; + accum = s->wrap_in_compound(); } } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 76c4219ae0..3119ad9b5d 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -610,6 +610,11 @@ ConversionResultShape * ifcopenshell::geometry::CgalShape::box() throw std::runtime_error("Not implemented"); } +ConversionResultShape* ifcopenshell::geometry::CgalShape::wrap_in_compound() +{ + return new CgalShape(poly(), convex_tag_); +} + std::vector ifcopenshell::geometry::CgalShape::vertices() { // @todo this is ridiculous @@ -1001,4 +1006,10 @@ void ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const std::vec shape_ = std::move(nw); } + +ConversionResultShape* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::wrap_in_compound() +{ + throw std::runtime_error("Not implemented"); +} + #endif \ No newline at end of file diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index e5fa0cabe5..f0fb6c224c 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -244,6 +244,7 @@ namespace ifcopenshell { namespace geometry { virtual ConversionResultShape* halfspaces(); virtual ConversionResultShape* solid(); virtual ConversionResultShape* box(); + virtual ConversionResultShape* wrap_in_compound(); virtual std::vector vertices(); virtual std::vector edges(); @@ -312,6 +313,7 @@ namespace ifcopenshell { namespace geometry { virtual ConversionResultShape* halfspaces(); virtual ConversionResultShape* solid(); virtual ConversionResultShape* box(); + virtual ConversionResultShape* wrap_in_compound(); virtual std::vector vertices(); virtual std::vector edges(); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp index 72f663b3ec..560c1a29fa 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp @@ -484,6 +484,15 @@ ConversionResultShape * ifcopenshell::geometry::OpenCascadeShape::box() throw std::runtime_error("Not implemented"); } +ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::wrap_in_compound() +{ + TopoDS_Compound compound; + BRep_Builder builder; + builder.MakeCompound(compound); + builder.Add(compound, shape_); + return new OpenCascadeShape(std::move(compound)); +} + std::vector ifcopenshell::geometry::OpenCascadeShape::vertices() { TopTools_IndexedMapOfShape map; @@ -556,7 +565,9 @@ ConversionResultShape* ifcopenshell::geometry::OpenCascadeShape::concat(Conversi auto& left = shape_; auto& right = ((ifcopenshell::geometry::OpenCascadeShape*)other)->shape_; - if (left.ShapeType() == TopAbs_COMPOUND) { + // This reads a bit strange, but we want to specifically avoid compounds of faces that are + // the result of shell instances that are not sewn into a shell (yet). + if (left.ShapeType() == TopAbs_COMPOUND && !IfcGeom::util::is_compound_of_faces(left)) { compound = TopoDS::Compound(left); } else { builder.MakeCompound(compound); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h index e812c207fa..f34e27bf8e 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h @@ -90,6 +90,7 @@ namespace ifcopenshell { virtual ConversionResultShape* halfspaces(); virtual ConversionResultShape* solid(); virtual ConversionResultShape* box(); + virtual ConversionResultShape* wrap_in_compound(); virtual std::vector vertices(); virtual std::vector edges(); diff --git a/src/ifcgeom/kernels/opencascade/base_utils.cpp b/src/ifcgeom/kernels/opencascade/base_utils.cpp index 273b5dd79f..5d8a07b5ab 100644 --- a/src/ifcgeom/kernels/opencascade/base_utils.cpp +++ b/src/ifcgeom/kernels/opencascade/base_utils.cpp @@ -607,7 +607,7 @@ gp_Pnt IfcGeom::util::point_above_plane(const gp_Pln& pln, bool agree) { } } -bool IfcGeom::util::is_compound(const TopoDS_Shape& shape) { +bool IfcGeom::util::is_compound_of_faces(const TopoDS_Shape& shape) { bool has_solids = TopExp_Explorer(shape, TopAbs_SOLID).More() != 0; bool has_shells = TopExp_Explorer(shape, TopAbs_SHELL).More() != 0; bool has_compounds = TopExp_Explorer(shape, TopAbs_COMPOUND).More() != 0; diff --git a/src/ifcgeom/kernels/opencascade/base_utils.h b/src/ifcgeom/kernels/opencascade/base_utils.h index bd74485ded..f8f86fafaa 100644 --- a/src/ifcgeom/kernels/opencascade/base_utils.h +++ b/src/ifcgeom/kernels/opencascade/base_utils.h @@ -51,7 +51,7 @@ namespace IfcGeom { IFC_GEOMLIBRARY_API bool create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& solid, double tol); IFC_GEOMLIBRARY_API bool shape_to_face_list(const TopoDS_Shape& s, TopTools_ListOfShape& li); IFC_GEOMLIBRARY_API bool create_solid_from_faces(const TopTools_ListOfShape& face_list, TopoDS_Shape& solid, double tol, bool force_sewing = false); - IFC_GEOMLIBRARY_API bool is_compound(const TopoDS_Shape& shape); + IFC_GEOMLIBRARY_API bool is_compound_of_faces(const TopoDS_Shape& shape); IFC_GEOMLIBRARY_API bool is_convex(const TopoDS_Wire& wire, double tol); IFC_GEOMLIBRARY_API TopoDS_Shape halfspace_from_plane(const gp_Pln& pln, const gp_Pnt& cent); IFC_GEOMLIBRARY_API gp_Pln plane_from_face(const TopoDS_Face& face); diff --git a/src/ifcgeom/kernels/opencascade/boolean_utils.cpp b/src/ifcgeom/kernels/opencascade/boolean_utils.cpp index 56f9cdf918..975ee00d0d 100644 --- a/src/ifcgeom/kernels/opencascade/boolean_utils.cpp +++ b/src/ifcgeom/kernels/opencascade/boolean_utils.cpp @@ -1431,7 +1431,7 @@ bool IfcGeom::util::boolean_operation(const boolean_settings& settings, const To } 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_of_faces(shape); if (!is_comp) { return shape; } diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index d54e33c5d5..5b7b4aba0b 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -81,6 +81,7 @@ %newobject IfcGeom::ConversionResultShape::intersect; %newobject IfcGeom::ConversionResultShape::concat; %newobject IfcGeom::ConversionResultShape::moved; +%newobject IfcGeom::ConversionResultShape::wrap_in_compound; %newobject IfcGeom::ConversionResultShape::area; %newobject IfcGeom::ConversionResultShape::volume;