Files
IfcOpenShell/src/ifcgeom/taxonomy.h
T

294 lines
7.9 KiB
C++
Raw Normal View History

2019-08-16 17:40:13 +02:00
#ifndef TAXONOMY_H
#define TAXONOMY_H
#include "../ifcparse/IfcBaseClass.h"
2019-08-04 09:36:31 +02:00
#include <boost/variant.hpp>
2019-08-16 17:40:13 +02:00
#include <Eigen/Dense>
#include <map>
#include <string>
#include <tuple>
2019-08-04 11:27:10 +02:00
#include <exception>
2019-08-16 17:40:13 +02:00
#include <cstdalign>
2019-08-04 11:27:10 +02:00
2019-08-04 09:36:31 +02:00
namespace ifcopenshell {
namespace geometry {
namespace taxonomy {
2019-08-24 18:32:30 +02:00
class topology_error : public std::runtime_error {
public:
topology_error() : std::runtime_error("Generic topology error") {}
2019-09-15 15:59:05 +02:00
topology_error(const char* const s) : std::runtime_error(s) {}
2019-08-24 18:32:30 +02:00
};
2019-09-18 16:35:26 +02:00
enum kinds { MATRIX4, POINT3, DIRECTION3, LINE, CIRCLE, ELLIPSE, BSPLINE_CURVE, PLANE, EDGE, LOOP, FACE, SHELL, EXTRUSION, NODE, COLLECTION, BOOLEAN_RESULT, COLOUR, STYLE };
2019-08-16 17:40:13 +02:00
2019-08-04 09:36:31 +02:00
struct item {
2019-08-16 17:40:13 +02:00
const IfcUtil::IfcBaseClass* instance;
2019-08-04 09:36:31 +02:00
virtual item* clone() const = 0;
2019-08-16 17:40:13 +02:00
virtual kinds kind() const = 0;
2019-08-24 18:32:30 +02:00
virtual void reverse() { throw taxonomy::topology_error(); }
2019-08-04 11:27:10 +02:00
2019-08-16 17:40:13 +02:00
item(const IfcUtil::IfcBaseClass* instance = nullptr) : instance(instance) {}
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
2019-08-04 09:36:31 +02:00
};
struct matrix4 : public item {
enum tag_t {
IDENTITY, AFFINE_WO_SCALE, AFFINE_W_UNIFORM_SCALE, AFFINE_W_NONUNIFORM_SCALE, OTHER
};
tag_t tag;
2019-08-16 17:40:13 +02:00
Eigen::Matrix4d components;
2019-09-01 10:36:49 +02:00
matrix4() : components(Eigen::Matrix4d::Identity()), tag(IDENTITY) {}
2019-08-18 14:31:22 +02:00
matrix4(const Eigen::Matrix4d& c) : components(c), tag(OTHER) {}
2019-09-01 10:36:49 +02:00
matrix4(const Eigen::Vector3d& o, const Eigen::Vector3d& z, const Eigen::Vector3d& x) : tag(AFFINE_WO_SCALE) {
auto X = x.normalized();
auto Y = z.cross(x).normalized();
auto Z = z.normalized();
components <<
X(0), Y(0), Z(0), o(0),
2019-09-01 13:36:46 +02:00
X(1), Y(1), Z(1), o(1),
X(2), Y(2), Z(2), o(2),
2019-09-01 10:36:49 +02:00
0, 0, 0, 1.;
}
2019-08-04 09:36:31 +02:00
virtual item* clone() const { return new matrix4(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return MATRIX4; }
};
struct colour : public item {
Eigen::Vector3d components;
virtual item* clone() const { return new colour(*this); }
virtual kinds kind() const { return COLOUR; }
colour() : components(Eigen::Vector3d::Zero()) {}
colour(double r, double g, double b) { components << r, g, b; }
const double& r() const { return components[0]; }
const double& g() const { return components[1]; }
const double& b() const { return components[2]; }
};
struct style : public item {
// @todo this is not very efficient wrt alignment
boost::optional<std::string> name;
boost::optional<colour> diffuse;
boost::optional<colour> specular;
boost::optional<double> specularity, transparency;
virtual item* clone() const { return new style(*this); }
virtual kinds kind() const { return STYLE; }
// @todo equality implementation based on values?
bool operator==(const style& other) const { return instance == other.instance; }
style() {}
style(const std::string& name) : name(name) {}
2019-08-04 09:36:31 +02:00
};
struct geom_item : public item {
2019-08-16 17:40:13 +02:00
style surface_style;
2019-08-04 09:36:31 +02:00
matrix4 matrix;
2019-09-16 19:30:11 +02:00
boost::optional<bool> orientation;
2019-08-04 11:27:10 +02:00
2019-08-16 17:40:13 +02:00
geom_item(const IfcUtil::IfcBaseClass* instance = nullptr) : item(instance) {}
geom_item(const IfcUtil::IfcBaseClass* instance, matrix4 m) : item(instance), matrix(m) {}
2019-08-18 15:53:26 +02:00
geom_item(matrix4 m) : matrix(m) {}
2019-08-04 09:36:31 +02:00
};
template <size_t N>
2019-08-04 11:27:10 +02:00
struct cartesian_base : public geom_item {
2019-08-16 17:40:13 +02:00
Eigen::Vector3d components;
2019-08-04 11:27:10 +02:00
2019-08-16 17:40:13 +02:00
cartesian_base() : components(Eigen::Vector3d::Zero()) {}
cartesian_base(double x, double y, double z = 0.) { components << x, y, z; }
2019-08-04 09:36:31 +02:00
};
struct point3 : public cartesian_base<3> {
virtual item* clone() const { return new point3(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return POINT3; }
2019-08-04 11:27:10 +02:00
2019-08-24 18:32:30 +02:00
point3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {}
2019-08-04 09:36:31 +02:00
};
struct direction3 : public cartesian_base<3> {
virtual item* clone() const { return new direction3(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return DIRECTION3; }
2019-08-04 11:27:10 +02:00
2019-08-24 18:32:30 +02:00
direction3(double x = 0., double y = 0., double z = 0.) : cartesian_base(x, y, z) {}
2019-08-04 09:36:31 +02:00
};
2019-08-26 17:19:06 +02:00
struct curve : public geom_item {};
struct line : public curve {
2019-08-04 09:36:31 +02:00
virtual item* clone() const { return new line(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return LINE; }
2019-08-04 09:36:31 +02:00
};
2019-08-26 17:19:06 +02:00
struct circle : public curve {
double radius;
2019-08-04 09:36:31 +02:00
virtual item* clone() const { return new circle(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return CIRCLE; }
2019-08-04 09:36:31 +02:00
};
2019-08-26 17:19:06 +02:00
struct ellipse : public circle {
double radius2;
2019-08-04 09:36:31 +02:00
virtual item* clone() const { return new ellipse(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return ELLIPSE; }
2019-08-04 09:36:31 +02:00
};
2019-08-26 17:19:06 +02:00
struct bspline_curve : public curve {
virtual item* clone() const { return new bspline_curve(*this); }
virtual kinds kind() const { return BSPLINE_CURVE; }
2019-08-04 09:36:31 +02:00
};
2019-08-26 17:19:06 +02:00
struct trimmed_curve : public curve {
2020-04-29 10:06:23 +02:00
// @todo The copy constructor of point3 within the variant fails on the avx instruction
// on the default gcc in Ubuntu 18.04 and a recent AMD Ryzen. Probably due to allignment.
2019-08-04 09:36:31 +02:00
boost::variant<point3, double> start, end;
2020-04-29 10:06:23 +02:00
2019-08-26 17:19:06 +02:00
// @todo somehow account for the fact that curve in IFC can be trimmed curve, polyline and composite curve as well.
2019-09-16 19:30:11 +02:00
item* basis;
2019-08-24 18:32:30 +02:00
bool orientation;
2019-08-04 09:36:31 +02:00
2019-08-26 17:19:06 +02:00
trimmed_curve() : basis(nullptr), orientation(true) {}
2019-08-24 18:32:30 +02:00
virtual void reverse() {
2020-03-30 14:31:59 +02:00
// std::swap(start, end);
2019-08-24 18:32:30 +02:00
orientation = !orientation;
}
2019-08-04 09:36:31 +02:00
};
2019-08-26 17:19:06 +02:00
struct edge : public trimmed_curve {
// @todo how to express similarity between trimmed_curve and edge?
virtual item* clone() const { return new edge(*this); }
virtual kinds kind() const { return EDGE; }
};
2019-08-24 18:32:30 +02:00
struct collection : public geom_item {
std::vector<item*> children;
2019-08-04 09:36:31 +02:00
2019-08-26 17:19:06 +02:00
template <typename T>
std::vector<T*> children_as() const {
std::vector<T*> ts;
ts.reserve(children.size());
std::for_each(children.begin(), children.end(), [&ts](item* i){
auto v = dynamic_cast<T*>(i);
if (v) {
ts.push_back(v);
}
});
return ts;
}
2019-08-24 18:32:30 +02:00
virtual item* clone() const { return new collection(*this); }
virtual kinds kind() const { return COLLECTION; }
virtual void reverse() {
std::reverse(children.begin(), children.end());
for (auto& child : children) {
child->reverse();
}
}
2019-08-04 09:36:31 +02:00
};
2019-08-24 18:32:30 +02:00
struct shell : public collection {
2019-08-28 09:54:20 +02:00
boost::optional<bool> closed;
2019-08-24 18:32:30 +02:00
virtual item* clone() const { return new shell(*this); }
virtual kinds kind() const { return SHELL; }
};
2019-08-04 09:36:31 +02:00
2019-09-18 16:35:26 +02:00
struct surface : public geom_item {};
struct plane : public surface {
virtual item* clone() const { return new plane(*this); }
virtual kinds kind() const { return PLANE; }
};
2019-08-24 18:32:30 +02:00
struct face : public collection {
2019-09-18 16:35:26 +02:00
item* basis;
2019-08-04 09:36:31 +02:00
virtual item* clone() const { return new face(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return FACE; }
2019-08-24 18:32:30 +02:00
};
2019-08-04 11:27:10 +02:00
2019-08-24 18:32:30 +02:00
struct loop : public collection {
2019-09-16 19:30:11 +02:00
boost::optional<bool> external, closed;
2019-08-26 17:19:06 +02:00
2019-08-24 18:32:30 +02:00
virtual item* clone() const { return new loop(*this); }
virtual kinds kind() const { return LOOP; }
2019-08-04 09:36:31 +02:00
};
2019-08-04 11:27:10 +02:00
struct sweep : public geom_item {
2019-08-24 18:32:30 +02:00
face basis;
2019-08-04 11:27:10 +02:00
2019-08-18 15:53:26 +02:00
sweep(face b) : basis(b) {}
sweep(matrix4 m, face b) : geom_item(m), basis(b) {}
2019-08-04 09:36:31 +02:00
};
struct extrusion : public sweep {
2019-08-24 18:32:30 +02:00
direction3 direction;
double depth;
2019-08-04 09:36:31 +02:00
virtual item* clone() const { return new extrusion(*this); }
2019-08-16 17:40:13 +02:00
virtual kinds kind() const { return EXTRUSION; }
2019-08-18 15:53:26 +02:00
extrusion(matrix4 m, face basis, direction3 dir, double d) : sweep(m, basis), direction(dir), depth(d) {}
};
2019-09-18 16:35:26 +02:00
struct node : public collection {
2019-08-16 17:40:13 +02:00
std::map<std::string, geom_item*> representations;
virtual item* clone() const { return new node(*this); }
virtual kinds kind() const { return NODE; }
};
2019-08-04 11:27:10 +02:00
2019-09-18 16:35:26 +02:00
struct boolean_result : public collection {
enum operation_t {
UNION, SUBTRACTION, INTERSECTION
};
virtual item* clone() const { return new boolean_result(*this); }
virtual kinds kind() const { return BOOLEAN_RESULT; }
operation_t operation;
};
2019-08-16 17:40:13 +02:00
namespace impl {
2019-09-18 16:35:26 +02:00
typedef std::tuple<matrix4, point3, direction3, line, circle, ellipse, bspline_curve, edge, plane, loop, face, shell, extrusion, node, collection, boolean_result> KindsTuple;
2019-09-15 15:59:05 +02:00
typedef std::tuple<line, circle, ellipse, bspline_curve, loop, edge> CurvesTuple;
2019-08-16 17:40:13 +02:00
}
struct type_by_kind {
template <std::size_t N>
using type = typename std::tuple_element<N, impl::KindsTuple>::type;
static const size_t max = std::tuple_size< impl::KindsTuple>::value;
};
2019-08-26 17:19:06 +02:00
struct curves {
template <std::size_t N>
using type = typename std::tuple_element<N, impl::CurvesTuple>::type;
static const size_t max = std::tuple_size< impl::CurvesTuple>::value;
};
2019-08-04 09:36:31 +02:00
}
2019-08-04 11:27:10 +02:00
2019-08-04 09:36:31 +02:00
}
}
2019-08-16 17:40:13 +02:00
#endif