PLaSK library

Loading...
Searching...
No Matches
primitives.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__PRIMITIVES_H
15#define PLASK__PRIMITIVES_H
16
21#include "../exceptions.hpp"
22#include "../vec.hpp"
23
24 namespace plask {
25
26 constexpr double POINT_TOLLERANCE = 1e-12;
27
28 extern PLASK_API const char* const DIRECTION_NAMES[];
29
36 struct PLASK_API Box2D {
38 Vec<2, double> lower;
39
41 Vec<2, double> upper;
42
47 constexpr Vec<2, double> size() const { return upper - lower; }
48
53 constexpr double height() const { return upper.vert() - lower.vert(); }
54
59 constexpr double width() const { return upper.tran() - lower.tran(); }
60
65 constexpr Vec<2, double> center() const { return 0.5 * (upper + lower); }
66
68 Box2D() {}
69
75 constexpr Box2D(const Vec<2, double>& lower, const Vec<2, double>& upper) : lower(lower), upper(upper) {}
76
82 constexpr Box2D(double x_lo, double y_lo, double x_up, double y_up) : lower(x_lo, y_lo), upper(x_up, y_up) {}
83
84 static Box2D invalidInstance() {
85 Box2D r;
86 r.makeInvalid();
87 return r;
88 }
89
95 bool operator==(const Box2D& r) const;
96
102 bool operator!=(const Box2D& r) const;
103
108 void fix();
109
115 bool contains(const Vec<2, double>& p) const;
116
122 bool intersects(const Box2D& other) const;
123
128 void makeInclude(const Vec<2, double>& p);
129
134 void makeInclude(const Box2D& other);
135
140 void makeIntersection(const Box2D& other);
141
147 Box2D intersection(Box2D other) const;
148
154 Box2D extension(Box2D other) const;
155
161 Box2D translated(const Vec<2, double>& translation_vec) const {
162 return Box2D(lower + translation_vec, upper + translation_vec);
163 }
164
170 Box2D operator+(const Vec<2, double>& translation_vec) const {
171 return Box2D(lower + translation_vec, upper + translation_vec);
172 }
173
179 Box2D operator-(const Vec<2, double>& translation_vec) const {
180 return Box2D(lower - translation_vec, upper - translation_vec);
181 }
182
188 Box2D translatedUp(const double trasnalation_in_up_dir) const {
189 return translated(vec(0.0, trasnalation_in_up_dir));
190 }
191
196 void translate(const Vec<2, double>& translation_vec) {
197 lower += translation_vec;
198 upper += translation_vec;
199 }
200
205 Box2D& operator+=(const Vec<2, double>& translation_vec) {
206 lower += translation_vec;
207 upper -= translation_vec;
208 return *this;
209 }
210
215 Box2D& operator-=(const Vec<2, double>& translation_vec) {
216 lower -= translation_vec;
217 upper -= translation_vec;
218 return *this;
219 }
220
225 void translateUp(const double trasnalation_in_up_dir) {
226 lower.vert() += trasnalation_in_up_dir;
227 upper.vert() += trasnalation_in_up_dir;
228 }
229
235 void translateDir(unsigned dir_index, const double trasnalation_in_dir) {
236 lower[dir_index] += trasnalation_in_dir;
237 upper[dir_index] += trasnalation_in_dir;
238 }
239
246 Vec<2, double> moveInside(Vec<2, double> p) const;
247
254 friend inline std::ostream& operator<<(std::ostream& out, const Box2D& to_print) {
255 return out << '[' << to_print.lower << ", " << to_print.upper << ']';
256 }
257
264 bool isValid() const { return upper.c0 >= lower.c0 && upper.c1 >= lower.c1; }
265
270 void makeInvalid() {
271 lower = vec(0.0, 0.0);
272 upper = vec(-1.0, -1.0);
273 }
274
279 double getArea() const {
280 Vec<2, double> v = size();
281 return v.c0 * v.c1;
282 }
283
289 inline void flip(size_t flipDir) {
290 assert(flipDir < 2);
291 double temp = lower[flipDir];
292 lower[flipDir] = -upper[flipDir];
293 upper[flipDir] = -temp;
294 }
295
302 inline Box2D flipped(size_t i) const {
303 Box2D res = *this;
304 res.flip(i);
305 return res;
306 }
307
312 const double& left() const { return lower.c0; }
313
318 double& left() { return lower.c0; }
319
324 const double& right() const { return upper.c0; }
325
330 double& right() { return upper.c0; }
331
336 const double& bottom() const { return lower.c1; }
337
342 double& bottom() { return lower.c1; }
343
348 const double& top() const { return upper.c1; }
349
354 double& top() { return upper.c1; }
355
356 void setLeft(double v) { lower.c0 = v; }
357 void setRight(double v) { upper.c0 = v; }
358 void setBottom(double v) { lower.c1 = v; }
359 void setTop(double v) { upper.c1 = v; }
360
361 double getLeft() const { return lower.c0; }
362 double getRight() const { return upper.c0; }
363 double getBottom() const { return lower.c1; }
364 double getTop() const { return upper.c1; }
365};
366
373 struct PLASK_API Box3D {
375 Vec<3, double> lower;
376
378 Vec<3, double> upper;
379
384 constexpr Vec<3, double> size() const { return upper - lower; }
385
390 constexpr double height() const { return upper.vert() - lower.vert(); }
391
396 constexpr double width() const { return upper.tran() - lower.tran(); }
397
402 constexpr double depth() const { return upper.lon() - lower.lon(); }
403
408 constexpr Vec<3, double> center() const { return 0.5 * (upper + lower); }
409
411 Box3D() {}
412
418 constexpr Box3D(const Vec<3, double>& lower, const Vec<3, double>& upper) : lower(lower), upper(upper) {}
419
425 constexpr Box3D(double x_lo, double y_lo, double z_lo, double x_up, double y_up, double z_up)
426 : lower(x_lo, y_lo, z_lo), upper(x_up, y_up, z_up) {}
427
428 static Box3D invalidInstance() {
429 Box3D r;
430 r.makeInvalid();
431 return r;
432 }
433
439 bool operator==(const Box3D& r) const;
440
446 bool operator!=(const Box3D& r) const;
447
452 void fix();
453
459 bool contains(const Vec<3, double>& p) const;
460
466 bool intersects(const Box3D& other) const;
467
472 void makeInclude(const Vec<3, double>& p);
473
478 void makeInclude(const Box3D& other);
479
484 void makeIntersection(const Box3D& other);
485
491 Box3D extension(Box3D other) const;
492
498 Box3D intersection(Box3D other) const;
499
505 Box3D translated(const Vec<3, double>& translation_vec) const {
506 return Box3D(lower + translation_vec, upper + translation_vec);
507 }
508
514 Box3D operator+(const Vec<3, double>& translation_vec) const {
515 return Box3D(lower + translation_vec, upper + translation_vec);
516 }
517
523 Box3D operator-(const Vec<3, double>& translation_vec) const {
524 return Box3D(lower - translation_vec, upper - translation_vec);
525 }
526
532 Box3D translatedUp(const double trasnalation_in_up_dir) const {
533 Box3D r = *this;
534 r.translateUp(trasnalation_in_up_dir);
535 return r;
536 }
537
542 void translate(const Vec<3, double>& translation_vec) {
543 lower += translation_vec;
544 upper += translation_vec;
545 }
546
551 Box3D& operator+=(const Vec<3, double>& translation_vec) {
552 lower += translation_vec;
553 upper -= translation_vec;
554 return *this;
555 }
556
561 Box3D& operator-=(const Vec<3, double>& translation_vec) {
562 lower -= translation_vec;
563 upper -= translation_vec;
564 return *this;
565 }
566
571 void translateUp(const double trasnalation_in_up_dir) {
572 lower.vert() += trasnalation_in_up_dir;
573 upper.vert() += trasnalation_in_up_dir;
574 }
575
581 void translateDir(unsigned dir_index, const double trasnalation_in_dir) {
582 lower[dir_index] += trasnalation_in_dir;
583 upper[dir_index] += trasnalation_in_dir;
584 }
585
590 void makeInclude(const Box2D& other);
591
598 Vec<3, double> moveInside(Vec<3, double> p) const;
599
606 friend inline std::ostream& operator<<(std::ostream& out, const Box3D& to_print) {
607 return out << '[' << to_print.lower << ", " << to_print.upper << ']';
608 }
609
616 bool isValid() const { return upper.c0 >= lower.c0 && upper.c1 >= lower.c1 && upper.c2 >= lower.c2; }
617
622 void makeInvalid() {
623 lower = vec(0.0, 0.0, 0.0);
624 upper = vec(-1.0, -1.0, -1.0);
625 }
626
631 double getArea() const {
632 Vec<3, double> v = size();
633 return v.c0 * v.c1 * v.c2;
634 }
635
641 inline void flip(size_t flipDir) {
642 assert(flipDir < 3);
643 double temp = lower[flipDir];
644 lower[flipDir] = -upper[flipDir];
645 upper[flipDir] = -temp;
646 }
647
654 inline Box3D flipped(size_t i) const {
655 Box3D res = *this;
656 res.flip(i);
657 return res;
658 }
659
664 const double& back() const { return lower.c0; }
665
670 double& back() { return lower.c0; }
671
676 const double& front() const { return upper.c0; }
677
682 double& front() { return upper.c0; }
683
688 const double& left() const { return lower.c1; }
689
694 double& left() { return lower.c1; }
695
700 const double& right() const { return upper.c1; }
701
706 double& right() { return upper.c1; }
707
712 const double& bottom() const { return lower.c2; }
713
718 double& bottom() { return lower.c2; }
719
724 const double& top() const { return upper.c2; }
725
730 double& top() { return upper.c2; }
731
732 void setBack(double v) { lower.c0 = v; }
733 void setFront(double v) { upper.c0 = v; }
734 void setLeft(double v) { lower.c1 = v; }
735 void setRight(double v) { upper.c1 = v; }
736 void setBottom(double v) { lower.c2 = v; }
737 void setTop(double v) { upper.c2 = v; }
738
739 double getBack() const { return lower.c0; }
740 double getFront() const { return upper.c0; }
741 double getLeft() const { return lower.c1; }
742 double getRight() const { return upper.c1; }
743 double getBottom() const { return lower.c2; }
744 double getTop() const { return upper.c2; }
745};
746
751 template <int dim> struct Primitive {};
752
756 template <> struct PLASK_API Primitive<1> {
758 typedef double DVec;
759
761 static const int dim = 1;
762
764 static const DVec ZERO_VEC;
765
766 enum Direction { DIRECTION = 0 };
767
769 inline static bool vecFuzzyCompare(DVec a, DVec b) { return b - a > POINT_TOLLERANCE; }
770};
771
775 template <> struct PLASK_API Primitive<2> {
777 typedef Box2D Box;
778
780 typedef Vec<2, double> DVec;
781
783 static const int dim = 2;
784
786 static const DVec ZERO_VEC;
787
789 static const DVec NAN_VEC;
790
792 static const Box INF_BOX;
793
794 enum Direction { DIRECTION_TRAN = 0, DIRECTION_VERT = 1 };
795
796 static void ensureIsValidDirection(unsigned direction) {
797 if (direction > 1) throw Exception("bad 2D direction index, {0} was given but allowed are: 0, 1.", direction);
798 }
799
801 inline static bool vecFuzzyCompare(const DVec& a, const DVec& b) {
802 return b.c1 - a.c1 > POINT_TOLLERANCE || (a.c1 - b.c1 <= POINT_TOLLERANCE && b.c0 - a.c0 > POINT_TOLLERANCE);
803 }
804};
805
809 template <> struct PLASK_API Primitive<3> {
811 typedef Box3D Box;
812
814 typedef Vec<3, double> DVec;
815
817 static const int dim = 3;
818
820 static const DVec ZERO_VEC;
821
823 static const DVec NAN_VEC;
824
826 static const Box INF_BOX;
827
828 enum Direction { DIRECTION_LONG = 0, DIRECTION_TRAN = 1, DIRECTION_VERT = 2 };
829
830 static void ensureIsValidDirection(unsigned direction) {
831 if (direction > 2)
832 throw DimensionError("bad 3D direction index, {} was given but allowed are: 0, 1, 2.", direction);
833 }
834
835 static void ensureIsValid2DDirection(unsigned direction) {
836 if (direction != DIRECTION_TRAN && direction != DIRECTION_VERT)
837 throw DimensionError(
838 "bad 2D direction index, {} was given but allowed are: 1 (DIRECTION_TRAN), 2 (DIRECTION_VERT).",
839 direction);
840 }
841
843 inline static bool vecFuzzyCompare(const DVec& a, const DVec& b) {
844 return b.c2 - a.c2 > POINT_TOLLERANCE || (a.c2 - b.c2 <= POINT_TOLLERANCE &&
845 (b.c1 - a.c1 > POINT_TOLLERANCE || (a.c1 - b.c1 <= POINT_TOLLERANCE &&
846 b.c0 - a.c0 > POINT_TOLLERANCE)));
847 }
848};
849
850 constexpr inline Primitive<3>::Direction direction3D(Primitive<2>::Direction dir2D) {
851 return Primitive<3>::Direction(dir2D + 1);
852}
853
854 constexpr inline Primitive<3>::Direction direction3D(Primitive<3>::Direction dir3D) { return dir3D; }
855
856 template <int dim, typename Primitive<dim>::Direction dirToSkip> struct DirectionWithout {};
857
858 template <> struct DirectionWithout<2, Primitive<2>::DIRECTION_TRAN> {
859 static const Primitive<2>::Direction value = Primitive<2>::DIRECTION_VERT;
860 static const Primitive<3>::Direction value3d = Primitive<3>::DIRECTION_VERT;
861};
862
863 template <> struct DirectionWithout<2, Primitive<2>::DIRECTION_VERT> {
864 static const Primitive<2>::Direction value = Primitive<2>::DIRECTION_TRAN;
865 static const Primitive<3>::Direction value3d = Primitive<3>::DIRECTION_TRAN;
866};
867
868 template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_LONG> {
869 static const unsigned value = Primitive<3>::DIRECTION_TRAN | Primitive<3>::DIRECTION_VERT;
870 static const Primitive<3>::Direction valueLower = Primitive<3>::DIRECTION_TRAN;
871 static const Primitive<3>::Direction valueHigher = Primitive<3>::DIRECTION_VERT;
872
873 // should be not usedm but sometimes it is useful to make compilation possible
874 static const Primitive<2>::Direction value2D =
875 Primitive<2>::Direction(Primitive<2>::DIRECTION_VERT | Primitive<2>::DIRECTION_VERT);
876};
877
878 template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_TRAN> {
879 static const unsigned value = Primitive<3>::DIRECTION_LONG | Primitive<3>::DIRECTION_VERT;
880 static const Primitive<3>::Direction valueLower = Primitive<3>::DIRECTION_LONG;
881 static const Primitive<3>::Direction valueHigher = Primitive<3>::DIRECTION_VERT;
882
883 static const Primitive<2>::Direction value2D = Primitive<2>::DIRECTION_VERT;
884};
885
886 template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_VERT> {
887 static const unsigned value = Primitive<3>::DIRECTION_LONG | Primitive<3>::DIRECTION_TRAN;
888 static const Primitive<3>::Direction valueLower = Primitive<3>::DIRECTION_LONG;
889 static const Primitive<3>::Direction valueHigher = Primitive<3>::DIRECTION_TRAN;
890
891 static const Primitive<2>::Direction value2D = Primitive<2>::DIRECTION_TRAN;
892};
893
894} // namespace plask
895
896#if FMT_VERSION >= 90000
897 template <> struct fmt::formatter<plask::Box2D> : ostream_formatter {};
898 template <> struct fmt::formatter<plask::Box3D> : ostream_formatter {};
899#endif
900
901#endif