Skip to content

Commit 809668c

Browse files
committed
Major update to halfspace algorithm, conversion result shape analysis
1 parent 559de7d commit 809668c

21 files changed

+1385
-133
lines changed

src/ifcconvert/validation_utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ struct intersection_validator {
476476
std::wcout << sss.c_str() << std::endl;
477477

478478
for (auto& g : geom_object->geometry()) {
479-
auto s = ((ifcopenshell::geometry::CgalShape*) g.Shape())->shape();
479+
cgal_shape_t s = *std::static_pointer_cast<ifcopenshell::geometry::CgalShape>(g.Shape());
480480
const auto& m = g.Placement()->ccomponents();
481481
const auto& n = geom_object->transformation().data()->ccomponents();
482482

src/ifcgeom/ConversionResult.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "ConversionResult.h"
2+
#include "IfcGeomRepresentation.h"
3+
4+
IfcGeom::Representation::Triangulation * IfcGeom::ConversionResultShape::Triangulate(const IfcGeom::IteratorSettings & settings) const
5+
{
6+
auto t = IfcGeom::Representation::Triangulation::empty(settings);
7+
static ifcopenshell::geometry::taxonomy::matrix4 iden;
8+
Triangulate(settings, iden, t, -1);
9+
return t;
10+
}

src/ifcgeom/ConversionResult.h

Lines changed: 185 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "../ifcgeom/IteratorSettings.h"
2525
#include "../ifcgeom/taxonomy.h"
2626

27+
#include <memory>
2728
#include <vector>
2829

2930
namespace IfcGeom {
@@ -32,26 +33,203 @@ namespace IfcGeom {
3233
class IFC_GEOM_API Triangulation;
3334
}
3435

35-
class IFC_GEOM_API ConversionResultShape {
36+
template <typename T>
37+
constexpr T add_(T a, T b) {
38+
return a + b;
39+
}
40+
41+
template <typename T>
42+
constexpr T subtract_(T a, T b) {
43+
return a - b;
44+
}
45+
46+
template <typename T>
47+
constexpr T multiply_(T a, T b) {
48+
return a * b;
49+
}
50+
51+
template <typename T>
52+
constexpr T divide_(T a, T b) {
53+
return a / b;
54+
}
55+
56+
template <typename T>
57+
constexpr bool equals_(T a, T b) {
58+
return a == b;
59+
}
60+
61+
template <typename T>
62+
constexpr bool less_than_(T a, T b) {
63+
return a < b;
64+
}
65+
66+
template <typename T>
67+
constexpr T negate_(T a) {
68+
return -a;
69+
}
70+
71+
class IFC_GEOM_API OpaqueNumber {
3672
public:
37-
virtual void Triangulate(const IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int surface_style_id) const = 0;
73+
virtual double to_double() const = 0;
74+
virtual ~OpaqueNumber() {}
75+
76+
virtual OpaqueNumber* operator+(OpaqueNumber* other) const = 0;
77+
virtual OpaqueNumber* operator-(OpaqueNumber* other) const = 0;
78+
virtual OpaqueNumber* operator*(OpaqueNumber* other) const = 0;
79+
virtual OpaqueNumber* operator/(OpaqueNumber* other) const = 0;
80+
virtual bool operator==(OpaqueNumber* other) const = 0;
81+
virtual bool operator<(OpaqueNumber* other) const = 0;
82+
virtual OpaqueNumber* operator-() const = 0;
83+
};
84+
85+
// @todo this can simply be a template class, to remove the need for the NumberEpeck in CGAL kernel.
86+
class IFC_GEOM_API NumberNativeDouble : public OpaqueNumber {
87+
private:
88+
double value_;
89+
90+
template <double (*Fn)(double, double)>
91+
OpaqueNumber* binary_op(OpaqueNumber* other) const {
92+
auto nnd = dynamic_cast<NumberNativeDouble*>(other);
93+
if (nnd) {
94+
return new NumberNativeDouble(Fn(value_, nnd->value_));
95+
} else {
96+
return nullptr;
97+
}
98+
}
99+
100+
template <bool(*Fn)(double, double)>
101+
bool binary_op_bool(OpaqueNumber* other) const {
102+
auto nnd = dynamic_cast<NumberNativeDouble*>(other);
103+
if (nnd) {
104+
return new NumberNativeDouble(Fn(value_, nnd->value_));
105+
} else {
106+
return nullptr;
107+
}
108+
}
109+
110+
template <double(*Fn)(double)>
111+
OpaqueNumber* unary_op() const {
112+
return new NumberNativeDouble(Fn(value_));
113+
}
114+
public:
115+
NumberNativeDouble(double v)
116+
: value_(v) {}
117+
118+
virtual double to_double() const {
119+
return value_;
120+
}
121+
122+
virtual OpaqueNumber* operator+(OpaqueNumber* other) const {
123+
return binary_op<add_<double>>(other);
124+
}
38125

126+
virtual OpaqueNumber* operator-(OpaqueNumber* other) const {
127+
return binary_op<subtract_<double>>(other);
128+
}
129+
virtual OpaqueNumber* operator*(OpaqueNumber* other) const {
130+
return binary_op<multiply_<double>>(other);
131+
}
132+
virtual OpaqueNumber* operator/(OpaqueNumber* other) const {
133+
return binary_op<divide_<double>>(other);
134+
}
135+
virtual bool operator==(OpaqueNumber* other) const {
136+
return binary_op_bool<equals_<double>>(other);
137+
}
138+
virtual bool operator<(OpaqueNumber* other) const {
139+
return binary_op_bool<less_than_<double>>(other);
140+
}
141+
virtual OpaqueNumber* operator-() const {
142+
return unary_op<negate_<double>>();
143+
}
144+
};
145+
146+
template <size_t N>
147+
struct IFC_GEOM_API OpaqueCoordinate {
148+
std::array<std::shared_ptr<OpaqueNumber>, N> values;
149+
150+
template <typename... Args>
151+
OpaqueCoordinate(Args... args) {
152+
static_assert(sizeof...(args) == N, "Incorrect number of arguments provided");
153+
init_<0>(args...);
154+
}
155+
156+
OpaqueCoordinate() {
157+
for (auto it = values.begin(); it != values.end(); ++it) {
158+
*it = nullptr;
159+
}
160+
}
161+
162+
std::shared_ptr<OpaqueNumber> get(size_t i) {
163+
if (i >= N) {
164+
return nullptr;
165+
}
166+
return values[i];
167+
}
168+
169+
void set(size_t i, std::shared_ptr<OpaqueNumber> n) {
170+
if (i < N) {
171+
values[i] = n;
172+
}
173+
}
174+
private:
175+
template <size_t Index, typename... Args>
176+
void init_(std::shared_ptr<OpaqueNumber> value, Args... args) {
177+
values[Index] = value;
178+
if constexpr (Index + 1 < N) {
179+
init_<Index + 1>(args...);
180+
}
181+
}
182+
};
183+
184+
class IFC_GEOM_API ConversionResultShape {
185+
public:
186+
virtual void Triangulate(const IfcGeom::IteratorSettings& settings, const ifcopenshell::geometry::taxonomy::matrix4& place, Representation::Triangulation* t, int surface_style_id) const = 0;
187+
IfcGeom::Representation::Triangulation* Triangulate(const IfcGeom::IteratorSettings& settings) const;
39188
virtual void Serialize(const ifcopenshell::geometry::taxonomy::matrix4& place, std::string&) const = 0;
40-
virtual ConversionResultShape* clone() const = 0;
189+
41190
virtual int surface_genus() const = 0;
42191
virtual bool is_manifold() const = 0;
43-
// @todo this must be something with a virtual dtor so that we can delete it.
44-
virtual double bounding_box(void*& b) const = 0;
192+
45193
virtual int num_vertices() const = 0;
194+
virtual int num_edges() const = 0;
195+
virtual int num_faces() const = 0;
196+
197+
// @todo choose one prototype
198+
virtual double bounding_box(void*&) const = 0;
199+
// @todo this must be something with a virtual dtor so that we can delete it.
200+
virtual std::pair<OpaqueCoordinate<3>, OpaqueCoordinate<3>> bounding_box() const = 0;
46201
virtual void set_box(void* b) = 0;
202+
203+
virtual std::shared_ptr<OpaqueNumber> length() = 0;
204+
virtual std::shared_ptr<OpaqueNumber> area() = 0;
205+
virtual std::shared_ptr<OpaqueNumber> volume() = 0;
206+
207+
virtual OpaqueCoordinate<3> position() = 0;
208+
virtual OpaqueCoordinate<3> axis() = 0;
209+
virtual OpaqueCoordinate<4> plane_equation() = 0;
210+
211+
virtual std::vector<ConversionResultShape*> convex_decomposition() = 0;
212+
virtual ConversionResultShape* halfspaces() = 0;
213+
virtual ConversionResultShape* box() = 0;
214+
virtual ConversionResultShape* solid() = 0;
215+
virtual std::vector<ConversionResultShape*> edges() = 0;
216+
virtual std::vector<ConversionResultShape*> facets() = 0;
217+
218+
virtual ConversionResultShape* add(ConversionResultShape*) = 0;
219+
virtual ConversionResultShape* subtract(ConversionResultShape*) = 0;
220+
virtual ConversionResultShape* intersect(ConversionResultShape*) = 0;
221+
222+
virtual void map(OpaqueCoordinate<4>& from, OpaqueCoordinate<4>& to) = 0;
223+
virtual ConversionResultShape* moved(ifcopenshell::geometry::taxonomy::matrix4::ptr) const = 0;
224+
47225
virtual ~ConversionResultShape() {}
48226
};
49227

50228
class IFC_GEOM_API ConversionResult {
51229
private:
52230
int id;
53231
ifcopenshell::geometry::taxonomy::matrix4::ptr placement_;
54-
ConversionResultShape* shape_;
232+
std::shared_ptr<ConversionResultShape> shape_;
55233
ifcopenshell::geometry::taxonomy::style::ptr style_;
56234
public:
57235
ConversionResult(int id, ifcopenshell::geometry::taxonomy::matrix4::ptr placement, ConversionResultShape* shape, ifcopenshell::geometry::taxonomy::style::ptr style)
@@ -74,7 +252,7 @@ namespace IfcGeom {
74252
// @todo verify order
75253
placement_->components() = trsf->ccomponents() * placement_->ccomponents();
76254
}
77-
ConversionResultShape* Shape() const { return shape_; }
255+
std::shared_ptr<ConversionResultShape> Shape() const { return shape_; }
78256
ifcopenshell::geometry::taxonomy::matrix4::ptr Placement() const { return placement_; }
79257
bool hasStyle() const { return !!style_; }
80258
const ifcopenshell::geometry::taxonomy::style& Style() const { return *style_; }

src/ifcgeom/IfcGeomRepresentation.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ IfcGeom::Representation::Serialization::Serialization(const BRep& brep)
171171
}
172172

173173
if (brep.begin() != brep.end()) {
174-
if (dynamic_cast<ifcopenshell::geometry::OpenCascadeShape*>(brep.begin()->Shape())) {
174+
if (std::dynamic_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(brep.begin()->Shape())) {
175175
ConversionResultShape* shape = brep.as_compound();
176176
ifcopenshell::geometry::taxonomy::matrix4 identity;
177177
shape->Serialize(identity, brep_data_);
@@ -198,7 +198,7 @@ IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::as_compound(bool
198198
builder.MakeCompound(compound);
199199

200200
for (auto it = begin(); it != end(); ++it) {
201-
const TopoDS_Shape& s = *(ifcopenshell::geometry::OpenCascadeShape*)it->Shape();
201+
const TopoDS_Shape& s = *std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape());
202202

203203
// @todo, check
204204
gp_GTrsf trsf;
@@ -237,7 +237,7 @@ bool IfcGeom::Representation::BRep::calculate_surface_area(double& area) const {
237237

238238
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
239239
GProp_GProps prop;
240-
BRepGProp::SurfaceProperties(*(ifcopenshell::geometry::OpenCascadeShape*)it->Shape(), prop);
240+
BRepGProp::SurfaceProperties(*std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape()), prop);
241241
area += prop.Mass();
242242
}
243243

@@ -257,9 +257,9 @@ bool IfcGeom::Representation::BRep::calculate_volume(double& volume) const {
257257
volume = 0.;
258258

259259
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
260-
if (util::is_manifold(*(ifcopenshell::geometry::OpenCascadeShape*)it->Shape())) {
260+
if (util::is_manifold(*std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape()))) {
261261
GProp_GProps prop;
262-
BRepGProp::VolumeProperties(*(ifcopenshell::geometry::OpenCascadeShape*)it->Shape(), prop);
262+
BRepGProp::VolumeProperties(*std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape()), prop);
263263
volume += prop.Mass();
264264
} else {
265265
return false;
@@ -299,9 +299,9 @@ bool IfcGeom::Representation::BRep::calculate_projected_surface_area(const ifcop
299299

300300
for (IfcGeom::ConversionResults::const_iterator it = begin(); it != end(); ++it) {
301301
double x, y, z;
302-
surface_area_along_direction(settings().deflection_tolerance(), *(ifcopenshell::geometry::OpenCascadeShape*)it->Shape(), ax, x, y, z);
302+
surface_area_along_direction(settings().deflection_tolerance(), *std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape()), ax, x, y, z);
303303

304-
if (util::is_manifold(*(ifcopenshell::geometry::OpenCascadeShape*)it->Shape())) {
304+
if (util::is_manifold(*std::static_pointer_cast<ifcopenshell::geometry::OpenCascadeShape>(it->Shape()))) {
305305
x /= 2.;
306306
y /= 2.;
307307
z /= 2.;
@@ -414,3 +414,11 @@ void IfcGeom::Representation::Triangulation::addEdge(int n1, int n2, std::map<st
414414
else edgecount[e] ++;
415415
edges_temp.push_back(e);
416416
}
417+
418+
const IfcGeom::ConversionResultShape* IfcGeom::Representation::BRep::item(int i) const {
419+
if (i >= 0 && i < shapes_.size()) {
420+
return shapes_[i].Shape()->moved(shapes_[i].Placement());
421+
} else {
422+
return nullptr;
423+
}
424+
}

src/ifcgeom/IfcGeomRepresentation.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ namespace IfcGeom {
6464
bool calculate_volume(double&) const;
6565
bool calculate_surface_area(double&) const;
6666
bool calculate_projected_surface_area(const ifcopenshell::geometry::taxonomy::matrix4& ax, double& along_x, double& along_y, double& along_z) const;
67+
68+
int size() const { return shapes_.size(); }
69+
const IfcGeom::ConversionResultShape* item(int i) const;
6770
};
6871

6972
class IFC_GEOM_API Serialization : public Representation {
@@ -105,6 +108,11 @@ namespace IfcGeom {
105108
size_t weld_offset_;
106109
VertexKeyMap welds;
107110

111+
Triangulation(IfcGeom::IteratorSettings settings)
112+
: Representation(IfcGeom::ElementSettings{ settings, 1., "" })
113+
, weld_offset_(0)
114+
{}
115+
108116
public:
109117
const std::string& id() const { return id_; }
110118
const std::vector<double>& verts() const { return _verts; }
@@ -146,6 +154,8 @@ namespace IfcGeom {
146154
/// @todo Very simple impl. Assumes that input vertices and normals match 1:1.
147155
static std::vector<double> box_project_uvs(const std::vector<double> &vertices, const std::vector<double> &normals);
148156

157+
static Triangulation* empty(IfcGeom::IteratorSettings settings) { return new Triangulation(settings); }
158+
149159
/// Welds vertices that belong to different faces
150160
int addVertex(int material_index, double X, double Y, double Z);
151161

0 commit comments

Comments
 (0)