From 4bb3cc5c90ccbac1925467e13088575447286ad2 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sat, 26 Aug 2023 11:35:23 +0200 Subject: [PATCH] Fix transformation in serialization element, accept geometry library in more geom functions --- src/ifcgeom/ConversionResult.h | 2 +- src/ifcgeom/IfcGeomRepresentation.cpp | 5 ++- .../kernels/cgal/CgalConversionResult.cpp | 21 +++++++++- .../kernels/cgal/CgalConversionResult.h | 2 +- .../OpenCascadeConversionResult.cpp | 6 ++- .../opencascade/OpenCascadeConversionResult.h | 2 +- .../kernels/opencascade/OpenCascadeKernel.h | 4 -- .../kernels/opencascade/base_utils.cpp | 18 ++++++++- src/ifcgeom/kernels/opencascade/base_utils.h | 2 +- src/ifcwrap/IfcGeomWrapper.i | 40 +++++++++---------- 10 files changed, 67 insertions(+), 35 deletions(-) diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 860e241056..a21f7e14a4 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -36,7 +36,7 @@ namespace IfcGeom { public: virtual void Triangulate(const IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int surface_style_id) const = 0; - virtual void Serialize(std::string&) const = 0; + virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const = 0; virtual ConversionResultShape* clone() const = 0; virtual int surface_genus() const = 0; virtual bool is_manifold() const = 0; diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp index 3be3e3bdb8..235d7f11f8 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -173,12 +173,13 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep) if (brep.begin() != brep.end()) { if (dynamic_cast(brep.begin()->Shape())) { ConversionResultShape* shape = brep.as_compound(); - shape->Serialize(brep_data_); + ifcopenshell::geometry::taxonomy::matrix4 identity; + shape->Serialize(identity, brep_data_); delete shape; } else { for (auto it = brep.begin(); it != brep.end(); ++it) { std::string part; - it->Shape()->Serialize(part); + it->Shape()->Serialize(*it->Placement(), part); if (brep_data_.size()) { brep_data_ = brep_data_ + "\n---\n" + part; } else { diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index 94f3164262..4b6fe74ed8 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -102,9 +102,26 @@ void ifcopenshell::geometry::CgalShape::Triangulate(const IfcGeom::IteratorSetti } -void ifcopenshell::geometry::CgalShape::Serialize(std::string& r) const { +void ifcopenshell::geometry::CgalShape::Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string& r) const { + cgal_shape_t s = shape_; + + if (!place.is_identity()) { + const auto& m = place.ccomponents(); + + // @todo check + const cgal_placement_t trsf( + m(0, 0), m(0, 1), m(0, 2), m(0, 3), + m(1, 0), m(1, 1), m(1, 2), m(1, 3), + m(2, 0), m(2, 1), m(2, 2), m(2, 3)); + + // Apply transformation + for (auto &vertex : vertices(s)) { + vertex->point() = vertex->point().transform(trsf); + } + } + std::stringstream sstream; - sstream << shape_; + sstream << s; r = sstream.str(); } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index 72d3927a6e..b02d259452 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -96,7 +96,7 @@ namespace ifcopenshell { namespace geometry { virtual void Triangulate(const IfcGeom::IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const; - virtual void Serialize(std::string&) const; + virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const; virtual IfcGeom::ConversionResultShape* clone() const { return new CgalShape(shape_); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp index f2a66d5838..7b3127cddf 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp @@ -2,6 +2,7 @@ #include "../../../ifcparse/IfcLogger.h" #include "../../../ifcgeom/IfcGeomRepresentation.h" +#include "base_utils.h" #include #include @@ -217,9 +218,10 @@ void ifcopenshell::geometry::OpenCascadeShape::Triangulate(const IfcGeom::Iterat BRepTools::Clean(shape_); } -void ifcopenshell::geometry::OpenCascadeShape::Serialize(std::string& r) const { +void ifcopenshell::geometry::OpenCascadeShape::Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string& r) const { + auto s = IfcGeom::util::apply_transformation(shape_, place); std::stringstream sstream; - BRepTools::Write(shape_, sstream); + BRepTools::Write(s, sstream); r = sstream.str(); } diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h index bee6e18fa5..198ae07393 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h @@ -49,7 +49,7 @@ namespace ifcopenshell { virtual void Triangulate(const IfcGeom::IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, IfcGeom::Representation::Triangulation* t, int surface_style_id) const; - virtual void Serialize(std::string&) const; + virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const; virtual IfcGeom::ConversionResultShape* clone() const { return new OpenCascadeShape(shape_); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h index db70f81b51..693ddbc991 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h @@ -138,10 +138,6 @@ public: bool convert(const taxonomy::solid::ptr, TopoDS_Shape&); bool convert(const taxonomy::bspline_surface::ptr bs, Handle(Geom_Surface) surf); - TopoDS_Shape apply_transformation(const TopoDS_Shape& s, const taxonomy::matrix4& t); - TopoDS_Shape apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t); - TopoDS_Shape apply_transformation(const TopoDS_Shape& s, const gp_Trsf& t); - virtual bool convert_impl(const taxonomy::face::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const taxonomy::solid::ptr, IfcGeom::ConversionResults&); virtual bool convert_impl(const taxonomy::shell::ptr, IfcGeom::ConversionResults&); diff --git a/src/ifcgeom/kernels/opencascade/base_utils.cpp b/src/ifcgeom/kernels/opencascade/base_utils.cpp index 37b019c722..896bee9c8c 100644 --- a/src/ifcgeom/kernels/opencascade/base_utils.cpp +++ b/src/ifcgeom/kernels/opencascade/base_utils.cpp @@ -286,15 +286,31 @@ TopoDS_Shape IfcGeom::util::apply_transformation(const TopoDS_Shape& s, const gp } } + TopoDS_Shape IfcGeom::util::apply_transformation(const TopoDS_Shape& s, const gp_GTrsf& t) { if (t.Form() == gp_Other) { return BRepBuilderAPI_GTransform(s, t, true); } else { - return apply_transformation(s, t.Trsf()); } } +TopoDS_Shape IfcGeom::util::apply_transformation(const TopoDS_Shape& s, const ifcopenshell::geometry::taxonomy::matrix4& t) { + // @todo this probably discards non-uniform scale? + gp_GTrsf trsf; + if (t.components_) { + gp_Trsf tr; + const auto& m = t.ccomponents(); + tr.SetValues( + m(0, 0), m(0, 1), m(0, 2), m(0, 3), + m(1, 0), m(1, 1), m(1, 2), m(1, 3), + m(2, 0), m(2, 1), m(2, 2), m(2, 3) + ); + trsf = tr; + } + return apply_transformation(s, trsf); +} + bool IfcGeom::util::fit_halfspace(const TopoDS_Shape& a, const TopoDS_Shape& b, TopoDS_Shape& box, double& height, double tol) { TopExp_Explorer exp(b, TopAbs_FACE); if (!exp.More()) { diff --git a/src/ifcgeom/kernels/opencascade/base_utils.h b/src/ifcgeom/kernels/opencascade/base_utils.h index f6f705e38f..84c57a8af2 100644 --- a/src/ifcgeom/kernels/opencascade/base_utils.h +++ b/src/ifcgeom/kernels/opencascade/base_utils.h @@ -66,10 +66,10 @@ namespace IfcGeom { bool project(const Handle_Geom_Curve&, const gp_Pnt&, gp_Pnt& p, double& u, double& d); bool project(const Handle_Geom_Surface&, const TopoDS_Shape&, double& u1, double& v1, double& u2, double& v2, double widen = 0.1); - double shape_volume(const TopoDS_Shape& s); double face_area(const TopoDS_Face& f); + TopoDS_Shape apply_transformation(const TopoDS_Shape&, const ifcopenshell::geometry::taxonomy::matrix4& t); TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_Trsf&); TopoDS_Shape apply_transformation(const TopoDS_Shape&, const gp_GTrsf&); diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 0a66b4265b..e538ac1f70 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -217,25 +217,25 @@ struct ShapeRTTI : public boost::static_visitor // I couldn't get the vector typemap to be applied when %extending Iterator constructor. // anyway it does not matter as SWIG generates C code without actual constructors %inline %{ - IfcGeom::Iterator* construct_iterator_with_include_exclude(IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { + IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { std::set elems_set(elems.begin(), elems.end()); IfcGeom::entity_filter ef{ include, false, elems_set }; - return new IfcGeom::Iterator(settings, file, {ef}, num_threads); + return new IfcGeom::Iterator(geometry_library, settings, file, {ef}, num_threads); } - IfcGeom::Iterator* construct_iterator_with_include_exclude_globalid(IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { + IfcGeom::Iterator* construct_iterator_with_include_exclude_globalid(const std::string& geometry_library, IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { std::set elems_set(elems.begin(), elems.end()); IfcGeom::attribute_filter af; af.attribute_name = "GlobalId"; af.populate(elems_set); af.include = include; - return new IfcGeom::Iterator(settings, file, {af}, num_threads); + return new IfcGeom::Iterator(geometry_library, settings, file, {af}, num_threads); } - IfcGeom::Iterator* construct_iterator_with_include_exclude_id(IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { + IfcGeom::Iterator* construct_iterator_with_include_exclude_id(const std::string& geometry_library, IfcGeom::IteratorSettings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads) { std::set elems_set(elems.begin(), elems.end()); IfcGeom::instance_id_filter af(include, false, elems_set); - return new IfcGeom::Iterator(settings, file, {af}, num_threads); + return new IfcGeom::Iterator(geometry_library, settings, file, {af}, num_threads); } %} @@ -373,10 +373,10 @@ struct ShapeRTTI : public boost::static_visitor } template - static boost::variant helper_fn_create_shape(IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) { + static boost::variant helper_fn_create_shape(const std::string& geometry_library, IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) { IfcParse::IfcFile* file = instance->data().file; - ifcopenshell::geometry::Converter kernel("opencascade", file, settings); + ifcopenshell::geometry::Converter kernel(geometry_library, file, settings); if (instance->declaration().is(Schema::IfcProduct::Class())) { if (representation) { @@ -501,62 +501,62 @@ struct ShapeRTTI : public boost::static_visitor %} %inline %{ - static boost::variant create_shape(IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0) { + static boost::variant create_shape(IfcGeom::IteratorSettings& settings, IfcUtil::IfcBaseClass* instance, IfcUtil::IfcBaseClass* representation = 0, const char* const geometry_library="opencascade") { const std::string& schema_name = instance->declaration().schema()->name(); #ifdef HAS_SCHEMA_2x3 if (schema_name == "IFC2X3") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4 if (schema_name == "IFC4") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x1 if (schema_name == "IFC4X1") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x2 if (schema_name == "IFC4X2") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3_rc1 if (schema_name == "IFC4X3_RC1") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3_rc2 if (schema_name == "IFC4X3_RC2") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3_rc3 if (schema_name == "IFC4X3_RC3") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3_rc4 if (schema_name == "IFC4X3_RC4") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3 if (schema_name == "IFC4X3") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3_tc1 if (schema_name == "IFC4X3_TC1") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif #ifdef HAS_SCHEMA_4x3_add1 if (schema_name == "IFC4X3_ADD1") { - return helper_fn_create_shape(settings, instance, representation); + return helper_fn_create_shape(geometry_library, settings, instance, representation); } #endif