diff --git a/src/ifcgeom/ConversionResult.cpp b/src/ifcgeom/ConversionResult.cpp index 3924c5cb04..092d33feee 100644 --- a/src/ifcgeom/ConversionResult.cpp +++ b/src/ifcgeom/ConversionResult.cpp @@ -23,9 +23,9 @@ void IfcGeom::ConversionResult::prepend(ifcopenshell::geometry::taxonomy::matrix std::string IfcGeom::NumberNativeDouble::to_string() const { std::stringstream ss; - ss << std::setprecision(std::numeric_limits::digits10 + 1) << value_; + 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>; \ No newline at end of file +template struct IFC_GEOM_API IfcGeom::OpaqueCoordinate<4>; diff --git a/src/ifcgeom/ConversionResult.h b/src/ifcgeom/ConversionResult.h index 1b5946f796..5ce3b19c2f 100644 --- a/src/ifcgeom/ConversionResult.h +++ b/src/ifcgeom/ConversionResult.h @@ -24,8 +24,18 @@ #include "../ifcgeom/ConversionSettings.h" #include "../ifcgeom/taxonomy.h" +#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include #include #include @@ -73,181 +83,361 @@ namespace IfcGeom { class IFC_GEOM_API Triangulation; } - template - constexpr T add_(T a, T b) { - return a + b; - } - - template - constexpr T subtract_(T a, T b) { - return a - b; - } - - template - constexpr T multiply_(T a, T b) { - return a * b; - } - - template - constexpr T divide_(T a, T b) { - return a / b; - } - - template - constexpr bool equals_(T a, T b) { - return a == b; - } - - template - constexpr bool less_than_(T a, T b) { - return a < b; - } - - template - constexpr T negate_(T a) { - return -a; - } - class IFC_GEOM_API OpaqueNumber { + protected: + struct NumberConcept { + virtual ~NumberConcept() {} + virtual double to_double() const = 0; + virtual std::string to_string() const = 0; + virtual std::shared_ptr add(const NumberConcept& other) const = 0; + virtual std::shared_ptr subtract(const NumberConcept& other) const = 0; + virtual std::shared_ptr multiply(const NumberConcept& other) const = 0; + virtual std::shared_ptr divide(const NumberConcept& other) const = 0; + virtual std::shared_ptr negate() const = 0; + virtual std::shared_ptr from_double(double value) const = 0; + virtual bool equals(const NumberConcept& other) const = 0; + virtual bool less_than(const NumberConcept& other) const = 0; + virtual const std::type_info& type() const = 0; + virtual const void* value_ptr() const = 0; + }; + + template + struct NumberModel : NumberConcept { + T value; + + NumberModel(const T& v) + : value(v) {} + + static const NumberModel& as_same(const NumberConcept& other) { + auto same = dynamic_cast(&other); + if (same == nullptr) { + throw std::runtime_error("Incompatible opaque number types"); + } + 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); + return ss.str(); + } + + virtual std::shared_ptr add(const NumberConcept& other) const { + return std::make_shared(value + as_same(other).value); + } + + virtual std::shared_ptr subtract(const NumberConcept& other) const { + return std::make_shared(value - as_same(other).value); + } + + virtual std::shared_ptr multiply(const NumberConcept& other) const { + return std::make_shared(value * as_same(other).value); + } + + virtual std::shared_ptr divide(const NumberConcept& other) const { + return std::make_shared(value / as_same(other).value); + } + + virtual std::shared_ptr negate() const { + return std::make_shared(-value); + } + + virtual std::shared_ptr from_double(double v) const { + return std::make_shared(T(v)); + } + + virtual bool equals(const NumberConcept& other) const { + return value == as_same(other).value; + } + + virtual bool less_than(const NumberConcept& other) const { + return value < as_same(other).value; + } + + virtual const std::type_info& type() const { + return typeid(T); + } + + virtual const void* value_ptr() const { + return &value; + } + }; + + template + struct is_shared_ptr : std::false_type {}; + + template + struct is_shared_ptr> : std::true_type {}; + + private: + std::shared_ptr data_; + + const NumberConcept& data() const { + if (!data_) { + throw std::runtime_error("Empty opaque number"); + } + return *data_; + } + + protected: + OpaqueNumber(std::shared_ptr data) + : data_(std::move(data)) {} + public: - virtual double to_double() const = 0; - virtual std::string to_string() const = 0; + OpaqueNumber() = default; + virtual ~OpaqueNumber() = default; - virtual ~OpaqueNumber() {} + 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))) {} - virtual OpaqueNumber* operator+(OpaqueNumber* other) const = 0; - virtual OpaqueNumber* operator-(OpaqueNumber* other) const = 0; - virtual OpaqueNumber* operator*(OpaqueNumber* other) const = 0; - virtual OpaqueNumber* operator/(OpaqueNumber* other) const = 0; - virtual bool operator==(OpaqueNumber* other) const = 0; - virtual bool operator<(OpaqueNumber* other) const = 0; - virtual OpaqueNumber* operator-() const = 0; - virtual OpaqueNumber* clone() const = 0; + double to_double() const { + return data().to_double(); + } + + std::string to_string() const { + return data().to_string(); + } + + bool empty() const { + return !data_; + } + + template + const T& value_as() const { + if (data().type() != typeid(T)) { + throw std::runtime_error("Unexpected opaque number type"); + } + return *static_cast(data().value_ptr()); + } + + OpaqueNumber add(const OpaqueNumber& other) const { + return OpaqueNumber(data().add(other.data())); + } + + OpaqueNumber subtract(const OpaqueNumber& other) const { + return OpaqueNumber(data().subtract(other.data())); + } + + OpaqueNumber multiply(const OpaqueNumber& other) const { + return OpaqueNumber(data().multiply(other.data())); + } + + OpaqueNumber divide(const OpaqueNumber& other) const { + return OpaqueNumber(data().divide(other.data())); + } + + OpaqueNumber negated() const { + return OpaqueNumber(data().negate()); + } + + OpaqueNumber same_type(double value) const { + return OpaqueNumber(data().from_double(value)); + } + + bool equals(const OpaqueNumber& other) const { + return data().equals(other.data()); + } + + bool less_than(const OpaqueNumber& other) const { + return data().less_than(other.data()); + } + + OpaqueNumber operator+(const OpaqueNumber& other) const { + return add(other); + } + + OpaqueNumber operator-(const OpaqueNumber& other) const { + return subtract(other); + } + + OpaqueNumber operator*(const OpaqueNumber& other) const { + return multiply(other); + } + + OpaqueNumber operator/(const OpaqueNumber& other) const { + return divide(other); + } + + bool operator==(const OpaqueNumber& other) const { + return equals(other); + } + + bool operator<(const OpaqueNumber& other) const { + return less_than(other); + } + + OpaqueNumber operator-() const { + return negated(); + } }; - // @todo this can simply be a template class, to remove the need for the NumberEpeck in CGAL kernel. class IFC_GEOM_API NumberNativeDouble : public OpaqueNumber { - private: - double value_; - - template - OpaqueNumber* binary_op(OpaqueNumber* other) const { - auto nnd = dynamic_cast(other); - if (nnd) { - return new NumberNativeDouble(Fn(value_, nnd->value_)); - } else { - return nullptr; - } - } - - template - bool binary_op_bool(OpaqueNumber* other) const { - auto nnd = dynamic_cast(other); - if (nnd) { - return Fn(value_, nnd->value_); - } else { - return false; - } - } - - template - OpaqueNumber* unary_op() const { - return new NumberNativeDouble(Fn(value_)); - } public: NumberNativeDouble(double v) - : value_(v) {} + : OpaqueNumber(v) {} - virtual double to_double() const { - return value_; + double value() const { + return value_as(); } - virtual std::string to_string() const; - - virtual OpaqueNumber* operator+(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual OpaqueNumber* operator-(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual OpaqueNumber* operator*(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual OpaqueNumber* operator/(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual bool operator==(OpaqueNumber* other) const { - return binary_op_bool>(other); - } - virtual bool operator<(OpaqueNumber* other) const { - return binary_op_bool>(other); - } - virtual OpaqueNumber* operator-() const { - return unary_op>(); - } - virtual OpaqueNumber* clone() const { - return new NumberNativeDouble(value_); - } + std::string to_string() const; }; template struct IFC_GEOM_API OpaqueCoordinate { private: - std::array values; + std::array values_; - static void copy_(std::array& dest, const std::array& src) { - for (size_t i = 0; i < N; ++i) { - dest[i] = (src[i] != nullptr) ? src[i]->clone() : nullptr; - } + static OpaqueNumber as_number(OpaqueNumber value) { + return value; } + public: - template - OpaqueCoordinate(Args... args) { - static_assert(sizeof...(args) == N, "Incorrect number of arguments provided"); - init_<0>(args...); +#ifndef SWIG + template > + OpaqueCoordinate(Args&&... args) { + init_<0>(std::forward(args)...); + } +#endif + + OpaqueCoordinate() = default; + + std::size_t size() const { + return N; } - OpaqueCoordinate() { - for (auto it = values.begin(); it != values.end(); ++it) { - *it = nullptr; - } - } - - OpaqueCoordinate(const OpaqueCoordinate& other) { - copy_(values, other.values); - } - - OpaqueCoordinate& operator=(const OpaqueCoordinate& other) { - if (this != &other) { - copy_(values, other.values); - } - return *this; - } - - ~OpaqueCoordinate() { - for (auto it = values.begin(); it != values.end(); ++it) { - delete *it; - } - } - - OpaqueNumber* get(size_t i) const { + OpaqueNumber get(size_t i) const { if (i >= N) { - return nullptr; + return OpaqueNumber(); } - return values[i]; + return values_[i]; } - void set(size_t i, OpaqueNumber* n) { + double get_double(size_t i) const { + return get(i).to_double(); + } + + void set(size_t i, const OpaqueNumber& n) { if (i < N) { - values[i] = n->clone(); + values_[i] = n; } } + + std::vector to_doubles() const { + std::vector result; + result.reserve(N); + for (const auto& value : values_) { + result.push_back(value.to_double()); + } + return result; + } + + OpaqueCoordinate operator-() const { + OpaqueCoordinate result; + for (size_t i = 0; i < N; ++i) { + result.values_[i] = values_[i].negated(); + } + return result; + } + + OpaqueCoordinate operator+(const OpaqueCoordinate& other) const { + OpaqueCoordinate result; + for (size_t i = 0; i < N; ++i) { + result.values_[i] = values_[i].add(other.values_[i]); + } + return result; + } + + OpaqueCoordinate operator-(const OpaqueCoordinate& other) const { + OpaqueCoordinate result; + for (size_t i = 0; i < N; ++i) { + result.values_[i] = values_[i].subtract(other.values_[i]); + } + return result; + } + + OpaqueCoordinate operator*(const OpaqueNumber& scalar) const { + OpaqueCoordinate result; + for (size_t i = 0; i < N; ++i) { + result.values_[i] = values_[i].multiply(scalar); + } + return result; + } + + OpaqueCoordinate operator/(const OpaqueNumber& scalar) const { + OpaqueCoordinate result; + for (size_t i = 0; i < N; ++i) { + result.values_[i] = values_[i].divide(scalar); + } + return result; + } + + OpaqueCoordinate scale(double scalar) const { + return *this * values_[0].same_type(scalar); + } + + OpaqueNumber dot(const OpaqueCoordinate& other) const { + if constexpr (N == 0) { + return OpaqueNumber(0.0); + } else { + OpaqueNumber result = values_[0].multiply(other.values_[0]); + for (size_t i = 1; i < N; ++i) { + result = result.add(values_[i].multiply(other.values_[i])); + } + return result; + } + } + + double norm() const { + return std::sqrt(dot(*this).to_double()); + } + + OpaqueCoordinate normalized() const { + const double length = norm(); + if (length == 0.0) { + return *this; + } + return *this / values_[0].same_type(length); + } + + OpaqueCoordinate normalized_by_max_abs() const { + double max_abs = 0.0; + for (const auto& value : values_) { + max_abs = (std::max)(max_abs, std::fabs(value.to_double())); + } + if (max_abs == 0.0) { + return *this; + } + return *this / values_[0].same_type(max_abs); + } + private: - template - void init_(OpaqueNumber* value, Args... args) { - values[Index] = value; + template + void init_(Arg&& value, Args&&... args) { + values_[Index] = as_number(std::forward(value)); if constexpr (Index + 1 < N) { - init_(args...); + init_(std::forward(args)...); } } }; @@ -271,9 +461,9 @@ namespace IfcGeom { virtual std::pair, OpaqueCoordinate<3>> bounding_box() const = 0; virtual void set_box(void* b) = 0; - virtual OpaqueNumber* length() = 0; - virtual OpaqueNumber* area() = 0; - virtual OpaqueNumber* volume() = 0; + virtual OpaqueNumber length() = 0; + virtual OpaqueNumber area() = 0; + virtual OpaqueNumber volume() = 0; virtual OpaqueCoordinate<3> position() = 0; virtual OpaqueCoordinate<3> axis() = 0; diff --git a/src/ifcgeom/IfcGeomRepresentation.cpp b/src/ifcgeom/IfcGeomRepresentation.cpp index f0c150597e..d533adf0df 100644 --- a/src/ifcgeom/IfcGeomRepresentation.cpp +++ b/src/ifcgeom/IfcGeomRepresentation.cpp @@ -81,7 +81,7 @@ bool IfcGeom::Representation::BRep::calculate_surface_area(double& area) const { area = 0.; return false; } - area = s->area()->to_double(); + area = s->area().to_double(); return true; } @@ -91,7 +91,7 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const { volume = 0.; return false; } - volume = s->volume()->to_double(); + volume = s->volume().to_double(); return true; } diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp index f8fa868946..bd9266dcf5 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.cpp @@ -40,9 +40,9 @@ namespace { OpaqueCoordinate<3> opaque_point(const cgal_point_t& p) { return OpaqueCoordinate<3>( - new NumberType(p.cartesian(0)), - new NumberType(p.cartesian(1)), - new NumberType(p.cartesian(2)) + NumberType(p.cartesian(0)), + NumberType(p.cartesian(1)), + NumberType(p.cartesian(2)) ); } @@ -59,9 +59,9 @@ namespace { throw std::runtime_error("Invalid shape type"); } return OpaqueCoordinate<3>( - new NumberType(v.x() / maxval), - new NumberType(v.y() / maxval), - new NumberType(v.z() / maxval) + NumberType(v.x() / maxval), + NumberType(v.y() / maxval), + NumberType(v.z() / maxval) ); } @@ -71,27 +71,27 @@ namespace { throw std::runtime_error("Invalid shape type"); } return OpaqueCoordinate<4>( - new NumberType(p.a() / maxval), - new NumberType(p.b() / maxval), - new NumberType(p.c() / maxval), - new NumberType(p.d() / maxval) + NumberType(p.a() / maxval), + NumberType(p.b() / maxval), + NumberType(p.c() / maxval), + NumberType(p.d() / maxval) ); } cgal_plane_t plane_from_opaque(const OpaqueCoordinate<4>& p) { #ifdef IFOPSH_SIMPLE_KERNEL return cgal_plane_t( - p.get(0)->to_double(), - p.get(1)->to_double(), - p.get(2)->to_double(), - p.get(3)->to_double() + p.get(0).to_double(), + p.get(1).to_double(), + p.get(2).to_double(), + p.get(3).to_double() ); #else return cgal_plane_t( - static_cast(p.get(0))->value(), - static_cast(p.get(1))->value(), - static_cast(p.get(2))->value(), - static_cast(p.get(3))->value() + p.get(0).value_as(), + p.get(1).value_as(), + p.get(2).value_as(), + p.get(3).value_as() ); #endif } @@ -697,7 +697,7 @@ int ifcopenshell::geometry::CgalShape::num_faces() const } } -OpaqueNumber* ifcopenshell::geometry::CgalShape::CgalShape::length() +OpaqueNumber ifcopenshell::geometry::CgalShape::CgalShape::length() { Kernel_::FT len = 0; if (is_wire()) { @@ -711,30 +711,30 @@ OpaqueNumber* ifcopenshell::geometry::CgalShape::CgalShape::length() ).squared_length()); } } - return new NumberType(len); + return NumberType(len); } -OpaqueNumber* ifcopenshell::geometry::CgalShape::area() +OpaqueNumber ifcopenshell::geometry::CgalShape::area() { if (is_wire()) { - return new NumberType(wire_area(wire())); + return NumberType(wire_area(wire())); } if (is_point()) { - return new NumberType(Kernel_::FT(0)); + return NumberType(Kernel_::FT(0)); } auto s = poly(); CGAL::Polygon_mesh_processing::triangulate_faces(s); - return new NumberType(CGAL::Polygon_mesh_processing::area(s)); + return NumberType(CGAL::Polygon_mesh_processing::area(s)); } -OpaqueNumber* ifcopenshell::geometry::CgalShape::volume() +OpaqueNumber ifcopenshell::geometry::CgalShape::volume() { if (is_point() || is_wire()) { - return new NumberType(Kernel_::FT(0)); + return NumberType(Kernel_::FT(0)); } auto s = poly(); CGAL::Polygon_mesh_processing::triangulate_faces(s); - return new NumberType(CGAL::Polygon_mesh_processing::volume(s)); + return NumberType(CGAL::Polygon_mesh_processing::volume(s)); } OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::position() @@ -760,9 +760,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShape::position() p[i] /= N; } return OpaqueCoordinate<3>( - new NumberType(p[0]), - new NumberType(p[1]), - new NumberType(p[2]) + NumberType(p[0]), + NumberType(p[1]), + NumberType(p[2]) ); } else { throw std::runtime_error("Invalid shape type"); @@ -1058,17 +1058,17 @@ int ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::num_faces() const throw std::runtime_error("Not implemented"); } -OpaqueNumber* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::CgalShapeHalfSpaceDecomposition::length() +OpaqueNumber ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::CgalShapeHalfSpaceDecomposition::length() { throw std::runtime_error("Not implemented"); } -OpaqueNumber* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::area() +OpaqueNumber ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::area() { throw std::runtime_error("Not implemented"); } -OpaqueNumber* ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::volume() +OpaqueNumber ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::volume() { throw std::runtime_error("Not implemented"); } @@ -1078,9 +1078,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::pos if (planes_.size() == 1) { auto xyz = CGAL::ORIGIN + planes_.front().d() * CGAL::Vector_3(planes_.front().a(), planes_.front().b(), planes_.front().c()); return OpaqueCoordinate<3>( - new NumberType(xyz.cartesian(0)), - new NumberType(xyz.cartesian(1)), - new NumberType(xyz.cartesian(2)) + NumberType(xyz.cartesian(0)), + NumberType(xyz.cartesian(1)), + NumberType(xyz.cartesian(2)) ); } else { throw std::runtime_error("Invalid shape type"); @@ -1095,9 +1095,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::axi auto maxel = std::max_element(abc.begin(), abc.end()); auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; return OpaqueCoordinate<3>( - new NumberType(planes_.front().a() / maxval), - new NumberType(planes_.front().b() / maxval), - new NumberType(planes_.front().c() / maxval) + NumberType(planes_.front().a() / maxval), + NumberType(planes_.front().b() / maxval), + NumberType(planes_.front().c() / maxval) ); } else { throw std::runtime_error("Invalid shape type"); @@ -1112,10 +1112,10 @@ OpaqueCoordinate<4> ifcopenshell::geometry::CgalShapeHalfSpaceDecomposition::pla auto maxel = std::max_element(abc.begin(), abc.end()); auto maxval = ((-*minel) > *maxel) ? (-*minel) : *maxel; return OpaqueCoordinate<4>( - new NumberType(planes_.front().a() / maxval), - new NumberType(planes_.front().b() / maxval), - new NumberType(planes_.front().c() / maxval), - new NumberType(planes_.front().d() / maxval) + NumberType(planes_.front().a() / maxval), + NumberType(planes_.front().b() / maxval), + NumberType(planes_.front().c() / maxval), + NumberType(planes_.front().d() / maxval) ); } else { throw std::runtime_error("Invalid shape type"); diff --git a/src/ifcgeom/kernels/cgal/CgalConversionResult.h b/src/ifcgeom/kernels/cgal/CgalConversionResult.h index d169f5495e..f54854ac30 100644 --- a/src/ifcgeom/kernels/cgal/CgalConversionResult.h +++ b/src/ifcgeom/kernels/cgal/CgalConversionResult.h @@ -95,86 +95,80 @@ namespace ifcopenshell { namespace geometry { using IfcGeom::OpaqueCoordinate; using IfcGeom::OpaqueNumber; - using IfcGeom::add_; - using IfcGeom::subtract_; - using IfcGeom::multiply_; - using IfcGeom::divide_; - using IfcGeom::equals_; - using IfcGeom::less_than_; - using IfcGeom::negate_; - #ifndef IFOPSH_SIMPLE_KERNEL class IFC_GEOMLIBRARY_API NumberEpeck : public OpaqueNumber { private: - CGAL::Epeck::FT value_; + struct Model : OpaqueNumber::NumberConcept { + CGAL::Epeck::FT value; - template - OpaqueNumber* binary_op(OpaqueNumber* other) const { - auto nnd = dynamic_cast(other); - if (nnd) { - return new NumberEpeck(Fn(value_, nnd->value_)); - } else { - return nullptr; + Model(const CGAL::Epeck::FT& v) + : value(v) {} + + static const Model& as_same(const NumberConcept& other) { + auto same = dynamic_cast(&other); + if (same == nullptr) { + throw std::runtime_error("Incompatible opaque number types"); + } + return *same; } - } - template - bool binary_op_bool(OpaqueNumber* other) const { - auto nnd = dynamic_cast(other); - if (nnd) { - return Fn(value_, nnd->value_); - } else { - return false; + virtual double to_double() const { + return CGAL::to_double(value); } - } - template - OpaqueNumber* unary_op() const { - return new NumberEpeck(Fn(value_)); - } + virtual std::string to_string() const { + std::stringstream ss; + ss << value.exact(); + return ss.str(); + } + + virtual std::shared_ptr add(const NumberConcept& other) const { + return std::make_shared(value + as_same(other).value); + } + + virtual std::shared_ptr subtract(const NumberConcept& other) const { + return std::make_shared(value - as_same(other).value); + } + + virtual std::shared_ptr multiply(const NumberConcept& other) const { + return std::make_shared(value * as_same(other).value); + } + + virtual std::shared_ptr divide(const NumberConcept& other) const { + return std::make_shared(value / as_same(other).value); + } + + virtual std::shared_ptr negate() const { + return std::make_shared(-value); + } + + virtual std::shared_ptr from_double(double v) const { + return std::make_shared(CGAL::Epeck::FT(v)); + } + + virtual bool equals(const NumberConcept& other) const { + return value == as_same(other).value; + } + + virtual bool less_than(const NumberConcept& other) const { + return value < as_same(other).value; + } + + virtual const std::type_info& type() const { + return typeid(CGAL::Epeck::FT); + } + + virtual const void* value_ptr() const { + return &value; + } + }; + public: NumberEpeck(const CGAL::Epeck::FT& v) - : value_(v) {} - - virtual ~NumberEpeck() { } - - virtual double to_double() const { - return CGAL::to_double(value_); - } - - virtual std::string to_string() const { - std::stringstream ss; - ss << value_.exact(); - return ss.str(); - } + : OpaqueNumber(std::make_shared(v)) {} const CGAL::Epeck::FT& value() const { - return value_; - } - - virtual OpaqueNumber* operator+(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual OpaqueNumber* operator-(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual OpaqueNumber* operator*(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual OpaqueNumber* operator/(OpaqueNumber* other) const { - return binary_op>(other); - } - virtual bool operator==(OpaqueNumber* other) const { - return binary_op_bool>(other); - } - virtual bool operator<(OpaqueNumber* other) const { - return binary_op_bool>(other); - } - virtual OpaqueNumber* operator-() const { - return unary_op>(); - } - virtual OpaqueNumber* clone() const { - return new NumberEpeck(value_); + return value_as(); } }; #endif @@ -253,9 +247,9 @@ namespace ifcopenshell { namespace geometry { // @todo this must be something with a virtual dtor so that we can delete it. virtual std::pair, OpaqueCoordinate<3>> bounding_box() const; - virtual OpaqueNumber* length(); - virtual OpaqueNumber* area(); - virtual OpaqueNumber* volume(); + virtual OpaqueNumber length(); + virtual OpaqueNumber area(); + virtual OpaqueNumber volume(); virtual OpaqueCoordinate<3> position(); virtual OpaqueCoordinate<3> axis(); @@ -322,9 +316,9 @@ namespace ifcopenshell { namespace geometry { virtual std::pair, OpaqueCoordinate<3>> bounding_box() const; virtual void set_box(void* b); - virtual OpaqueNumber* length(); - virtual OpaqueNumber* area(); - virtual OpaqueNumber* volume(); + virtual OpaqueNumber length(); + virtual OpaqueNumber area(); + virtual OpaqueNumber volume(); virtual OpaqueCoordinate<3> position(); virtual OpaqueCoordinate<3> axis(); diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp index 36e423730e..37f38c303e 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.cpp @@ -385,28 +385,28 @@ int ifcopenshell::geometry::OpenCascadeShape::num_faces() const return IfcGeom::util::count(shape_, TopAbs_FACE); } -OpaqueNumber* ifcopenshell::geometry::OpenCascadeShape::OpenCascadeShape::length() +OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::OpenCascadeShape::length() { GProp_GProps prop; BRepGProp::LinearProperties(shape_, prop); double l = prop.Mass(); - return new NumberNativeDouble(l); + return NumberNativeDouble(l); } -OpaqueNumber* ifcopenshell::geometry::OpenCascadeShape::area() +OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::area() { GProp_GProps prop; BRepGProp::SurfaceProperties(shape_, prop); double l = prop.Mass(); - return new NumberNativeDouble(l); + return NumberNativeDouble(l); } -OpaqueNumber* ifcopenshell::geometry::OpenCascadeShape::volume() +OpaqueNumber ifcopenshell::geometry::OpenCascadeShape::volume() { GProp_GProps prop; BRepGProp::VolumeProperties(shape_, prop); double l = prop.Mass(); - return new NumberNativeDouble(l); + return NumberNativeDouble(l); } #include @@ -419,9 +419,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::OpenCascadeShape::position() if (plane) { auto loc = plane->Location(); return OpaqueCoordinate<3>( - new NumberNativeDouble(loc.X()), - new NumberNativeDouble(loc.Y()), - new NumberNativeDouble(loc.Z()) + NumberNativeDouble(loc.X()), + NumberNativeDouble(loc.Y()), + NumberNativeDouble(loc.Z()) ); } } @@ -436,9 +436,9 @@ OpaqueCoordinate<3> ifcopenshell::geometry::OpenCascadeShape::axis() if (plane) { auto dir = plane->Axis().Direction(); return OpaqueCoordinate<3>( - new NumberNativeDouble(dir.X()), - new NumberNativeDouble(dir.Y()), - new NumberNativeDouble(dir.Z()) + NumberNativeDouble(dir.X()), + NumberNativeDouble(dir.Y()), + NumberNativeDouble(dir.Z()) ); } } @@ -454,10 +454,10 @@ OpaqueCoordinate<4> ifcopenshell::geometry::OpenCascadeShape::plane_equation() double a, b, c, d; plane->Pln().Coefficients(a, b, c, d); return OpaqueCoordinate<4>( - new NumberNativeDouble(a), - new NumberNativeDouble(b), - new NumberNativeDouble(c), - new NumberNativeDouble(d) + NumberNativeDouble(a), + NumberNativeDouble(b), + NumberNativeDouble(c), + NumberNativeDouble(d) ); } } diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h index 643c797905..70b612feba 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeConversionResult.h @@ -78,9 +78,9 @@ namespace ifcopenshell { // @todo this must be something with a virtual dtor so that we can delete it. virtual std::pair, OpaqueCoordinate<3>> bounding_box() const; - virtual OpaqueNumber* length(); - virtual OpaqueNumber* area(); - virtual OpaqueNumber* volume(); + virtual OpaqueNumber length(); + virtual OpaqueNumber area(); + virtual OpaqueNumber volume(); virtual OpaqueCoordinate<3> position(); virtual OpaqueCoordinate<3> axis(); diff --git a/src/ifcwrap/IfcGeomWrapper.i b/src/ifcwrap/IfcGeomWrapper.i index 10d9083403..20e687e04e 100644 --- a/src/ifcwrap/IfcGeomWrapper.i +++ b/src/ifcwrap/IfcGeomWrapper.i @@ -83,16 +83,9 @@ %newobject IfcGeom::ConversionResultShape::moved; %newobject IfcGeom::ConversionResultShape::wrap_in_compound; -%newobject IfcGeom::ConversionResultShape::area; -%newobject IfcGeom::ConversionResultShape::volume; -%newobject IfcGeom::ConversionResultShape::length; %newobject nary_union; -%newobject IfcGeom::OpaqueNumber::operator+; -%newobject IfcGeom::OpaqueNumber::operator-; -%newobject IfcGeom::OpaqueNumber::operator*; -%newobject IfcGeom::OpaqueNumber::operator/; %inline %{ template @@ -1180,17 +1173,15 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type %template(OpaqueCoordinate_3) IfcGeom::OpaqueCoordinate<3>; %template(OpaqueCoordinate_4) IfcGeom::OpaqueCoordinate<4>; -%newobject create_epeck; - %inline %{ - IfcGeom::OpaqueNumber* create_epeck(int i) { - return new ifcopenshell::geometry::NumberEpeck(i); + IfcGeom::OpaqueNumber create_epeck(int i) { + return ifcopenshell::geometry::NumberEpeck(i); } - IfcGeom::OpaqueNumber* create_epeck(double d) { - return new ifcopenshell::geometry::NumberEpeck(d); + IfcGeom::OpaqueNumber create_epeck(double d) { + return ifcopenshell::geometry::NumberEpeck(d); } - IfcGeom::OpaqueNumber* create_epeck(const std::string& s) { - return new 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)); } %}