-
-
Notifications
You must be signed in to change notification settings - Fork 901
Expand file tree
/
Copy pathtaxonomy.h
More file actions
1755 lines (1456 loc) · 52.8 KB
/
taxonomy.h
File metadata and controls
1755 lines (1456 loc) · 52.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef TAXONOMY_H
#define TAXONOMY_H
#include "../ifcparse/IfcBaseClass.h"
#include "../ifcparse/IfcLogger.h"
#include "ConversionSettings.h"
#include <boost/variant.hpp>
#include <boost/functional/hash.hpp>
#include <boost/math/constants/constants.hpp>
#include <Eigen/Dense>
#include <map>
#include <string>
#include <tuple>
#include <exception>
#include <numeric>
#ifndef TAXONOMY_USE_UNIQUE_PTR
#ifndef TAXONOMY_USE_NAKED_PTR
#define TAXONOMY_USE_SHARED_PTR
#endif
#endif
#ifdef TAXONOMY_USE_SHARED_PTR
#include <memory>
#endif
// @todo don't do std::less but use hashing and cache hash values.
namespace boost { inline std::size_t hash_value(const blank&) { return 0; } }
namespace ifcopenshell {
namespace geometry {
namespace taxonomy {
#ifdef TAXONOMY_USE_SHARED_PTR
template <typename T>
T clone(T& t) {
return t;
}
template <typename T, typename U>
std::shared_ptr<T> cast(const std::shared_ptr<U>& u);
template <typename T, typename U>
std::shared_ptr<T> dcast(const std::shared_ptr<U>& u);
#endif
#ifdef TAXONOMY_USE_UNIQUE_PTR
// untested currently
template <typename T>
T clone(T& t) {
return t->clone_();
}
template <typename T, typename U>
T* cast(const std::unique_ptr<U>& u);
template <typename T, typename U>
T* dcast(const std::unique_ptr<U>& u);
#endif
#ifdef TAXONOMY_USE_NAKED_PTR
// untested currently
template <typename T>
T clone(T& t) {
return t->clone_();
}
template <typename T, typename U>
T* cast(const U*& u);
template <typename T, typename U>
T* dcast(const U*& u);
#endif
#ifdef TAXONOMY_USE_SHARED_PTR
#define DECLARE_PTR(item) \
typedef std::shared_ptr<item> ptr; \
typedef std::shared_ptr<const item> const_ptr;
#endif
#ifdef TAXONOMY_USE_UNIQUE_PTR
#define DECLARE_PTR(item) \
typedef std::uniqe_ptr<item> ptr; \
typedef std::uniqe_ptr<const item> ptr;
#endif
#ifdef TAXONOMY_USE_NAKED_PTR
#define DECLARE_PTR(item) \
typedef item* ptr; \
typedef item const* ptr;
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4275)
#endif
class IFC_GEOM_API topology_error : public std::runtime_error {
public:
topology_error() : std::runtime_error("Generic topology error") {}
topology_error(const char* const s) : std::runtime_error(s) {}
~topology_error() override;
};
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
// Implementer note: If you add a new item type, be sure to do the following
// 1) Add a new kind to this list
// 2) Update the values array used by kind_to_string()
// 3) Update the KindsTuple with the class name of the new item
// 4) Add compare function (see compare functions in taxonomy.cpp starting around line 9)
// 4) Update Python bindings
// a) update list of assign_repr in IfcGeomWrapper.i
// b) update inheritance list in IfcGeomWrapper.i (around line 120 in the file)
// c) update item_to_pyobject function definition in type_conversion.i
enum kinds {
MATRIX4,
POINT3,
DIRECTION3,
LINE,
CIRCLE,
ELLIPSE,
BSPLINE_CURVE,
OFFSET_CURVE,
PLANE,
CYLINDER,
SPHERE,
TORUS,
BSPLINE_SURFACE,
EDGE,
LOOP,
FACE,
SHELL,
SOLID,
LOFT,
EXTRUSION,
REVOLVE,
SWEEP_ALONG_CURVE,
NODE,
COLLECTION,
BOOLEAN_RESULT,
FUNCTION_ITEM,
FUNCTOR_ITEM,
PIECEWISE_FUNCTION,
GRADIENT_FUNCTION,
CANT_FUNCTION,
OFFSET_FUNCTION,
COLOUR,
STYLE
};
IFC_GEOM_API const std::string& kind_to_string(kinds k);
struct IFC_GEOM_API item {
private:
uint32_t identity_;
static std::atomic_uint32_t counter_;
mutable size_t computed_hash_;
public:
DECLARE_PTR(item)
const IfcUtil::IfcBaseInterface* instance;
boost::optional<bool> orientation;
virtual item* clone_() const = 0;
virtual kinds kind() const = 0;
virtual void print(std::ostream&, int indent = 0) const;
virtual void reverse() { throw taxonomy::topology_error(); }
virtual size_t calc_hash() const = 0;
virtual size_t hash() const {
if (computed_hash_) {
return computed_hash_;
}
computed_hash_ = calc_hash();
if (computed_hash_ == 0) {
computed_hash_++;
}
return computed_hash_;
}
item(const IfcUtil::IfcBaseInterface* instance = nullptr) : identity_(counter_++), computed_hash_(0), instance(instance) {}
virtual ~item() {}
uint32_t identity() const { return identity_; }
};
namespace {
template <typename T>
const T& eigen_defaults();
template <>
const Eigen::Vector3d& eigen_defaults<Eigen::Vector3d>() {
static Eigen::Vector3d identity = Eigen::Vector3d::Zero();
return identity;
}
template <>
const Eigen::Matrix4d& eigen_defaults<Eigen::Matrix4d>() {
static Eigen::Matrix4d identity = Eigen::Matrix4d::Identity();
return identity;
}
}
template <typename T>
struct IFC_GEOM_API eigen_base {
T* components_;
eigen_base() {
components_ = nullptr;
}
eigen_base(const eigen_base& other) {
this->components_ = other.components_ ? new T(*other.components_) : nullptr;
}
eigen_base(const T& other) {
this->components_ = new T(other);
}
eigen_base& operator=(const eigen_base& other) {
if (this != &other) {
this->components_ = other.components_ ? new T(*other.components_) : nullptr;
}
return *this;
}
void print_impl(std::ostream& o, const std::string& class_name, int indent = 0) const {
o << std::string(indent, ' ') << class_name;
if (this->components_) {
int n = T::RowsAtCompileTime * T::ColsAtCompileTime;
for (int i = 0; i < n; ++i) {
o << " " << (*components_)(i);
}
}
o << std::endl;
}
virtual ~eigen_base() {
delete this->components_;
}
const T& ccomponents() const {
if (this->components_) {
return *this->components_;
} else {
return eigen_defaults<T>();
}
}
T& components() {
if (!this->components_) {
this->components_ = new T(eigen_defaults<T>());
}
return *this->components_;
}
explicit operator bool() const {
return components_;
}
uint32_t hash_components() const {
size_t h = std::hash<size_t>{}(T::RowsAtCompileTime);
boost::hash_combine(h, std::hash<size_t>{}(T::ColsAtCompileTime));
if (components_) {
for (int i = 0; i < components_->size(); ++i) {
auto elem = *(components_->data() + (size_t)i);
boost::hash_combine(h, std::hash<typename T::Scalar>()(elem));
}
}
return (uint32_t)h;
}
};
struct IFC_GEOM_API matrix4 : public item, public eigen_base<Eigen::Matrix4d> {
private:
void init(const Eigen::Vector3d& o, const Eigen::Vector3d& z, const Eigen::Vector3d& x) {
auto Z = z.normalized();
auto Y = Z.cross(x).normalized();
auto X = Y.cross(Z);
components_ = new Eigen::Matrix4d;
(*components_) <<
X(0), Y(0), Z(0), o(0),
X(1), Y(1), Z(1), o(1),
X(2), Y(2), Z(2), o(2),
0, 0, 0, 1.;
if (is_identity()) {
// @todo detect this earlier to save us the heapalloc.
delete components_;
components_ = nullptr;
tag = IDENTITY;
}
}
public:
DECLARE_PTR(matrix4)
enum tag_t {
IDENTITY, AFFINE_WO_SCALE, AFFINE_W_UNIFORM_SCALE, AFFINE_W_NONUNIFORM_SCALE, OTHER
};
tag_t tag;
matrix4() : eigen_base(), tag(IDENTITY) {}
matrix4(const Eigen::Matrix4d& c) : eigen_base(c), tag(OTHER) {}
matrix4(const Eigen::Vector3d& o, const Eigen::Vector3d& z, const Eigen::Vector3d& x) : tag(AFFINE_WO_SCALE) {
init(o, z, x);
}
matrix4(const Eigen::Vector3d& o, const Eigen::Vector3d& z) : tag(AFFINE_WO_SCALE) {
auto x = Eigen::Vector3d(1, 0, 0);
auto y = z.cross(x);
if (y.squaredNorm() < 1.e-7) {
x = Eigen::Vector3d(0, 0, 1);
}
init(o, z, x);
}
bool is_identity() const {
return !components_ || components_->isIdentity();
}
void print(std::ostream& o, int indent = 0) const;
virtual matrix4* clone_() const { return new matrix4(*this); }
virtual kinds kind() const { return MATRIX4; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(MATRIX4), hash_components());
return boost::hash<decltype(v)>{}(v);
}
void pre_multiply_scale(double s) {
components().block<3, 4>(0, 0) *= s;
}
void post_multiply_scale(double s) {
components().block<4, 3>(0, 0) *= s;
}
Eigen::Vector3d translation_part() const { return ccomponents().col(3).head<3>(); }
};
struct IFC_GEOM_API colour : public item, public eigen_base<Eigen::Vector3d> {
DECLARE_PTR(colour)
void print(std::ostream& o, int indent = 0) const;
virtual colour* clone_() const { return new colour(*this); }
virtual kinds kind() const { return COLOUR; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(COLOUR), hash_components());
return boost::hash<decltype(v)>{}(v);
}
colour() : eigen_base() {}
colour(double r, double g, double b) { components() << r, g, b; }
const double& r() const { return ccomponents()[0]; }
const double& g() const { return ccomponents()[1]; }
const double& b() const { return ccomponents()[2]; }
};
struct IFC_GEOM_API style : public item {
DECLARE_PTR(style)
std::string name;
colour diffuse;
colour surface;
colour specular;
double specularity, transparency;
bool use_surface_color;
void print(std::ostream& o, int indent = 0) const;
virtual style* clone_() const { return new style(*this); }
virtual kinds kind() const { return STYLE; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(STYLE), name, diffuse.hash(), surface.hash(), specular.hash(), specularity, transparency);
return boost::hash<decltype(v)>{}(v);
}
// @todo equality implementation based on values?
bool operator==(const style& other) const { return instance == other.instance; }
style() : specularity(std::numeric_limits<double>::quiet_NaN()), transparency(std::numeric_limits<double>::quiet_NaN()), use_surface_color(false) {}
style(const std::string& name) : name(name), specularity(std::numeric_limits<double>::quiet_NaN()), transparency(std::numeric_limits<double>::quiet_NaN()), use_surface_color(false) {}
const colour& get_color() const {
if (use_surface_color && surface) {
return surface;
}
return diffuse;
}
bool has_specularity() const {
return !std::isnan(specularity);
}
bool has_transparency() const {
return !std::isnan(transparency);
}
};
struct IFC_GEOM_API geom_item : public item {
DECLARE_PTR(geom_item)
style::ptr surface_style;
matrix4::ptr matrix;
geom_item(const IfcUtil::IfcBaseInterface* instance = nullptr) : item(instance), surface_style(nullptr) {}
geom_item(const IfcUtil::IfcBaseInterface* instance, matrix4::ptr m) : item(instance), surface_style(nullptr), matrix(m) {}
geom_item(matrix4::ptr m) : surface_style(nullptr), matrix(m) {}
};
struct IFC_GEOM_API implicit_item : public geom_item {
DECLARE_PTR(implicit_item)
using geom_item::geom_item;
};
struct IFC_GEOM_API function_item : public implicit_item {
DECLARE_PTR(function_item)
function_item(const IfcUtil::IfcBaseInterface* instance = nullptr) : implicit_item(instance) {}
function_item(function_item&&) = default;
function_item(const function_item&) = default;
virtual ~function_item() = default;
virtual double start() const = 0;
virtual double end() const = 0;
virtual double length() const {
return end() - start();
}
virtual kinds kind() const { return FUNCTION_ITEM; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(FUNCTION_ITEM), 0);
return boost::hash<decltype(v)>{}(v);
};
};
struct IFC_GEOM_API functor_item : public function_item {
DECLARE_PTR(functor_item)
functor_item(double length, std::function<Eigen::Matrix4d(double u)> fn, const IfcUtil::IfcBaseInterface* instance = nullptr) : function_item(instance),
length_(length), fn_(fn) {}
functor_item(functor_item&&) = default;
functor_item(const functor_item&) = default;
virtual ~functor_item() = default;
double start() const override { return 0.0; }
double end() const override { return length_; }
Eigen::Matrix4d operator()(double u) const { return fn_(u); }
functor_item* clone_() const override { return new functor_item(*this); }
virtual kinds kind() const { return FUNCTOR_ITEM; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(FUNCTOR_ITEM), 0);
return boost::hash<decltype(v)>{}(v);
}
private:
double length_;
std::function<Eigen::Matrix4d(double u)> fn_;
};
struct IFC_GEOM_API piecewise_function : public function_item {
DECLARE_PTR(piecewise_function)
using spans_t = std::vector<function_item::const_ptr>;
piecewise_function(double start, const spans_t& s, const IfcUtil::IfcBaseInterface* instance = nullptr);
piecewise_function(double start, const std::vector<piecewise_function::ptr>& pwfs, const IfcUtil::IfcBaseInterface* instance = nullptr);
piecewise_function(piecewise_function&&) = default;
piecewise_function(const piecewise_function&) = default;
virtual ~piecewise_function() = default;
const spans_t& spans() const;
size_t span_count() const {return spans_.size();}
function_item::const_ptr span_fn(size_t i) { return spans_[i]; }
bool is_empty() const;
double start() const override;
double end() const override;
double length() const override;
piecewise_function* clone_() const override { return new piecewise_function(*this); }
virtual kinds kind() const { return PIECEWISE_FUNCTION; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(PIECEWISE_FUNCTION), 0);
return boost::hash<decltype(v)>{}(v);
}
private:
double start_ = 0.0; // starting value of the pwf
spans_t spans_;
};
struct IFC_GEOM_API gradient_function : public function_item {
DECLARE_PTR(gradient_function)
gradient_function(piecewise_function::const_ptr horizontal, piecewise_function::const_ptr vertical, const IfcUtil::IfcBaseInterface* instance = nullptr);
gradient_function(gradient_function&&) = default;
gradient_function(const gradient_function&) = default;
virtual ~gradient_function() = default;
virtual double start() const override;
virtual double end() const override;
piecewise_function::const_ptr get_horizontal() const;
piecewise_function::const_ptr get_vertical() const;
gradient_function* clone_() const override { return new gradient_function(*this); }
virtual kinds kind() const { return GRADIENT_FUNCTION; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(GRADIENT_FUNCTION), 0);
return boost::hash<decltype(v)>{}(v);
}
private:
piecewise_function::const_ptr horizontal_, vertical_;
};
struct IFC_GEOM_API cant_function : public function_item {
DECLARE_PTR(cant_function)
cant_function(gradient_function::const_ptr gradient, piecewise_function::const_ptr cant, const IfcUtil::IfcBaseInterface* instance = nullptr);
cant_function(cant_function&&) = default;
cant_function(const cant_function&) = default;
virtual ~cant_function() = default;
virtual double start() const override;
virtual double end() const override;
gradient_function::const_ptr get_gradient() const;
piecewise_function::const_ptr get_cant() const;
cant_function* clone_() const override { return new cant_function(*this); }
virtual kinds kind() const { return CANT_FUNCTION; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(CANT_FUNCTION), 0);
return boost::hash<decltype(v)>{}(v);
}
private:
gradient_function::const_ptr gradient_;
piecewise_function::const_ptr cant_;
};
struct IFC_GEOM_API offset_function : public function_item {
DECLARE_PTR(offset_function)
offset_function(function_item::const_ptr basis, piecewise_function::const_ptr offset, const IfcUtil::IfcBaseInterface* instance = nullptr);
offset_function(offset_function&&) = default;
offset_function(const offset_function&) = default;
virtual ~offset_function() = default;
virtual double start() const override;
virtual double end() const override;
function_item::const_ptr get_basis() const;
piecewise_function::const_ptr get_offset() const;
offset_function* clone_() const override { return new offset_function(*this); }
virtual kinds kind() const { return OFFSET_FUNCTION; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(OFFSET_FUNCTION), 0);
return boost::hash<decltype(v)>{}(v);
}
private:
function_item::const_ptr basis_;
piecewise_function::const_ptr offset_;
};
#ifdef TAXONOMY_USE_SHARED_PTR
typedef std::shared_ptr<item> ptr;
typedef std::shared_ptr<const item> const_ptr;
template<typename T, typename... Args>
std::shared_ptr<T> make(Args&&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
}
#endif
#ifdef TAXONOMY_USE_UNIQUE_PTR
typedef std::uniqe_ptr<item> ptr;
typedef std::uniqe_ptr<const item> ptr;
template<typename T, typename... Args>
std::uniqe_ptr<T> make(Args&&... args) {
return new T(std::forward<Args>(args)...));
}
#endif
#ifdef TAXONOMY_USE_NAKED_PTR
typedef item* ptr;
typedef item const* ptr;
template<typename T, typename... Args>
T* make(Args&&... args) {
return new T(std::forward<Args>(args)...));
}
#endif
IFC_GEOM_API bool less(item::const_ptr, item::const_ptr);
struct less_functor {
bool operator()(item::const_ptr a, item::const_ptr b) const {
return less(a, b);
}
};
struct equal_functor {
bool operator()(taxonomy::item::ptr const& a,
taxonomy::item::ptr const& b) const
{
if (a == b) {
return true;
}
return !less(a, b) && !less(b, a);
}
};
struct hash_functor {
size_t operator()(taxonomy::item::ptr const& a) const
{
return a->hash();
}
};
// @todo make 4d for easier multiplication
template <size_t N>
struct IFC_GEOM_API cartesian_base : public item, public eigen_base<Eigen::Vector3d> {
cartesian_base() : eigen_base() {}
cartesian_base(const Eigen::Vector3d& c) : eigen_base(c) {}
cartesian_base(double x, double y, double z = 0.) : eigen_base(Eigen::Vector3d(x, y, z)) {}
};
struct IFC_GEOM_API point3 : public cartesian_base<3> {
DECLARE_PTR(point3)
virtual point3* clone_() const { return new point3(*this); }
virtual kinds kind() const { return POINT3; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(POINT3), hash_components());
return boost::hash<decltype(v)>{}(v);
}
void print(std::ostream& o, int indent = 0) const;
point3() : cartesian_base() {}
point3(const Eigen::Vector3d& c) : cartesian_base(c) {}
point3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {}
};
struct IFC_GEOM_API direction3 : public cartesian_base<3> {
DECLARE_PTR(direction3)
virtual direction3* clone_() const { return new direction3(*this); }
virtual kinds kind() const { return DIRECTION3; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(DIRECTION3), hash_components());
return boost::hash<decltype(v)>{}(v);
}
void print(std::ostream& o, int indent = 0) const;
direction3() : cartesian_base() {}
direction3(const Eigen::Vector3d& c) : cartesian_base(c) {}
direction3(double x, double y, double z = 0.) : cartesian_base(x, y, z) {}
};
struct IFC_GEOM_API curve : public geom_item {
void print_impl(std::ostream& o, const std::string& classname, int indent = 0) const {
o << std::string(indent, ' ') << classname << std::endl;
this->matrix->print(o, indent + 4);
}
};
struct IFC_GEOM_API line : public curve {
DECLARE_PTR(line)
virtual line* clone_() const { return new line(*this); }
virtual kinds kind() const { return LINE; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(LINE), matrix->hash_components());
return boost::hash<decltype(v)>{}(v);
}
void print(std::ostream& o, int indent = 0) const;
};
struct IFC_GEOM_API circle : public curve {
DECLARE_PTR(circle)
double radius;
virtual circle* clone_() const { return new circle(*this); }
virtual kinds kind() const { return CIRCLE; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(CIRCLE), matrix->hash_components(), radius);
return boost::hash<decltype(v)>{}(v);
}
void print(std::ostream& o, int indent = 0) const;
static circle::ptr from_3_points(const Eigen::Vector3d& p1, const Eigen::Vector3d& p2, const Eigen::Vector3d& p3) {
Eigen::Vector3d t = p2 - p1;
Eigen::Vector3d u = p3 - p1;
Eigen::Vector3d v = p3 - p2;
auto norm = t.cross(u);
auto mag = norm.dot(norm);
auto iwsl2 = 1. / (2. * mag);
auto tt = t.dot(t);
auto uu = u.dot(u);
auto orig = p1 + (u * tt * u.dot(v) - t * uu * t.dot(v)) * iwsl2;
if (!orig.array().isNaN().any()) {
auto radius = std::sqrt(tt * uu * v.dot(v) * iwsl2 * 0.5f);
auto ax = norm / std::sqrt(mag);
auto c = make<circle>();
c->radius = radius;
c->matrix = taxonomy::make<taxonomy::matrix4>(orig, ax);
return c;
}
return nullptr;
}
};
struct IFC_GEOM_API ellipse : public curve {
DECLARE_PTR(ellipse)
double radius;
double radius2;
virtual ellipse* clone_() const { return new ellipse(*this); }
virtual kinds kind() const { return ELLIPSE; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(ELLIPSE), matrix->hash_components(), radius, radius2);
return boost::hash<decltype(v)>{}(v);
}
void print(std::ostream& o, int indent = 0) const;
};
struct IFC_GEOM_API bspline_curve : public curve {
DECLARE_PTR(bspline_curve)
virtual bspline_curve* clone_() const { return new bspline_curve(*this); }
virtual kinds kind() const { return BSPLINE_CURVE; }
virtual size_t calc_hash() const {
size_t h = std::hash<size_t>{}(BSPLINE_CURVE);
for (auto& x : control_points) {
boost::hash_combine(h, x->hash());
}
for (auto& x : multiplicities) {
boost::hash_combine(h, std::hash<int>{}(x));
}
for (auto& x : knots) {
boost::hash_combine(h, std::hash<double>{}(x));
}
if (weights) {
for (auto& x : *weights) {
boost::hash_combine(h, std::hash<double>{}(x));
}
}
boost::hash_combine(h, std::hash<int>{}(degree));
return h;
}
std::vector<point3::ptr> control_points;
std::vector<int> multiplicities;
std::vector<double> knots;
boost::optional<std::vector<double>> weights;
int degree;
};
struct IFC_GEOM_API offset_curve : public curve {
DECLARE_PTR(offset_curve)
direction3::ptr reference;
double offset;
item::ptr basis;
virtual offset_curve* clone_() const { return new offset_curve(*this); }
virtual kinds kind() const { return OFFSET_CURVE; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(OFFSET_CURVE), reference->hash(), offset, basis ? basis->hash() : size_t(0));
return boost::hash<decltype(v)>{}(v);
}
};
struct IFC_GEOM_API trimmed_curve : public geom_item {
DECLARE_PTR(trimmed_curve)
// @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.
boost::variant<boost::blank, point3::ptr, double> start, end;
// @todo somehow account for the fact that curve in IFC can be trimmed curve, polyline and composite curve as well.
item::ptr basis;
// @todo does this make sense? this is to accommodate for the fact that orientation is defined on both TrimmedCurve as well CompCurveSegment
boost::optional<bool> curve_sense;
trimmed_curve() : basis(nullptr) {}
trimmed_curve(const point3::ptr& a, const point3::ptr& b) : start(a), end(b), basis(nullptr) {}
virtual void reverse() {
// std::swap(start, end);
orientation = !orientation.get_value_or(true);
}
void print(std::ostream& o, int indent = 0) const;
};
struct IFC_GEOM_API edge : public trimmed_curve {
DECLARE_PTR(edge)
edge() : trimmed_curve() {}
edge(const point3::ptr& a, const point3::ptr& b) : trimmed_curve(a, b) {}
// @todo how to express similarity between trimmed_curve and edge?
virtual edge* clone_() const { return new edge(*this); }
virtual kinds kind() const { return EDGE; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(EDGE), start, end, basis ? basis->hash() : size_t(0), curve_sense ? *curve_sense ? 2 : 1 : 0);
return boost::hash<decltype(v)>{}(v);
}
};
template <typename T = item>
struct IFC_GEOM_API collection_base : public geom_item {
std::vector<typename T::ptr> children;
collection_base() {}
collection_base(const collection_base& other)
: geom_item()
{
std::transform(other.children.begin(), other.children.end(), std::back_inserter(children), [](typename T::ptr p) { return clone(p); });
}
/*
template <typename T>
std::vector<typename T::ptr> children_as() const {
std::vector<typename T::ptr> ts;
ts.reserve(children.size());
std::for_each(children.begin(), children.end(), [&ts](ptr i){
auto v = dcast<T>(i);
if (v) {
ts.push_back(v);
}
});
return ts;
}
*/
virtual void reverse() {
// @todo this needs to create copies of the children in case of shared_ptr
std::reverse(children.begin(), children.end());
for (auto& child : children) {
child->reverse();
}
}
virtual void print_impl(std::ostream&, int) const {
// empty on purpose
}
void print(std::ostream& o, int indent = 0) const {
o << std::string(indent, ' ') << kind_to_string(kind()) << std::endl;
if (matrix && !matrix->is_identity()) {
matrix->print(o, indent + 4);
}
for (auto& c : children) {
c->print(o, indent + 4);
}
print_impl(o, indent + 4);
}
virtual ~collection_base() {
#ifdef TAXONOMY_USE_NAKED_PTR
for (auto& c : children) {
delete c;
}
#endif
}
uint32_t hash_elements() const {
size_t h = 0;
for (auto& c : children) {
boost::hash_combine(h, c->hash());
}
// @todo should we really use uint32_t instead of size_t for hashes?
return (uint32_t) h;
}
};
struct IFC_GEOM_API collection : public collection_base<geom_item> {
DECLARE_PTR(collection)
virtual collection* clone_() const { return new collection(*this); }
virtual kinds kind() const { return COLLECTION; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(COLLECTION), hash_elements());
return boost::hash<decltype(v)>{}(v);
}
};
struct IFC_GEOM_API loop : public collection_base<edge> {
DECLARE_PTR(loop)
boost::optional<bool> external, closed;
boost::optional<taxonomy::function_item::ptr> function_item;
boost::optional<std::vector<std::string>> tags;
bool is_polyhedron() const {
for (auto& e : children) {
if (e->basis != nullptr) {
if (e->basis->kind() != LINE) {
return false;
}
}
}
return true;
}
void calculate_linear_edge_curves() const {
for (auto& e : children) {
if (e->basis == nullptr) {
if (e->start.which() == 1 && e->end.which() == 1) {
auto ln = make<taxonomy::line>();
auto a = boost::get<point3::ptr>(e->start)->ccomponents();
auto b = boost::get<point3::ptr>(e->end)->ccomponents();
ln->matrix = make<matrix4>(a, b - a);
e->basis = ln;
}
}
}
}
void remove_linear_edge_curves() const {
for (auto& e : children) {
if (e->basis != nullptr && e->basis->kind() == LINE) {
e->basis = nullptr;
}
}
}
virtual loop* clone_() const { return new loop(*this); }
virtual kinds kind() const { return LOOP; }
virtual size_t calc_hash() const {
auto v = std::make_tuple(static_cast<size_t>(LOOP), hash_elements(), external ? *external ? 2 : 1 : 0, closed ? *closed ? 2 : 1 : 0);
return boost::hash<decltype(v)>{}(v);
}
// nb only takes into account explicit points
taxonomy::point3::ptr centroid() const {
Eigen::Vector3d c(0, 0, 0);
for (auto& e : children) {
if (e->start.which() == 1) {
c += boost::get<point3::ptr>(e->start)->ccomponents();
}
if (e->end.which() == 1) {
c += boost::get<point3::ptr>(e->end)->ccomponents();
}
}
c /= static_cast<double>(children.size());
return make<taxonomy::point3>(c);
}
};
struct IFC_GEOM_API face : public collection_base<loop> {
DECLARE_PTR(face)
item::ptr basis;
virtual face* clone_() const { return new face(*this); }
virtual kinds kind() const { return FACE; }
virtual void print_impl(std::ostream& o, int indent) const {
if (basis) {