Auto mem mngt in conversion result number types; more arithmetic on OpaqueCoordinate

This commit is contained in:
Thomas Krijnen
2026-06-22 10:38:25 +02:00
parent 312be203c9
commit 4f21bd1c69
8 changed files with 477 additions and 302 deletions
+2 -2
View File
@@ -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<double>::digits10 + 1) << value_;
ss << std::setprecision(std::numeric_limits<double>::digits10 + 1) << value();
return ss.str();
}
template struct IFC_GEOM_API IfcGeom::OpaqueCoordinate<3>;
template struct IFC_GEOM_API IfcGeom::OpaqueCoordinate<4>;
template struct IFC_GEOM_API IfcGeom::OpaqueCoordinate<4>;
+337 -147
View File
@@ -24,8 +24,18 @@
#include "../ifcgeom/ConversionSettings.h"
#include "../ifcgeom/taxonomy.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef>
#include <iomanip>
#include <limits>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <vector>
#include <unordered_map>
@@ -73,181 +83,361 @@ namespace IfcGeom {
class IFC_GEOM_API Triangulation;
}
template <typename T>
constexpr T add_(T a, T b) {
return a + b;
}
template <typename T>
constexpr T subtract_(T a, T b) {
return a - b;
}
template <typename T>
constexpr T multiply_(T a, T b) {
return a * b;
}
template <typename T>
constexpr T divide_(T a, T b) {
return a / b;
}
template <typename T>
constexpr bool equals_(T a, T b) {
return a == b;
}
template <typename T>
constexpr bool less_than_(T a, T b) {
return a < b;
}
template <typename T>
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<const NumberConcept> add(const NumberConcept& other) const = 0;
virtual std::shared_ptr<const NumberConcept> subtract(const NumberConcept& other) const = 0;
virtual std::shared_ptr<const NumberConcept> multiply(const NumberConcept& other) const = 0;
virtual std::shared_ptr<const NumberConcept> divide(const NumberConcept& other) const = 0;
virtual std::shared_ptr<const NumberConcept> negate() const = 0;
virtual std::shared_ptr<const NumberConcept> 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 <typename T>
struct NumberModel : NumberConcept {
T value;
NumberModel(const T& v)
: value(v) {}
static const NumberModel& as_same(const NumberConcept& other) {
auto same = dynamic_cast<const NumberModel*>(&other);
if (same == nullptr) {
throw std::runtime_error("Incompatible opaque number types");
}
return *same;
}
template <typename U>
static auto stream_exact(std::ostream& os, const U& v, int) -> decltype(os << v.exact(), void()) {
os << v.exact();
}
template <typename U>
static void stream_exact(std::ostream& os, const U& v, long) {
if constexpr (std::is_floating_point<U>::value) {
os << std::setprecision(std::numeric_limits<U>::digits10 + 1);
}
os << v;
}
virtual double to_double() const {
return static_cast<double>(value);
}
virtual std::string to_string() const {
std::stringstream ss;
stream_exact(ss, value, 0);
return ss.str();
}
virtual std::shared_ptr<const NumberConcept> add(const NumberConcept& other) const {
return std::make_shared<NumberModel>(value + as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> subtract(const NumberConcept& other) const {
return std::make_shared<NumberModel>(value - as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> multiply(const NumberConcept& other) const {
return std::make_shared<NumberModel>(value * as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> divide(const NumberConcept& other) const {
return std::make_shared<NumberModel>(value / as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> negate() const {
return std::make_shared<NumberModel>(-value);
}
virtual std::shared_ptr<const NumberConcept> from_double(double v) const {
return std::make_shared<NumberModel>(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 <typename T>
struct is_shared_ptr : std::false_type {};
template <typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
private:
std::shared_ptr<const NumberConcept> data_;
const NumberConcept& data() const {
if (!data_) {
throw std::runtime_error("Empty opaque number");
}
return *data_;
}
protected:
OpaqueNumber(std::shared_ptr<const NumberConcept> 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<T>,
typename = std::enable_if_t<!std::is_base_of<OpaqueNumber, Decayed>::value && !is_shared_ptr<Decayed>::value>>
explicit OpaqueNumber(T&& value)
: data_(std::make_shared<NumberModel<Decayed>>(std::forward<T>(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 <typename T>
const T& value_as() const {
if (data().type() != typeid(T)) {
throw std::runtime_error("Unexpected opaque number type");
}
return *static_cast<const T*>(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 <double (*Fn)(double, double)>
OpaqueNumber* binary_op(OpaqueNumber* other) const {
auto nnd = dynamic_cast<NumberNativeDouble*>(other);
if (nnd) {
return new NumberNativeDouble(Fn(value_, nnd->value_));
} else {
return nullptr;
}
}
template <bool(*Fn)(double, double)>
bool binary_op_bool(OpaqueNumber* other) const {
auto nnd = dynamic_cast<NumberNativeDouble*>(other);
if (nnd) {
return Fn(value_, nnd->value_);
} else {
return false;
}
}
template <double(*Fn)(double)>
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<double>();
}
virtual std::string to_string() const;
virtual OpaqueNumber* operator+(OpaqueNumber* other) const {
return binary_op<add_<double>>(other);
}
virtual OpaqueNumber* operator-(OpaqueNumber* other) const {
return binary_op<subtract_<double>>(other);
}
virtual OpaqueNumber* operator*(OpaqueNumber* other) const {
return binary_op<multiply_<double>>(other);
}
virtual OpaqueNumber* operator/(OpaqueNumber* other) const {
return binary_op<divide_<double>>(other);
}
virtual bool operator==(OpaqueNumber* other) const {
return binary_op_bool<equals_<double>>(other);
}
virtual bool operator<(OpaqueNumber* other) const {
return binary_op_bool<less_than_<double>>(other);
}
virtual OpaqueNumber* operator-() const {
return unary_op<negate_<double>>();
}
virtual OpaqueNumber* clone() const {
return new NumberNativeDouble(value_);
}
std::string to_string() const;
};
template <size_t N>
struct IFC_GEOM_API OpaqueCoordinate {
private:
std::array<OpaqueNumber*, N> values;
std::array<OpaqueNumber, N> values_;
static void copy_(std::array<OpaqueNumber*, N>& dest, const std::array<OpaqueNumber*, N>& 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 <typename... Args>
OpaqueCoordinate(Args... args) {
static_assert(sizeof...(args) == N, "Incorrect number of arguments provided");
init_<0>(args...);
#ifndef SWIG
template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == N>>
OpaqueCoordinate(Args&&... args) {
init_<0>(std::forward<Args>(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<double> to_doubles() const {
std::vector<double> 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 <size_t Index, typename... Args>
void init_(OpaqueNumber* value, Args... args) {
values[Index] = value;
template <size_t Index, typename Arg, typename... Args>
void init_(Arg&& value, Args&&... args) {
values_[Index] = as_number(std::forward<Arg>(value));
if constexpr (Index + 1 < N) {
init_<Index + 1>(args...);
init_<Index + 1>(std::forward<Args>(args)...);
}
}
};
@@ -271,9 +461,9 @@ namespace IfcGeom {
virtual std::pair<OpaqueCoordinate<3>, 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;
+2 -2
View File
@@ -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;
}
@@ -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<NumberEpeck*>(p.get(0))->value(),
static_cast<NumberEpeck*>(p.get(1))->value(),
static_cast<NumberEpeck*>(p.get(2))->value(),
static_cast<NumberEpeck*>(p.get(3))->value()
p.get(0).value_as<CGAL::Epeck::FT>(),
p.get(1).value_as<CGAL::Epeck::FT>(),
p.get(2).value_as<CGAL::Epeck::FT>(),
p.get(3).value_as<CGAL::Epeck::FT>()
);
#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<Kernel_>(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");
+68 -74
View File
@@ -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 <CGAL::Epeck::FT(*Fn)(CGAL::Epeck::FT, CGAL::Epeck::FT)>
OpaqueNumber* binary_op(OpaqueNumber* other) const {
auto nnd = dynamic_cast<NumberEpeck*>(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<const Model*>(&other);
if (same == nullptr) {
throw std::runtime_error("Incompatible opaque number types");
}
return *same;
}
}
template <bool(*Fn)(CGAL::Epeck::FT, CGAL::Epeck::FT)>
bool binary_op_bool(OpaqueNumber* other) const {
auto nnd = dynamic_cast<NumberEpeck*>(other);
if (nnd) {
return Fn(value_, nnd->value_);
} else {
return false;
virtual double to_double() const {
return CGAL::to_double(value);
}
}
template <CGAL::Epeck::FT(*Fn)(CGAL::Epeck::FT)>
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<const NumberConcept> add(const NumberConcept& other) const {
return std::make_shared<Model>(value + as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> subtract(const NumberConcept& other) const {
return std::make_shared<Model>(value - as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> multiply(const NumberConcept& other) const {
return std::make_shared<Model>(value * as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> divide(const NumberConcept& other) const {
return std::make_shared<Model>(value / as_same(other).value);
}
virtual std::shared_ptr<const NumberConcept> negate() const {
return std::make_shared<Model>(-value);
}
virtual std::shared_ptr<const NumberConcept> from_double(double v) const {
return std::make_shared<Model>(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<Model>(v)) {}
const CGAL::Epeck::FT& value() const {
return value_;
}
virtual OpaqueNumber* operator+(OpaqueNumber* other) const {
return binary_op<add_<CGAL::Epeck::FT>>(other);
}
virtual OpaqueNumber* operator-(OpaqueNumber* other) const {
return binary_op<subtract_<CGAL::Epeck::FT>>(other);
}
virtual OpaqueNumber* operator*(OpaqueNumber* other) const {
return binary_op<multiply_<CGAL::Epeck::FT>>(other);
}
virtual OpaqueNumber* operator/(OpaqueNumber* other) const {
return binary_op<divide_<CGAL::Epeck::FT>>(other);
}
virtual bool operator==(OpaqueNumber* other) const {
return binary_op_bool<equals_<CGAL::Epeck::FT>>(other);
}
virtual bool operator<(OpaqueNumber* other) const {
return binary_op_bool<less_than_<CGAL::Epeck::FT>>(other);
}
virtual OpaqueNumber* operator-() const {
return unary_op<negate_<CGAL::Epeck::FT>>();
}
virtual OpaqueNumber* clone() const {
return new NumberEpeck(value_);
return value_as<CGAL::Epeck::FT>();
}
};
#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>, 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>, 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();
@@ -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 <Geom_Plane.hxx>
@@ -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)
);
}
}
@@ -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>, 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();
+6 -15
View File
@@ -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 <typename T>
@@ -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));
}
%}