diff --git a/src/ifcgeom/ConversionResult.cpp b/src/ifcgeom/ConversionResult.cpp index 092d33feee..a5749bf494 100644 --- a/src/ifcgeom/ConversionResult.cpp +++ b/src/ifcgeom/ConversionResult.cpp @@ -1,8 +1,6 @@ #include "ConversionResult.h" #include "IfcGeomRepresentation.h" -#include - IfcGeom::Representation::Triangulation* IfcGeom::ConversionResultShape::Triangulate(const ifcopenshell::geometry::Settings& settings, Logger& logger) const { auto t = IfcGeom::Representation::Triangulation::empty(settings); @@ -21,11 +19,5 @@ void IfcGeom::ConversionResult::prepend(ifcopenshell::geometry::taxonomy::matrix placement_ = make(trsf->ccomponents() * placement_->ccomponents()); } -std::string IfcGeom::NumberNativeDouble::to_string() const { - std::stringstream ss; - ss << std::setprecision(std::numeric_limits::digits10 + 1) << value(); - return ss.str(); -} - template struct IFC_GEOM_API IfcGeom::OpaqueCoordinate<3>; template struct IFC_GEOM_API IfcGeom::OpaqueCoordinate<4>; diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 5ce3b19c2f..f7a380184a 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -101,6 +101,12 @@ namespace IfcGeom { virtual const void* value_ptr() const = 0; }; + template + struct has_exact : std::false_type {}; + + template + struct has_exact().exact())>> : std::true_type {}; + template struct NumberModel : NumberConcept { T value; @@ -116,26 +122,19 @@ namespace IfcGeom { return *same; } - template - static auto stream_exact(std::ostream& os, const U& v, int) -> decltype(os << v.exact(), void()) { - os << v.exact(); - } - - template - static void stream_exact(std::ostream& os, const U& v, long) { - if constexpr (std::is_floating_point::value) { - os << std::setprecision(std::numeric_limits::digits10 + 1); - } - os << v; - } - virtual double to_double() const { return static_cast(value); } virtual std::string to_string() const { std::stringstream ss; - stream_exact(ss, value, 0); + if constexpr (has_exact::value) { + ss << value.exact(); + } else if constexpr (std::is_floating_point::value) { + ss << std::setprecision(std::numeric_limits::digits10 + 1); + } + ss << value; + } return ss.str(); } @@ -204,12 +203,14 @@ namespace IfcGeom { OpaqueNumber() = default; virtual ~OpaqueNumber() = default; +#ifndef SWIG template < typename T, typename Decayed = std::decay_t, typename = std::enable_if_t::value && !is_shared_ptr::value>> explicit OpaqueNumber(T&& value) : data_(std::make_shared>(std::forward(value))) {} +#endif double to_double() const { return data().to_double(); @@ -292,18 +293,6 @@ namespace IfcGeom { } }; - class IFC_GEOM_API NumberNativeDouble : public OpaqueNumber { - public: - NumberNativeDouble(double v) - : OpaqueNumber(v) {} - - double value() const { - return value_as(); - } - - std::string to_string() const; - }; - template struct IFC_GEOM_API OpaqueCoordinate { private: diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index bd9266dcf5..5dfcf9ebfb 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -11,11 +11,10 @@ using IfcGeom::OpaqueNumber; using IfcGeom::OpaqueCoordinate; -using IfcGeom::NumberNativeDouble; using IfcGeom::ConversionResultShape; #ifdef IFOPSH_SIMPLE_KERNEL -#define NumberType NumberNativeDouble +#define NumberType OpaqueNumber #else using ifcopenshell::geometry::NumberEpeck; #define NumberType NumberEpeck @@ -103,6 +102,15 @@ namespace { }); } + void apply_normalized_plane_map(const plane_map& mp, std::list& planes) { + for (auto& plane : planes) { + auto it = mp.find(normalized_plane_for_map(plane)); + if (it != mp.end()) { + plane = it->second; + } + } + } + cgal_vector_t wire_normal(const cgal_wire_t& wire) { typename Kernel_::FT a(0), b(0), c(0); if (wire.size() < 3) { @@ -1196,6 +1204,7 @@ std::size_t ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(OpaqueC std::size_t mutated = 0; auto nw = shape_->map(mp, mutated); shape_ = std::move(nw); + apply_normalized_plane_map(mp, planes_); return mutated; } @@ -1214,6 +1223,7 @@ std::size_t ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::map(const s std::size_t mutated = 0; auto nw = shape_->map(mp, mutated); shape_ = std::move(nw); + apply_normalized_plane_map(mp, planes_); return mutated; } diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp index 37f38c303e..00de7fbbee 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp @@ -31,7 +31,6 @@ using IfcGeom::OpaqueNumber; using IfcGeom::OpaqueCoordinate; -using IfcGeom::NumberNativeDouble; using IfcGeom::ConversionResultShape; namespace { @@ -390,7 +389,7 @@ OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::OpenCascadeShape::length( GProp_GProps prop; BRepGProp::LinearProperties(shape_, prop); double l = prop.Mass(); - return NumberNativeDouble(l); + return OpaqueNumber(l); } OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::area() @@ -398,7 +397,7 @@ OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::area() GProp_GProps prop; BRepGProp::SurfaceProperties(shape_, prop); double l = prop.Mass(); - return NumberNativeDouble(l); + return OpaqueNumber(l); } OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::volume() @@ -406,7 +405,7 @@ OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::volume() GProp_GProps prop; BRepGProp::VolumeProperties(shape_, prop); double l = prop.Mass(); - return NumberNativeDouble(l); + return OpaqueNumber(l); } #include @@ -419,9 +418,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::OpenCascadeShape::position() if (plane) { auto loc = plane->Location(); return OpaqueCoordinate<3>( - NumberNativeDouble(loc.X()), - NumberNativeDouble(loc.Y()), - NumberNativeDouble(loc.Z()) + OpaqueNumber(loc.X()), + OpaqueNumber(loc.Y()), + OpaqueNumber(loc.Z()) ); } } @@ -436,9 +435,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::OpenCascadeShape::axis() if (plane) { auto dir = plane->Axis().Direction(); return OpaqueCoordinate<3>( - NumberNativeDouble(dir.X()), - NumberNativeDouble(dir.Y()), - NumberNativeDouble(dir.Z()) + OpaqueNumber(dir.X()), + OpaqueNumber(dir.Y()), + OpaqueNumber(dir.Z()) ); } } @@ -454,10 +453,10 @@ OpaqueCoordinate<4> ifcopenshell::geometry::OpenCascadeShape::plane_equation() double a, b, c, d; plane->Pln().Coefficients(a, b, c, d); return OpaqueCoordinate<4>( - NumberNativeDouble(a), - NumberNativeDouble(b), - NumberNativeDouble(c), - NumberNativeDouble(d) + OpaqueNumber(a), + OpaqueNumber(b), + OpaqueNumber(c), + OpaqueNumber(d) ); } } diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 20e687e04e..65655cd247 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -630,31 +630,31 @@ 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(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, int num_threads, Logger& logger = Logger::Root()) { - return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, num_threads, logger); - } - - IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads, Logger& logger = Logger::Root()) { - std::set elems_set(elems.begin(), elems.end()); - IfcGeom::entity_filter ef{ include, false, elems_set }; - return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {ef}, num_threads, logger); - } - - IfcGeom::Iterator* construct_iterator_with_include_exclude_globalid(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads, Logger& logger = Logger::Root()) { - 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(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {af}, num_threads, logger); - } - - IfcGeom::Iterator* construct_iterator_with_include_exclude_id(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads, Logger& logger = Logger::Root()) { - std::set elems_set(elems.begin(), elems.end()); - IfcGeom::instance_id_filter af(include, false, elems_set); - return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {af}, num_threads, logger); - } -%} + IfcGeom::Iterator* construct_iterator(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, int num_threads, Logger& logger = Logger::Root()) { + return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, num_threads, logger); + } + + IfcGeom::Iterator* construct_iterator_with_include_exclude(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads, Logger& logger = Logger::Root()) { + std::set elems_set(elems.begin(), elems.end()); + IfcGeom::entity_filter ef{ include, false, elems_set }; + return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {ef}, num_threads, logger); + } + + IfcGeom::Iterator* construct_iterator_with_include_exclude_globalid(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads, Logger& logger = Logger::Root()) { + 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(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {af}, num_threads, logger); + } + + IfcGeom::Iterator* construct_iterator_with_include_exclude_id(const std::string& geometry_library, ifcopenshell::geometry::Settings settings, IfcParse::IfcFile* file, std::vector elems, bool include, int num_threads, Logger& logger = Logger::Root()) { + std::set elems_set(elems.begin(), elems.end()); + IfcGeom::instance_id_filter af(include, false, elems_set); + return new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(file, geometry_library, settings, logger), settings, file, {af}, num_threads, logger); + } +%} %extend IfcGeom::Representation::Triangulation { @@ -1174,14 +1174,14 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type %template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>; %inline %{ - IfcGeom::OpaqueNumber create_epeck(int i) { - return ifcopenshell::geometry::NumberEpeck(i); + IfcGeom::OpaqueNumber create_epeck(int i) { + return ifcopenshell::geometry::NumberEpeck(i); } - IfcGeom::OpaqueNumber create_epeck(double d) { - return ifcopenshell::geometry::NumberEpeck(d); + IfcGeom::OpaqueNumber create_epeck(double d) { + return ifcopenshell::geometry::NumberEpeck(d); } - IfcGeom::OpaqueNumber create_epeck(const std::string& s) { - return ifcopenshell::geometry::NumberEpeck(typename CGAL::Epeck::FT::ET(s)); + IfcGeom::OpaqueNumber create_epeck(const std::string& s) { + return ifcopenshell::geometry::NumberEpeck(typename CGAL::Epeck::FT::ET(s)); } %} @@ -1279,11 +1279,11 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type } } - std::vector arrange_polygons(svgfill::arrange_polygon_settings settings, const std::vector& polygons, Logger& logger = Logger::Root()) { - std::vector r; - if (svgfill::arrange_polygons(settings, polygons, r, logger)) { - return r; - } else { + std::vector arrange_polygons(svgfill::arrange_polygon_settings settings, const std::vector& polygons, Logger& logger = Logger::Root()) { + std::vector r; + if (svgfill::arrange_polygons(settings, polygons, r, logger)) { + return r; + } else { throw std::runtime_error("Failed to arrange polygons"); } } diff --git a/src/ifcwrap/IfcPython.i b/src/ifcwrap/IfcPython.i index ca802cedfa..eb73c984a7 100644 --- a/src/ifcwrap/IfcPython.i +++ b/src/ifcwrap/IfcPython.i @@ -59,7 +59,6 @@ %} %template(DoubleArray3) std::array; -%ignore IfcGeom::NumberNativeDouble; %ignore ifcopenshell::geometry::Converter; // Not relevant for python: new_IfcBaseClass() calls instantiate()