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
24namespace plask {
25
26constexpr double POINT_TOLLERANCE = 1e-12;
27
37
40
45 constexpr Vec<2, double> size() const { return upper - lower; }
46
51 constexpr double height() const { return upper.vert() - lower.vert(); }
52
57 constexpr double width() const { return upper.tran() - lower.tran(); }
58
63 constexpr Vec<2, double> center() const { return 0.5 * (upper + lower); }
64
66 Box2D() {}
67
73 constexpr Box2D(const Vec<2, double>& lower, const Vec<2, double>& upper) : lower(lower), upper(upper) {}
74
80 constexpr Box2D(double x_lo, double y_lo, double x_up, double y_up) : lower(x_lo, y_lo), upper(x_up, y_up) {}
81
83 Box2D r;
84 r.makeInvalid();
85 return r;
86 }
87
93 bool operator==(const Box2D& r) const;
94
100 bool operator!=(const Box2D& r) const;
101
106 void fix();
107
113 bool contains(const Vec<2, double>& p) const;
114
120 bool intersects(const Box2D& other) const;
121
126 void makeInclude(const Vec<2, double>& p);
127
132 void makeInclude(const Box2D& other);
133
138 void makeIntersection(const Box2D& other);
139
145 Box2D intersection(Box2D other) const;
146
152 Box2D extension(Box2D other) const;
153
160 return Box2D(lower + translation_vec, upper + translation_vec);
161 }
162
169 return Box2D(lower + translation_vec, upper + translation_vec);
170 }
171
178 return Box2D(lower - translation_vec, upper - translation_vec);
179 }
180
187 return translated(vec(0.0, trasnalation_in_up_dir));
188 }
189
195 lower += translation_vec;
196 upper += translation_vec;
197 }
198
204 lower += translation_vec;
205 upper -= translation_vec;
206 return *this;
207 }
208
214 lower -= translation_vec;
215 upper -= translation_vec;
216 return *this;
217 }
218
224 lower.vert() += trasnalation_in_up_dir;
225 upper.vert() += trasnalation_in_up_dir;
226 }
227
233 void translateDir(unsigned dir_index, const double trasnalation_in_dir) {
236 }
237
244 Vec<2, double> moveInside(Vec<2, double> p) const;
245
252 friend inline std::ostream& operator<<(std::ostream& out, const Box2D& to_print) {
253 return out << '[' << to_print.lower << ", " << to_print.upper << ']';
254 }
255
262 bool isValid() const { return upper.c0 >= lower.c0 && upper.c1 >= lower.c1; }
263
268 void makeInvalid() {
269 lower = vec(0.0, 0.0);
270 upper = vec(-1.0, -1.0);
271 }
272
277 double getArea() const {
278 Vec<2, double> v = size();
279 return v.c0 * v.c1;
280 }
281
287 inline void flip(size_t flipDir) {
288 assert(flipDir < 2);
289 double temp = lower[flipDir];
290 lower[flipDir] = -upper[flipDir];
291 upper[flipDir] = -temp;
292 }
293
300 inline Box2D flipped(size_t i) const {
301 Box2D res = *this;
302 res.flip(i);
303 return res;
304 }
305
310 const double& left() const { return lower.c0; }
311
316 double& left() { return lower.c0; }
317
322 const double& right() const { return upper.c0; }
323
328 double& right() { return upper.c0; }
329
334 const double& bottom() const { return lower.c1; }
335
340 double& bottom() { return lower.c1; }
341
346 const double& top() const { return upper.c1; }
347
352 double& top() { return upper.c1; }
353
354 void setLeft(double v) { lower.c0 = v; }
355 void setRight(double v) { upper.c0 = v; }
356 void setBottom(double v) { lower.c1 = v; }
357 void setTop(double v) { upper.c1 = v; }
358
359 double getLeft() const { return lower.c0; }
360 double getRight() const { return upper.c0; }
361 double getBottom() const { return lower.c1; }
362 double getTop() const { return upper.c1; }
363};
364
374
377
382 constexpr Vec<3, double> size() const { return upper - lower; }
383
388 constexpr double height() const { return upper.vert() - lower.vert(); }
389
394 constexpr double width() const { return upper.tran() - lower.tran(); }
395
400 constexpr double depth() const { return upper.lon() - lower.lon(); }
401
406 constexpr Vec<3, double> center() const { return 0.5 * (upper + lower); }
407
409 Box3D() {}
410
416 constexpr Box3D(const Vec<3, double>& lower, const Vec<3, double>& upper) : lower(lower), upper(upper) {}
417
423 constexpr Box3D(double x_lo, double y_lo, double z_lo, double x_up, double y_up, double z_up)
424 : lower(x_lo, y_lo, z_lo), upper(x_up, y_up, z_up) {}
425
427 Box3D r;
428 r.makeInvalid();
429 return r;
430 }
431
437 bool operator==(const Box3D& r) const;
438
444 bool operator!=(const Box3D& r) const;
445
450 void fix();
451
457 bool contains(const Vec<3, double>& p) const;
458
464 bool intersects(const Box3D& other) const;
465
470 void makeInclude(const Vec<3, double>& p);
471
476 void makeInclude(const Box3D& other);
477
482 void makeIntersection(const Box3D& other);
483
489 Box3D extension(Box3D other) const;
490
496 Box3D intersection(Box3D other) const;
497
504 return Box3D(lower + translation_vec, upper + translation_vec);
505 }
506
513 return Box3D(lower + translation_vec, upper + translation_vec);
514 }
515
522 return Box3D(lower - translation_vec, upper - translation_vec);
523 }
524
531 Box3D r = *this;
533 return r;
534 }
535
541 lower += translation_vec;
542 upper += translation_vec;
543 }
544
550 lower += translation_vec;
551 upper -= translation_vec;
552 return *this;
553 }
554
560 lower -= translation_vec;
561 upper -= translation_vec;
562 return *this;
563 }
564
570 lower.vert() += trasnalation_in_up_dir;
571 upper.vert() += trasnalation_in_up_dir;
572 }
573
579 void translateDir(unsigned dir_index, const double trasnalation_in_dir) {
582 }
583
588 void makeInclude(const Box2D& other);
589
596 Vec<3, double> moveInside(Vec<3, double> p) const;
597
604 friend inline std::ostream& operator<<(std::ostream& out, const Box3D& to_print) {
605 return out << '[' << to_print.lower << ", " << to_print.upper << ']';
606 }
607
614 bool isValid() const { return upper.c0 >= lower.c0 && upper.c1 >= lower.c1 && upper.c2 >= lower.c2; }
615
620 void makeInvalid() {
621 lower = vec(0.0, 0.0, 0.0);
622 upper = vec(-1.0, -1.0, -1.0);
623 }
624
629 double getArea() const {
630 Vec<3, double> v = size();
631 return v.c0 * v.c1 * v.c2;
632 }
633
639 inline void flip(size_t flipDir) {
640 assert(flipDir < 3);
641 double temp = lower[flipDir];
642 lower[flipDir] = -upper[flipDir];
643 upper[flipDir] = -temp;
644 }
645
652 inline Box3D flipped(size_t i) const {
653 Box3D res = *this;
654 res.flip(i);
655 return res;
656 }
657
662 const double& back() const { return lower.c0; }
663
668 double& back() { return lower.c0; }
669
674 const double& front() const { return upper.c0; }
675
680 double& front() { return upper.c0; }
681
686 const double& left() const { return lower.c1; }
687
692 double& left() { return lower.c1; }
693
698 const double& right() const { return upper.c1; }
699
704 double& right() { return upper.c1; }
705
710 const double& bottom() const { return lower.c2; }
711
716 double& bottom() { return lower.c2; }
717
722 const double& top() const { return upper.c2; }
723
728 double& top() { return upper.c2; }
729
730 void setBack(double v) { lower.c0 = v; }
731 void setFront(double v) { upper.c0 = v; }
732 void setLeft(double v) { lower.c1 = v; }
733 void setRight(double v) { upper.c1 = v; }
734 void setBottom(double v) { lower.c2 = v; }
735 void setTop(double v) { upper.c2 = v; }
736
737 double getBack() const { return lower.c0; }
738 double getFront() const { return upper.c0; }
739 double getLeft() const { return lower.c1; }
740 double getRight() const { return upper.c1; }
741 double getBottom() const { return lower.c2; }
742 double getTop() const { return upper.c2; }
743};
744
749template <int dim> struct Primitive {};
750
754template <> struct PLASK_API Primitive<1> {
756 typedef double DVec;
757
759 static const int dim = 1;
760
762 static const DVec ZERO_VEC;
763
764 enum Direction { DIRECTION = 0 };
765
767 inline static bool vecFuzzyCompare(DVec a, DVec b) { return b - a > POINT_TOLLERANCE; }
768};
769
773template <> struct PLASK_API Primitive<2> {
775 typedef Box2D Box;
776
779
781 static const int dim = 2;
782
784 static const DVec ZERO_VEC;
785
787 static const DVec NAN_VEC;
788
790 static const Box INF_BOX;
791
792 enum Direction { DIRECTION_TRAN = 0, DIRECTION_VERT = 1 };
793
794 static void ensureIsValidDirection(unsigned direction) {
795 if (direction > 1) throw Exception("bad 2D direction index, {0} was given but allowed are: 0, 1.", direction);
796 }
797
799 inline static bool vecFuzzyCompare(const DVec& a, const DVec& b) {
800 return b.c1 - a.c1 > POINT_TOLLERANCE || (a.c1 - b.c1 <= POINT_TOLLERANCE && b.c0 - a.c0 > POINT_TOLLERANCE);
801 }
802};
803
807template <> struct PLASK_API Primitive<3> {
809 typedef Box3D Box;
810
813
815 static const int dim = 3;
816
818 static const DVec ZERO_VEC;
819
821 static const DVec NAN_VEC;
822
824 static const Box INF_BOX;
825
826 enum Direction { DIRECTION_LONG = 0, DIRECTION_TRAN = 1, DIRECTION_VERT = 2 };
827
828 static void ensureIsValidDirection(unsigned direction) {
829 if (direction > 2)
830 throw DimensionError("bad 3D direction index, {} was given but allowed are: 0, 1, 2.", direction);
831 }
832
833 static void ensureIsValid2DDirection(unsigned direction) {
834 if (direction != DIRECTION_TRAN && direction != DIRECTION_VERT)
835 throw DimensionError(
836 "bad 2D direction index, {} was given but allowed are: 1 (DIRECTION_TRAN), 2 (DIRECTION_VERT).",
837 direction);
838 }
839
841 inline static bool vecFuzzyCompare(const DVec& a, const DVec& b) {
842 return b.c2 - a.c2 > POINT_TOLLERANCE || (a.c2 - b.c2 <= POINT_TOLLERANCE &&
843 (b.c1 - a.c1 > POINT_TOLLERANCE || (a.c1 - b.c1 <= POINT_TOLLERANCE &&
844 b.c0 - a.c0 > POINT_TOLLERANCE)));
845 }
846};
847
851
853
855
856template <> struct DirectionWithout<2, Primitive<2>::DIRECTION_TRAN> {
859};
860
861template <> struct DirectionWithout<2, Primitive<2>::DIRECTION_VERT> {
864};
865
866template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_LONG> {
870
871 // should be not usedm but sometimes it is useful to make compilation possible
872 static const Primitive<2>::Direction value2D =
874};
875
876template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_TRAN> {
880
882};
883
884template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_VERT> {
888
890};
891
892} // namespace plask
893
894#endif