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
28extern PLASK_API const char* const DIRECTION_NAMES[];
29
39
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
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
162 return Box2D(lower + translation_vec, upper + translation_vec);
163 }
164
171 return Box2D(lower + translation_vec, upper + translation_vec);
172 }
173
180 return Box2D(lower - translation_vec, upper - translation_vec);
181 }
182
189 return translated(vec(0.0, trasnalation_in_up_dir));
190 }
191
197 lower += translation_vec;
198 upper += translation_vec;
199 }
200
206 lower += translation_vec;
207 upper -= translation_vec;
208 return *this;
209 }
210
216 lower -= translation_vec;
217 upper -= translation_vec;
218 return *this;
219 }
220
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) {
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
376
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
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
506 return Box3D(lower + translation_vec, upper + translation_vec);
507 }
508
515 return Box3D(lower + translation_vec, upper + translation_vec);
516 }
517
524 return Box3D(lower - translation_vec, upper - translation_vec);
525 }
526
533 Box3D r = *this;
535 return r;
536 }
537
543 lower += translation_vec;
544 upper += translation_vec;
545 }
546
552 lower += translation_vec;
553 upper -= translation_vec;
554 return *this;
555 }
556
562 lower -= translation_vec;
563 upper -= translation_vec;
564 return *this;
565 }
566
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) {
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
751template <int dim> struct Primitive {};
752
756template <> 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
775template <> struct PLASK_API Primitive<2> {
777 typedef Box2D Box;
778
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
809template <> struct PLASK_API Primitive<3> {
811 typedef Box3D Box;
812
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
853
855
857
858template <> struct DirectionWithout<2, Primitive<2>::DIRECTION_TRAN> {
861};
862
863template <> struct DirectionWithout<2, Primitive<2>::DIRECTION_VERT> {
866};
867
868template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_LONG> {
872
873 // should be not usedm but sometimes it is useful to make compilation possible
874 static const Primitive<2>::Direction value2D =
876};
877
878template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_TRAN> {
882
884};
885
886template <> struct DirectionWithout<3, Primitive<3>::DIRECTION_VERT> {
890
892};
893
894} // namespace plask
895
896#if FMT_VERSION >= 90000
897template <> struct fmt::formatter<plask::Box2D> : ostream_formatter {};
898template <> struct fmt::formatter<plask::Box3D> : ostream_formatter {};
899#endif
900
901#endif