PLaSK library

Loading...
Searching...
No Matches
align.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__GEOMETRY_ALIGN_H
15#define PLASK__GEOMETRY_ALIGN_H
16
21#include "transform.hpp"
22#include <boost/lexical_cast.hpp>
23#include "../utils/xml.hpp"
24#include "../memory.hpp"
25#include "../utils/metaprog.hpp"
26
27 namespace plask {
28
29 namespace align {
30
34 typedef Primitive<3>::Direction Direction;
35
37 template <Direction direction>
38 struct DirectionTo2D {
39 //static_assert(false, "given 3D direction cannot be converted to 2D direction");
40};
41
42 template <>
43 struct DirectionTo2D<Primitive<3>::DIRECTION_TRAN> {
44 enum { value = 0 };
45};
46
47 template <>
48 struct DirectionTo2D<Primitive<3>::DIRECTION_VERT> {
49 enum { value = 1 };
50};
51
52
59 template <Direction _direction>
60 struct AlignerImpl: public Printable {
61
63 static const Direction direction = _direction;
64
66 double coordinate;
67
72 AlignerImpl(double coordinate): coordinate(coordinate) {}
73
74 virtual ~AlignerImpl() {}
75
81 virtual double getAlign(double low, double hi) const = 0;
82
87 virtual bool useBounds() const { return true; }
88
96 inline double align(Translation<3>& toAlign, const Box3D& childBoundingBox) const {
97 return toAlign.translation[direction] = this->getAlign(childBoundingBox.lower[direction], childBoundingBox.upper[direction]);
98 }
99
106 virtual double align(Translation<3>& toAlign) const {
107 if (this->useBounds() && toAlign.getChild())
108 return align(toAlign, toAlign.getChild()->getBoundingBox());
109 else
110 return toAlign.translation[direction] = this->getAlign(0.0, 0.0);
111 }
112
118 virtual std::string key(const AxisNames& axis_names) const = 0;
119
125 std::map<std::string,double> asDict(const AxisNames& axis_names) const {
126 std::map<std::string,double> dict;
127 dict[key(axis_names)] = this->coordinate;
128 return dict;
129 }
130
136 void writeToXML(XMLElement& dest, const AxisNames& axis_names) const {
137 dest.attr(key(axis_names), this->coordinate);
138 }
139
140};
141
142 template <Direction _direction>
143 struct AlignerBase: public HolderRef<AlignerImpl<_direction>> {
144
145 AlignerBase() {}
146
147 AlignerBase(AlignerImpl<_direction>* impl): HolderRef<AlignerImpl<_direction>>(impl) {}
148
150 static const Direction direction = _direction;
151
156 double getCoordinate() const { return this->held->coordinate; }
157
163 double getAlign(double low, double hi) const { return this->held->getAlign(low, hi); }
164
169 bool useBounds() const { return this->held->useBounds(); }
170
178 double align(Translation<3>& toAlign, const Box3D& childBoundingBox) const {
179 return this->held->align(toAlign, childBoundingBox);
180 }
181
188 virtual double align(Translation<3>& toAlign) const {
189 return this->held->align(toAlign);
190 }
191
197 virtual std::string key(const AxisNames& axis_names) const { return this->held->key(axis_names); }
198
204 std::map<std::string,double> asDict(const AxisNames& axis_names) const {
205 return this->held->asDict(axis_names);
206 }
207
208
214 void writeToXML(XMLElement& dest, const AxisNames& axis_names) const {
215 this->held->writeToXML(dest, axis_names);
216 }
217
224 friend inline std::ostream& operator<<(std::ostream& out, const AlignerBase<_direction>& to_print) {
225 return out << *to_print.held;
226 }
227
232 std::string str() const { return this->held; }
233
234};
235
236 template <Direction... directions> struct Aligner;
237
241 template <Direction _direction>
242 struct Aligner<_direction>: public AlignerBase<_direction> {
243
244 static const Direction direction = _direction;
245
246 enum { direction2D = DirectionTo2D<_direction>::value };
247
248 Aligner<_direction>() {}
249
250 Aligner<_direction>(AlignerImpl<_direction>* impl): AlignerBase<_direction>(impl) {}
251
252 using AlignerBase<_direction>::align;
253
261 void align(Translation<2>& toAlign, const Box2D& childBoundingBox) const {
262 toAlign.translation[direction2D] = this->getAlign(childBoundingBox.lower[direction2D], childBoundingBox.upper[direction2D]);
263 }
264
271 void align(Translation<2>& toAlign) const {
272 if (this->useBounds() && toAlign.getChild())
273 this->align(toAlign, toAlign.getChild()->getBoundingBox());
274 else
275 toAlign.translation[direction2D] = this->getAlign(0.0, 0.0);
276 }
277
278};
279
280 template <>
281 struct Aligner<Primitive<3>::DIRECTION_LONG>: public AlignerBase<Primitive<3>::DIRECTION_LONG> {
282 Aligner() {}
283 Aligner(AlignerImpl<direction>* impl): AlignerBase<Primitive<3>::DIRECTION_LONG>(impl) {}
284};
285
286 namespace details {
287
291 template <Direction direction>
292 struct PositionAlignerImpl: public AlignerImpl<direction> {
293
294 PositionAlignerImpl(double translation): AlignerImpl<direction>(translation) {}
295
296 double getAlign(double PLASK_UNUSED(low), double PLASK_UNUSED(hi)) const override {
297 return this->coordinate;
298 }
299
300 bool useBounds() const override { return false; }
301
302 void print(std::ostream& out) const override { out << "align object position along axis " << direction << " to " << this->coordinate; }
303
304 std::string key(const AxisNames& axis_names) const override { return axis_names[direction]; }
305};
306
307} // namespace details
308
312 template <Direction _direction1, Direction _direction2>
313 struct AlignerBase2D {
314
315 static_assert(_direction1 < _direction2, "Wrong Aligner template parameters, two different directions are required and first direction must have lower index than second one. Try swapping Aligner template parameters.");
316
317 Aligner<_direction1> dir1aligner;
318 Aligner<_direction2> dir2aligner;
319
320 static const Direction direction1 = _direction1, direction2 = _direction2;
321
322 AlignerBase2D() {}
323
324 AlignerBase2D(const Aligner<direction1>& dir1aligner, const Aligner<direction2>& dir2aligner)
325 : dir1aligner(dir1aligner), dir2aligner(dir2aligner) {}
326
327 /* Aligner(const Aligner<direction1, direction2>& toCopy)
328 : dir1aligner(toCopy.dir1aligner->clone()), dir2aligner(toCopy.dir2aligner->clone()) {}
329
330 Aligner(const Aligner<direction2, direction1>& toCopy)
331 : dir1aligner(toCopy.dir2aligner->clone()), dir2aligner(toCopy.dir1aligner->clone()) {}
332
333 Aligner(Aligner<direction1, direction2>&& toMove)
334 : dir1aligner(toMove.dir1aligner), dir2aligner(toMove.dir2aligner) {
335 toMove.dir1aligner = 0; toMove.dir2aligner = 0;
336 }
337
338 Aligner(Aligner<direction2, direction1>&& toMove)
339 : dir1aligner(toMove.dir2aligner), dir2aligner(toMove.dir1aligner) {
340 toMove.dir1aligner = 0; toMove.dir2aligner = 0;
341 }*/
342
347 bool useBounds() const { return dir1aligner.useBounds() || dir2aligner.useBounds(); }
348
356 virtual void align(Translation<3>& toAlign, const Box3D& childBoundingBox) const {
357 toAlign.translation[direction1] =
358 dir1aligner.getAlign(childBoundingBox.lower[direction1], childBoundingBox.upper[direction1]);
359 toAlign.translation[direction2] =
360 dir2aligner.getAlign(childBoundingBox.lower[direction2], childBoundingBox.upper[direction2]);
361 }
362
369 virtual void align(Translation<3>& toAlign) const {
370 if (useBounds() && toAlign.getChild())
371 align(toAlign, toAlign.getChild()->getBoundingBox());
372 else {
373 toAlign.translation[direction1] = dir1aligner.getAlign(0.0, 0.0);
374 toAlign.translation[direction2] = dir2aligner.getAlign(0.0, 0.0);
375 }
376 }
377
384 friend inline std::ostream& operator<<(std::ostream& out, const Aligner<_direction1,_direction2>& to_print) {
385 return out << to_print.dir1aligner << ", " << to_print.dir2aligner;
386 }
387
392 std::string str() const { return boost::lexical_cast<std::string>(*this); }
393
399 virtual std::map<std::string,double> asDict(const AxisNames& axis_names) const {
400 std::map<std::string,double> dict;
401 dict[dir1aligner.key(axis_names)] = dir1aligner.getCoordinate();
402 dict[dir2aligner.key(axis_names)] = dir2aligner.getCoordinate();
403 return dict;
404 }
405
411 virtual void writeToXML(XMLElement& dest, const AxisNames& axis_names) const {
412 dir1aligner.writeToXML(dest, axis_names);
413 dir2aligner.writeToXML(dest, axis_names);
414 }
415
416 bool isNull() { return dir1aligner.isNull() || dir2aligner.isNull(); }
417
418};
419
423 template <Direction _direction1, Direction _direction2>
424 struct Aligner<_direction1, _direction2>: public AlignerBase2D<_direction1, _direction2> {
425
426 Aligner() {}
427
428 Aligner(const Aligner<_direction1>& dir1aligner, const Aligner<_direction2>& dir2aligner)
429 : AlignerBase2D<_direction1, _direction2>(dir1aligner, dir2aligner) {}
430
431};
432
438 template <>
439 struct Aligner<Primitive<3>::DIRECTION_TRAN, Primitive<3>::DIRECTION_VERT>: public AlignerBase2D<Primitive<3>::DIRECTION_TRAN, Primitive<3>::DIRECTION_VERT> {
440
441 Aligner() {}
442
443 Aligner(const Aligner<Primitive<3>::DIRECTION_TRAN>& dir1aligner, const Aligner<Primitive<3>::DIRECTION_VERT>& dir2aligner)
444 : AlignerBase2D<Primitive<3>::DIRECTION_TRAN, Primitive<3>::DIRECTION_VERT>(dir1aligner, dir2aligner) {}
445
446 using AlignerBase2D<Primitive<3>::DIRECTION_TRAN, Primitive<3>::DIRECTION_VERT>::align;
447
455 void align(Translation<2>& toAlign, const Box2D& childBoundingBox) const {
456 toAlign.translation[0] = this->dir1aligner.getAlign(childBoundingBox.lower[0], childBoundingBox.upper[0]);
457 toAlign.translation[1] = this->dir2aligner.getAlign(childBoundingBox.lower[1], childBoundingBox.upper[1]);
458 }
459
466 void align(Translation<2>& toAlign) const {
467 if (this->useBounds() && toAlign.getChild())
468 this->align(toAlign, toAlign.getChild()->getBoundingBox());
469 else {
470 toAlign.translation[0] = this->dir1aligner.getAlign(0.0, 0.0);
471 toAlign.translation[1] = this->dir2aligner.getAlign(0.0, 0.0);
472 }
473 }
474
475};
476
477 typedef Aligner<Primitive<3>::DIRECTION_TRAN, Primitive<3>::DIRECTION_VERT> Aligner2D;
478
482 template <>
483 struct Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1), Primitive<3>::Direction(2)> {
484
485 Aligner<Primitive<3>::DIRECTION_LONG> dir1aligner;
486 Aligner<Primitive<3>::DIRECTION_TRAN> dir2aligner;
487 Aligner<Primitive<3>::DIRECTION_VERT> dir3aligner;
488
489 Aligner() {}
490
491 Aligner(const Aligner<Primitive<3>::DIRECTION_LONG>& dir1aligner, const Aligner<Primitive<3>::DIRECTION_TRAN>& dir2aligner, const Aligner<Primitive<3>::DIRECTION_VERT>& dir3aligner)
492 : dir1aligner(dir1aligner), dir2aligner(dir2aligner), dir3aligner(dir3aligner) {}
493
498 bool useBounds() const { return dir1aligner.useBounds() || dir2aligner.useBounds() || dir3aligner.useBounds(); }
499
507 virtual void align(Translation<3>& toAlign, const Box3D& childBoundingBox) const {
508 toAlign.translation[0] = dir1aligner.getAlign(childBoundingBox.lower[0], childBoundingBox.upper[0]);
509 toAlign.translation[1] = dir2aligner.getAlign(childBoundingBox.lower[1], childBoundingBox.upper[1]);
510 toAlign.translation[2] = dir3aligner.getAlign(childBoundingBox.lower[2], childBoundingBox.upper[2]);
511 }
512
519 virtual void align(Translation<3>& toAlign) const {
520 if (useBounds() && toAlign.getChild())
521 align(toAlign, toAlign.getChild()->getBoundingBox());
522 else {
523 toAlign.translation[0] = dir1aligner.getAlign(0.0, 0.0);
524 toAlign.translation[1] = dir2aligner.getAlign(0.0, 0.0);
525 toAlign.translation[2] = dir3aligner.getAlign(0.0, 0.0);
526 }
527 }
528
535 friend inline std::ostream& operator<<(std::ostream& out, const Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1), Primitive<3>::Direction(2)>& to_print) {
536 return out << to_print.dir1aligner << ", " << to_print.dir2aligner << ", " << to_print.dir3aligner;
537 }
538
543 std::string str() const { return boost::lexical_cast<std::string>(*this); }
544
550 virtual std::map<std::string,double> asDict(const AxisNames& axis_names) const {
551 std::map<std::string,double> dict;
552 dict[dir1aligner.key(axis_names)] = dir1aligner.getCoordinate();
553 dict[dir2aligner.key(axis_names)] = dir2aligner.getCoordinate();
554 dict[dir3aligner.key(axis_names)] = dir3aligner.getCoordinate();
555 return dict;
556 }
557
563 virtual void writeToXML(XMLElement& dest, const AxisNames& axis_names) const {
564 dir1aligner.writeToXML(dest, axis_names);
565 dir2aligner.writeToXML(dest, axis_names);
566 dir3aligner.writeToXML(dest, axis_names);
567 }
568
569 bool isNull() { return dir1aligner.isNull() || dir2aligner.isNull() || dir3aligner.isNull(); }
570
571};
572
573
574
575 typedef Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1), Primitive<3>::Direction(2)> Aligner3D;
576
578 template <int dim> using AlignerD = typename chooseType<dim-2, Aligner2D, Aligner3D>::type;
579
580//two 1D aligners gives 2D aligner
581 inline Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1)> operator&(const Aligner<Primitive<3>::Direction(0)>& dir1aligner, const Aligner<Primitive<3>::Direction(1)>& dir2aligner) {
582 return Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1)>(dir1aligner, dir2aligner);
583}
584
585 inline Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1)> operator&(const Aligner<Primitive<3>::Direction(1)>& dir1aligner, const Aligner<Primitive<3>::Direction(0)>& dir2aligner) {
586 return Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1)>(dir2aligner, dir1aligner);
587}
588
589 inline Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(2)> operator&(const Aligner<Primitive<3>::Direction(0)>& dir1aligner, const Aligner<Primitive<3>::Direction(2)>& dir2aligner) {
590 return Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(2)>(dir1aligner, dir2aligner);
591}
592
593 inline Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(2)> operator&(const Aligner<Primitive<3>::Direction(2)>& dir1aligner, const Aligner<Primitive<3>::Direction(0)>& dir2aligner) {
594 return Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(2)>(dir2aligner, dir1aligner);
595}
596
597 inline Aligner<Primitive<3>::Direction(1), Primitive<3>::Direction(2)> operator&(const Aligner<Primitive<3>::Direction(1)>& dir1aligner, const Aligner<Primitive<3>::Direction(2)>& dir2aligner) {
598 return Aligner<Primitive<3>::Direction(1), Primitive<3>::Direction(2)>(dir1aligner, dir2aligner);
599}
600
601 inline Aligner<Primitive<3>::Direction(1), Primitive<3>::Direction(2)> operator&(const Aligner<Primitive<3>::Direction(2)>& dir1aligner, const Aligner<Primitive<3>::Direction(1)>& dir2aligner) {
602 return Aligner<Primitive<3>::Direction(1), Primitive<3>::Direction(2)>(dir2aligner, dir1aligner);
603}
604
605//1D aligner & 2D aligner = 3D aligner
606 inline Aligner3D operator&(const Aligner<Primitive<3>::Direction(1), Primitive<3>::Direction(2)>& dir12aligner, const Aligner<Primitive<3>::Direction(0)>& dir0aligner) {
607 return Aligner3D(dir0aligner, dir12aligner.dir1aligner, dir12aligner.dir2aligner);
608}
609
610 inline Aligner3D operator&(const Aligner<Primitive<3>::Direction(0)>& dir0aligner, const Aligner<Primitive<3>::Direction(1), Primitive<3>::Direction(2)>& dir12aligner) {
611 return dir12aligner & dir0aligner;
612}
613
614 inline Aligner3D operator&(const Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(2)>& dir02aligner, const Aligner<Primitive<3>::Direction(1)>& dir1aligner) {
615 return Aligner3D(dir02aligner.dir1aligner, dir1aligner, dir02aligner.dir2aligner);
616}
617
618 inline Aligner3D operator&(const Aligner<Primitive<3>::Direction(1)>& dir1aligner, const Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(2)>& dir02aligner) {
619 return dir02aligner & dir1aligner;
620}
621
622 inline Aligner3D operator&(const Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1)>& dir01aligner, const Aligner<Primitive<3>::Direction(2)>& dir2aligner) {
623 return Aligner3D(dir01aligner.dir1aligner, dir01aligner.dir2aligner, dir2aligner);
624}
625
626 inline Aligner3D operator&(const Aligner<Primitive<3>::Direction(2)>& dir2aligner, const Aligner<Primitive<3>::Direction(0), Primitive<3>::Direction(1)>& dir01aligner) {
627 return dir01aligner & dir2aligner;
628}
629
630
631 namespace details {
632
633 typedef double alignStrategy(double lo, double hi, double coordinate);
634 inline double lowToCoordinate(double lo, double /*hi*/, double coordinate) { return coordinate -lo; }
635 inline double hiToCoordinate(double /*lo*/, double hi, double coordinate) { return coordinate -hi; }
636 inline double centerToCoordinate(double lo, double hi, double coordinate) { return coordinate -(lo+hi)/2.0; }
637
638 struct LEFT { static constexpr const char* value = "left"; };
639 struct RIGHT { static constexpr const char* value = "right"; };
640 struct FRONT { static constexpr const char* value = "front"; };
641 struct BACK { static constexpr const char* value = "back"; };
642 struct TOP { static constexpr const char* value = "top"; };
643 struct BOTTOM { static constexpr const char* value = "bottom"; };
644 struct TRAN_CENTER { static constexpr const char* value = "trancenter"; };
645 struct LON_CENTER { static constexpr const char* value = "longcenter"; };
646 struct VERT_CENTER { static constexpr const char* value = "vertcenter"; };
647
648 template <Direction direction, alignStrategy strategy, typename name_tag>
649 struct AlignerCustomImpl: public AlignerImpl<direction> {
650
651 AlignerCustomImpl(double coordinate): AlignerImpl<direction>(coordinate) {}
652
653 double getAlign(double low, double hi) const override {
654 return strategy(low, hi, this->coordinate);
655 }
656
657 /*virtual AlignerImpl<direction, strategy, name_tag>* clone() const {
658 return new AlignerImpl<direction, strategy, name_tag>(this->coordinate);
659 }*/
660
661 void print(std::ostream& out) const override { out << "align " << name_tag::value << " to " << this->coordinate; }
662
663 std::string key(const AxisNames& /*axis_names*/) const override { return name_tag::value; }
664};
665
666} // namespace details
667
668// 1D tran. aligners:
669 inline Aligner<Primitive<3>::DIRECTION_TRAN> left(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_TRAN, details::lowToCoordinate, details::LEFT>(coordinate); }
670 inline Aligner<Primitive<3>::DIRECTION_TRAN> right(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_TRAN, details::hiToCoordinate, details::RIGHT>(coordinate); }
671 inline Aligner<Primitive<3>::DIRECTION_TRAN> tranCenter(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_TRAN, details::centerToCoordinate, details::TRAN_CENTER>(coordinate); }
672 inline Aligner<Primitive<3>::DIRECTION_TRAN> center(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_TRAN, details::centerToCoordinate, details::TRAN_CENTER>(coordinate); }
673 inline Aligner<Primitive<3>::DIRECTION_TRAN> tran(double coordinate) { return new details::PositionAlignerImpl<Primitive<3>::DIRECTION_TRAN>(coordinate); }
674
675// 1D long. aligners:
676 inline Aligner<Primitive<3>::DIRECTION_LONG> front(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_LONG, details::hiToCoordinate, details::FRONT>(coordinate); }
677 inline Aligner<Primitive<3>::DIRECTION_LONG> back(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_LONG, details::lowToCoordinate, details::BACK>(coordinate); }
678 inline Aligner<Primitive<3>::DIRECTION_LONG> lonCenter(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_LONG, details::centerToCoordinate, details::LON_CENTER>(coordinate); }
679 inline Aligner<Primitive<3>::DIRECTION_LONG> lon(double coordinate) { return new details::PositionAlignerImpl<Primitive<3>::DIRECTION_LONG>(coordinate); }
680
681// 1D vert. aligners:
682 inline Aligner<Primitive<3>::DIRECTION_VERT> bottom(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_VERT, details::lowToCoordinate, details::BOTTOM>(coordinate); }
683 inline Aligner<Primitive<3>::DIRECTION_VERT> top(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_VERT, details::hiToCoordinate, details::TOP>(coordinate); }
684 inline Aligner<Primitive<3>::DIRECTION_VERT> vertCenter(double coordinate) { return new details::AlignerCustomImpl<Primitive<3>::DIRECTION_VERT, details::centerToCoordinate, details::VERT_CENTER>(coordinate); }
685 inline Aligner<Primitive<3>::DIRECTION_VERT> vert(double coordinate) { return new details::PositionAlignerImpl<Primitive<3>::DIRECTION_VERT>(coordinate); }
686
687 inline Aligner2D fromVector(const Vec<2, double>& v) {
688 return tran(v.tran()) & vert(v.vert());
689}
690
691 inline Aligner3D fromVector(const Vec<3, double>& v) {
692 return lon(v.lon()) & tran(v.tran()) & vert(v.vert());
693}
694
695 template<Primitive<3>::Direction dir>
696 using LowerBoundImpl = details::AlignerCustomImpl<dir, details::lowToCoordinate, typename chooseType<dir, details::BACK, details::LEFT, details::BOTTOM>::type>;
697
703 template <Primitive<3>::Direction dir> inline Aligner<dir> lowerBoundZero() { return new LowerBoundImpl<dir>(0.0); }
704 template <Primitive<3>::Direction dir1, Primitive<3>::Direction dir2> inline Aligner<dir1, dir2> lowerBoundZero() { return lowerBoundZero<dir1> & lowerBoundZero<dir2>; }
705
706 typedef std::function<plask::optional<double>(const std::string& name)> Dictionary;
707
708 namespace details {
709 PLASK_API Aligner<Primitive<3>::DIRECTION_TRAN> transAlignerFromDictionary(Dictionary dic, const std::string& axis_name);
710 PLASK_API Aligner<Primitive<3>::DIRECTION_LONG> lonAlignerFromDictionary(Dictionary dic, const std::string& axis_name);
711 PLASK_API Aligner<Primitive<3>::DIRECTION_VERT> vertAlignerFromDictionary(Dictionary dic, const std::string& axis_name);
712}
713
723 template <Direction direction>
724 Aligner<direction> fromDictionary(Dictionary dictionary, const std::string& axis_name);
725
726 template <>
727 inline Aligner<Primitive<3>::DIRECTION_TRAN> fromDictionary<Primitive<3>::DIRECTION_TRAN>(Dictionary dictionary, const std::string& axis_name) {
728 return details::transAlignerFromDictionary(dictionary, axis_name);
729}
730
731 template <>
732 inline Aligner<Primitive<3>::DIRECTION_LONG> fromDictionary<Primitive<3>::DIRECTION_LONG>(Dictionary dictionary, const std::string& axis_name) {
733 return details::lonAlignerFromDictionary(dictionary, axis_name);
734}
735
736 template <>
737 inline Aligner<Primitive<3>::DIRECTION_VERT> fromDictionary<Primitive<3>::DIRECTION_VERT>(Dictionary dictionary, const std::string& axis_name) {
738 return details::vertAlignerFromDictionary(dictionary, axis_name);
739}
740
750 template <Direction direction>
751 Aligner<direction> fromDictionary(Dictionary dic, const AxisNames& axis_names) {
752 return fromDictionary<direction>(dic, axis_names[direction]);
753}
754
765 template <Direction direction>
766 Aligner<direction> fromDictionary(Dictionary dictionary, const AxisNames& axis_names, Aligner<direction> default_aligner) {
767 Aligner<direction> result = fromDictionary<direction>(dictionary, axis_names[direction]);
768 if (result.isNull()) result = default_aligner;
769 return result;
770}
771
775 struct DictionaryFromXML {
776 const XMLReader& reader;
777 DictionaryFromXML(const XMLReader& reader): reader(reader) {}
778 plask::optional<double> operator()(const std::string& s) const { return reader.getAttribute<double>(s); }
779};
780
781 template <Direction direction>
782 inline Aligner<direction> fromXML(const XMLReader& reader, const std::string& axis_name) {
783 return fromDictionary<direction>(DictionaryFromXML(reader), axis_name);
784}
785
786 template <Direction direction>
787 inline Aligner<direction> fromXML(const XMLReader& reader, const AxisNames& axis_names) {
788 return fromXML<direction>(reader, axis_names[direction]);
789}
790
791 template <Direction direction>
792 inline Aligner<direction> fromXML(const XMLReader& reader, const AxisNames& axis_names, Aligner<direction> default_aligner) {
793 return fromDictionary<direction>(DictionaryFromXML(reader), axis_names, default_aligner);
794}
795
805 template <Direction direction1, Direction direction2>
806 inline Aligner<direction1, direction2> fromDictionary(Dictionary dic, const AxisNames& axes) {
807 Aligner<direction1> a1 = fromDictionary<direction1>(dic, axes);
808 if (a1.isNull()) throw Exception("no aligner for axis{0} defined.", int(direction1));
809 Aligner<direction2> a2 = fromDictionary<direction2>(dic, axes);
810 if (a2.isNull()) throw Exception("no aligner for axis{0} defined.", int(direction2));
811 return Aligner<direction1, direction2>(a1, a2);
812}
813
823 template <Direction direction1, Direction direction2>
824 inline Aligner<direction1, direction2> fromXML(const XMLReader& reader, const AxisNames& axes) {
825 return fromDictionary<direction1, direction2>(DictionaryFromXML(reader), axes);
826}
827
837 template <Direction direction1, Direction direction2>
838 inline Aligner<direction1, direction2> fromDictionary(Dictionary dictionary, const AxisNames& axes, Aligner<direction1, direction2> default2D) {
839 return Aligner<direction1, direction2>(fromDictionary(dictionary, axes, default2D.dir1aligner), fromDictionary(dictionary, axes, default2D.dir2aligner));
840}
841
851 template <Direction direction1, Direction direction2>
852 inline Aligner<direction1, direction2> fromXML(const XMLReader& reader, const AxisNames& axes, Aligner<direction1, direction2> default2D) {
853 return fromDictionary<direction1, direction2>(DictionaryFromXML(reader), axes, default2D);
854}
855
865 template <Direction direction1, Direction direction2, Direction direction3>
866 inline Aligner3D fromDictionary(Dictionary dictionary, const AxisNames& axis_names) {
867 Aligner<Primitive<3>::Direction(0)> a0 = fromDictionary<Primitive<3>::Direction(0)>(dictionary, axis_names);
868 if (a0.isNull()) throw Exception("no aligner for axis{0} defined.", 0);
869 Aligner<Primitive<3>::Direction(1)> a1 = fromDictionary<Primitive<3>::Direction(1)>(dictionary, axis_names);
870 if (a1.isNull()) throw Exception("no aligner for axis{0} defined.", 1);
871 Aligner<Primitive<3>::Direction(2)> a2 = fromDictionary<Primitive<3>::Direction(2)>(dictionary, axis_names);
872 if (a2.isNull()) throw Exception("no aligner for axis{0} defined.", 2);
873 return Aligner3D(a0, a1, a2);
874}
875
885 template <Direction direction1, Direction direction2, Direction direction3>
886 inline Aligner3D fromXML(const XMLReader& reader, const AxisNames& axes) {
887 return fromDictionary<direction1,direction2,direction3>(DictionaryFromXML(reader), axes);
888}
889
899 template <Direction direction1, Direction direction2, Direction direction3>
900 inline Aligner3D fromDictionary(Dictionary dic, const AxisNames& axes, Aligner<direction1,direction2,direction3> default3D) {
901 return Aligner3D(fromDictionary(dic, axes, default3D.dir1aligner), fromDictionary(dic, axes, default3D.dir2aligner), fromDictionary(dic, axes, default3D.dir3aligner));
902}
903
913 template <Direction direction1, Direction direction2, Direction direction3>
914 inline Aligner3D fromXML(const XMLReader& reader, const AxisNames& axes, Aligner<direction1,direction2,direction3> default3D) {
915 return fromDictionary(DictionaryFromXML(reader), axes, default3D);
916}
917
931 template <typename TranslationT, typename Aligner1T, typename Aligner2T>
932 void align(TranslationT& toAlign, const Aligner1T& aligner1, const Aligner2T& aligner2) {
933 if ((aligner1.useBounds() || aligner2.useBounds()) && toAlign.getChild()) {
934 auto bb = toAlign.getChild()->getBoundingBox();
935 aligner1.align(toAlign, bb);
936 aligner2.align(toAlign, bb);
937 } else {
938 aligner1.align(toAlign);
939 aligner2.align(toAlign);
940 }
941}
942
943} // namespace align
944} // namespace plask
945
946#endif // PLASK__GEOMETRY_ALIGN_H