PLaSK library

Loading...
Searching...
No Matches
stack.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_STACK_H
15#define PLASK__GEOMETRY_STACK_H
16
17#include "primitives.hpp"
18#include "container.hpp"
19#include <deque>
20
21 namespace plask {
22
29 template <int dim, typename Primitive<dim>::Direction growingDirection = Primitive<dim>::DIRECTION_VERT>
30 struct PLASK_API StackContainerBaseImpl: public GeometryObjectContainer<dim> {
31
32 typedef GeometryObjectContainer<dim> BaseClass;
33
34 static constexpr typename Primitive<dim>::Direction GROWING_DIR = growingDirection;
35
37 typedef typename BaseClass::DVec DVec;
38
40 typedef typename BaseClass::Box Box;
41
43 typedef typename BaseClass::ChildType ChildType;
44
46 typedef typename BaseClass::TranslationT TranslationT;
47
49 typedef typename BaseClass::TranslationVector TranslationVector;
50
51 using BaseClass::children;
52
56 explicit StackContainerBaseImpl(const double baseHeight = 0.0) {
57 stackHeights.push_back(baseHeight);
58 }
59
64 double getBaseHeight() const { return stackHeights.front(); }
65
70 void setBaseHeight(double newBaseHeight);
71
76 void setZeroBefore(std::size_t index);
77
83 void setZeroBefore(const shared_ptr<ChildType>& object, const PathHints* path = 0) {
84 setZeroBefore(this->getChildIndex(object, path));
85 }
86
92 void setZeroBefore(const shared_ptr<ChildType>& object, const PathHints& path) {
93 setZeroBefore(this->getChildIndex(object, path));
94 }
95
101 void alignZeroOn(std::size_t index, double pos = 0.);
102
109 void alignZeroOn(const shared_ptr<ChildType>& object, const PathHints* path = 0, double pos = 0.) {
110 alignZeroOn(this->getChildIndex(object, path), pos);
111 }
112
119 void alignZeroOn(const shared_ptr<ChildType>& object, const PathHints& path, double pos = 0.) {
120 alignZeroOn(this->getChildIndex(object, path), pos);
121 }
122
123 std::size_t getInsertionIndexForHeight(double height) const;
124
130 const shared_ptr<TranslationT> getChildForHeight(double height, shared_ptr<TranslationT>& sec_candidate) const;
131
132 const shared_ptr<TranslationT> getChildForHeight(double height) const {
133 shared_ptr<TranslationT> to_ignore;
134 return getChildForHeight(height, to_ignore);
135 }
136
137 bool contains(const DVec& p) const override;
138
139 shared_ptr<Material> getMaterial(const DVec& p) const override;
140
141 GeometryObject::Subtree getPathsAt(const DVec& point, bool all=false) const override;
142
143 bool removeIfTUnsafe(const std::function<bool(const shared_ptr<TranslationT>& c)>& predicate) override;
144
145 void removeAtUnsafe(std::size_t index) override;
146
148 void onChildChanged(const GeometryObject::Event& evt) override;
149
154 double getHeight() const {
155 return stackHeights.back() - stackHeights.front();
156 }
157
158 protected:
159
164 std::vector<double> stackHeights;
165
173 void calcHeight(const Box& elBoudingBox, double prev_height, double& el_translation, double& next_height) {
174 el_translation = prev_height - elBoudingBox.lower[growingDirection];
175 next_height = elBoudingBox.upper[growingDirection] + el_translation;
176 }
177
185 void calcHeight(const shared_ptr<ChildType>& el, double prev_height, double& el_translation, double& next_height) {
186 calcHeight(el->getBoundingBox(), prev_height, el_translation, next_height);
187 }
188
193 void updateHeight(std::size_t child_index) {
194 calcHeight(children[child_index]->getChild(),
195 stackHeights[child_index],
196 children[child_index]->translation[growingDirection],
197 stackHeights[child_index+1]);
198 }
199
204 void updateAllHeights(std::size_t first_child_index);
205
206 void updateAllHeights();
207
212 void rebuildStackHeights(std::size_t first_child_index = 0);
213
214 void writeXMLAttr(XMLWriter::Element &dest_xml_object, const AxisNames &axes) const override;
215};
216
217 PLASK_API_EXTERN_TEMPLATE_STRUCT(StackContainerBaseImpl<2, Primitive<2>::DIRECTION_VERT>)
218 PLASK_API_EXTERN_TEMPLATE_STRUCT(StackContainerBaseImpl<3, Primitive<3>::DIRECTION_VERT>)
219 PLASK_API_EXTERN_TEMPLATE_STRUCT(StackContainerBaseImpl<2, Primitive<2>::DIRECTION_TRAN>)
220
225 struct PLASK_API ShelfContainer2D: public StackContainerBaseImpl<2, Primitive<2>::DIRECTION_TRAN> {
226
227 typedef StackContainerBaseImpl<2, Primitive<2>::DIRECTION_TRAN> BaseClass;
228
230 typedef typename BaseClass::ChildType ChildType;
231
233 typedef typename BaseClass::TranslationT TranslationT;
234
235 private:
237 //TODO use it, support in remove
238 shared_ptr<TranslationT> resizableGap;
239
240 public:
241
242 ShelfContainer2D(double baseH = 0.0): BaseClass(baseH) {}
243
244 static const char* NAME;
245
246 std::string getTypeName() const override { return NAME; }
247
252 bool isFlat() const;
253
258 void ensureFlat() const {
259 if (!isFlat()) throw Exception("not all items in the shelf have the same height "
260 "(correct heights or set 'flat' to false)");
261 }
262
269 PathHints::Hint add(const shared_ptr<ChildType> &el) {
270 if (el) this->ensureCanHaveAsChild(*el);
271 return addUnsafe(el);
272 }
273
279 PathHints::Hint addGap(double size);
280
281 /*
282 * Try to resize gap which have given index.
283 * @param gap_index
284 */
285 //void resizeGap(std::size_t gap_index, double new_size);
286
293 PathHints::Hint push_back(const shared_ptr<ChildType> &el) { return add(el); }
294
301 PathHints::Hint addUnsafe(const shared_ptr<ChildType>& el);
302
310 PathHints::Hint insertUnsafe(const shared_ptr<ChildType>& el, const std::size_t pos);
311
319 PathHints::Hint insert(const shared_ptr<ChildType>& el, const std::size_t pos) {
320 if (el) this->ensureCanHaveAsChild(*el);
321 return insertUnsafe(el, pos);
322 }
323
331 PathHints::Hint push_front(const shared_ptr<ChildType>& el) {
332 if (el) this->ensureCanHaveAsChild(*el);
333 return insertUnsafe(el, 0);
334 }
335
336 shared_ptr<GeometryObject> changedVersionForChildren(std::vector<std::pair<shared_ptr<ChildType>, Vec<3, double>>>& children_after_change, Vec<3, double>* recomended_translation) const override;
337
338 void writeXMLAttr(XMLWriter::Element &dest_xml_object, const AxisNames &) const override;
339
340 shared_ptr<GeometryObject> shallowCopy() const override;
341
342 shared_ptr<GeometryObject> deepCopy(std::map<const GeometryObject*, shared_ptr<GeometryObject>>& copied) const override;
343
344};
345
346 template <int dim>
347 using StackContainerChildAligner =
348 typename chooseType<dim-2, align::Aligner<Primitive<3>::DIRECTION_TRAN>, align::Aligner<Primitive<3>::DIRECTION_LONG, Primitive<3>::DIRECTION_TRAN> >::type;
349
354//TODO copy constructor
355//TODO remove some redundant code and use one from WithAligners
356 template <int dim>
357 struct PLASK_API StackContainer: public WithAligners< StackContainerBaseImpl<dim>, StackContainerChildAligner<dim> > {
358
359 typedef StackContainerChildAligner<dim> ChildAligner;
360 static const ChildAligner& DefaultAligner();
361
362 typedef typename StackContainerBaseImpl<dim>::ChildType ChildType;
363 typedef typename StackContainerBaseImpl<dim>::TranslationT TranslationT;
364
366 typedef typename StackContainerBaseImpl<dim>::Box Box;
367
368 using StackContainerBaseImpl<dim>::shared_from_this;
369 using StackContainerBaseImpl<dim>::children;
370 using StackContainerBaseImpl<dim>::stackHeights;
371
372 static const char* NAME;
373
374 std::string getTypeName() const override { return NAME; }
375
376 ChildAligner default_aligner;
377
378 private:
379
380 typedef WithAligners< StackContainerBaseImpl<dim>, StackContainerChildAligner<dim> > ParentClass;
381
390 shared_ptr<TranslationT> newTranslation(const shared_ptr<ChildType>& el, const ChildAligner& aligner, double up_trans, const Box& elBB) const;
391
399 shared_ptr<TranslationT> newTranslation(const shared_ptr<ChildType>& el, const ChildAligner& aligner, double up_trans) const;
400
401 public:
402
407 explicit StackContainer(const double baseHeight = 0.0, const ChildAligner& aligner=DefaultAligner()):
408 ParentClass(baseHeight), default_aligner(aligner) {}
409
410 void onChildChanged(const GeometryObject::Event& evt) override;
411
420 PathHints::Hint insertUnsafe(const shared_ptr<ChildType>& el, const std::size_t pos, const ChildAligner& aligner);
421
422 PathHints::Hint insertUnsafe(const shared_ptr<ChildType>& el, const std::size_t pos) {
423 return insertUnsafe(el, pos, default_aligner);
424 }
425
434 PathHints::Hint insert(const shared_ptr<ChildType>& el, const std::size_t pos, const ChildAligner& aligner) {
435 if (el) this->ensureCanHaveAsChild(*el);
436 return insertUnsafe(el, pos, aligner);
437 }
438
439 PathHints::Hint insert(const shared_ptr<ChildType>& el, const std::size_t pos) {
440 return insert(el, pos, default_aligner);
441 }
442
450 PathHints::Hint addUnsafe(const shared_ptr<ChildType>& el, const ChildAligner& aligner);
451
452 PathHints::Hint addUnsafe(const shared_ptr<ChildType>& el) {
453 return addUnsafe(el, default_aligner);
454 }
455
463 PathHints::Hint add(const shared_ptr<ChildType> &el, const ChildAligner& aligner) {
464 if (el) this->ensureCanHaveAsChild(*el);
465 return addUnsafe(el, aligner);
466 }
467
468 PathHints::Hint add(const shared_ptr<ChildType>& el) {
469 return add(el, default_aligner);
470 }
471
479 PathHints::Hint push_back(const shared_ptr<ChildType> &el, const ChildAligner& aligner) {
480 return add(el, aligner);
481 }
482
483 PathHints::Hint push_back(const shared_ptr<ChildType> &el) {
484 return push_back(el, default_aligner);
485 }
486
494 PathHints::Hint push_front(const shared_ptr<ChildType>& el, const ChildAligner& aligner) {
495 if (el) this->ensureCanHaveAsChild(*el);
496 return insertUnsafe(el, 0, aligner);
497 }
498
499 PathHints::Hint push_front(const shared_ptr<ChildType>& el) {
500 return push_front(el, default_aligner);
501 }
502
503 const ChildAligner& getAlignerAt(std::size_t child_no) const {
504 this->ensureIsValidChildNr(child_no, "getAlignerAt");
505 return this->aligners[child_no];
506 }
507
508 /*
509 * Set new aligner.
510 * @param child_no (real) child number for which aligner will be set
511 * @param aligner new aligner for given child, this pointer will be delete by this stack and it can be used only in one stack, for one child
512 */
513 /*void setAlignerAtMove(std::size_t child_no, Aligner* aligner) {
514 this->ensureIsValidChildNr(child_no, "setAlignerAtMove");
515 if (aligners[child_no] == aligner) return; //protected for self assign
516 aligners[child_no] = aligner;
517 aligners[child_no]->align(*children[child_no]);
518 this->fireChanged(GeometryObject::Event::EVENT_RESIZE);
519 }*/
520
521 bool removeIfTUnsafe(const std::function<bool(const shared_ptr<TranslationT>& c)>& predicate) override;
522
523 void removeAtUnsafe(std::size_t index) override;
524
525 //add in reverse order
526 void writeXML(XMLWriter::Element& parent_xml_object, GeometryObject::WriteXMLCallback& write_cb, AxisNames parent_axes) const override;
527
528 shared_ptr<GeometryObject> shallowCopy() const override;
529
530 shared_ptr<GeometryObject> deepCopy(std::map<const GeometryObject*, shared_ptr<GeometryObject>>& copied) const override;
531
532 protected:
533 void writeXMLChildAttr(XMLWriter::Element &dest_xml_child_tag, std::size_t child_index, const AxisNames &axes) const override;
534
535 shared_ptr<GeometryObject> changedVersionForChildren(std::vector<std::pair<shared_ptr<ChildType>, Vec<3, double>>>& children_after_change, Vec<3, double>* recomended_translation) const override;
536
537};
538
539 template <> const StackContainer<2>::ChildAligner& StackContainer<2>::DefaultAligner();
540 template <> const StackContainer<3>::ChildAligner& StackContainer<3>::DefaultAligner();
541
542 PLASK_API_EXTERN_TEMPLATE_STRUCT(StackContainer<2>)
543 PLASK_API_EXTERN_TEMPLATE_STRUCT(StackContainer<3>)
544
545
549 template <typename UpperClass>
550 class PLASK_API MultiStackContainer: public UpperClass {
551
552 static const int DIM = UpperClass::DIM;
553
554 /*
555 * @param a, divider
556 * @return \f$a - \floor{a / divider} * divider\f$
557 */
558 /*static double modulo(double a, double divider) {
559 return a - static_cast<double>( static_cast<int>( a / divider ) ) * divider;
560 }*/
561
562 public:
563 using UpperClass::getChildForHeight;
564 using UpperClass::stackHeights;
565 using UpperClass::children;
566
567 typedef typename StackContainerBaseImpl<DIM>::ChildType ChildType;
568 typedef typename StackContainerBaseImpl<DIM>::TranslationT TranslationT;
569
571 typedef typename UpperClass::DVec DVec;
572
574 typedef typename UpperClass::Box Box;
575
576 protected:
577
578 /*
579 * Get number of all children.
580 * @return number of all children
581 */
582 //std::size_t size() const { return children.size() * repeat_count; }
583
584 /*
585 * Get child with translation.
586 * @param index index of child
587 * @return child with given index
588 */
589 //typename UpperClass::TranslationT& operator[] (std::size_t index) { return children[index % children.size()]; }
590
596 bool reduceHeight(double& height) const;
597
598 public:
599
601 unsigned repeat_count;
602
609 template <typename... UpperCtrArgs>
610 explicit MultiStackContainer(unsigned repeat_count, UpperCtrArgs&&... upperCtrArgs):
611 UpperClass(std::forward<UpperCtrArgs>(upperCtrArgs)...), repeat_count(repeat_count) {}
612
613 //this is not used but, just for case redefine UpperClass::getChildForHeight
614 /*const shared_ptr<TranslationT> getChildForHeight(double height) const {
615 if (!reduceHeight(height)) return nullptr;
616 return UpperClass::getChildForHeight(height);
617 }*/
618
619 //TODO good but unused
620 //virtual bool intersects(const Box& area) const;
621
622 Box getBoundingBox() const override;
623
624 Box getRealBoundingBox() const override;
625
626 void getBoundingBoxesToVec(const GeometryObject::Predicate& predicate, std::vector<Box>& dest, const PathHints* path = 0) const override;
627
628 void getObjectsToVec(const GeometryObject::Predicate& predicate, std::vector< shared_ptr<const GeometryObject> >& dest, const PathHints* path = 0) const override;
629
630 void getPositionsToVec(const GeometryObject::Predicate& predicate, std::vector<DVec>& dest, const PathHints* path = 0) const override;
631
632 // void extractToVec(const GeometryObject::Predicate &predicate, std::vector< shared_ptr<const GeometryObjectD<dim> > >& dest, const PathHints *path = 0) const;
633
634 GeometryObject::Subtree getPathsTo(const GeometryObject& el, const PathHints* path = 0) const override;
635
636 GeometryObject::Subtree getPathsAt(const DVec& point, bool all=false) const override;
637
638 bool contains(const DVec& p) const override;
639
640 shared_ptr<Material> getMaterial(const DVec& p) const override;
641
642 std::size_t getChildrenCount() const override { return children.size() * repeat_count; }
643
644 shared_ptr<GeometryObject> getChildNo(std::size_t child_no) const override;
645
646 std::size_t getRealChildrenCount() const override;
647
648 shared_ptr<GeometryObject> getRealChildNo(std::size_t child_no) const override;
649
650 unsigned getRepeatCount() const { return repeat_count; }
651
652 void setRepeatCount(unsigned new_repeat_count) {
653 if (repeat_count == new_repeat_count) return;
654 repeat_count = new_repeat_count;
655 this->fireChildrenChanged(); //TODO should this be called? or simple change?
656 }
657
658 shared_ptr<GeometryObject> shallowCopy() const override;
659
660 shared_ptr<GeometryObject> deepCopy(std::map<const GeometryObject*, shared_ptr<GeometryObject>>& copied) const override;
661
662 void addPointsAlongToSet(std::set<double>& points,
663 Primitive<3>::Direction direction,
664 unsigned max_steps,
665 double min_step_size) const override;
666
667 void addLineSegmentsToSet(std::set<typename GeometryObjectD<UpperClass::DIM>::LineSegment>& segments,
668 unsigned max_steps,
669 double min_step_size) const override;
670
671 protected:
672 void writeXMLAttr(XMLWriter::Element &dest_xml_object, const AxisNames &axes) const override;
673
674 shared_ptr<GeometryObject> changedVersionForChildren(std::vector<std::pair<shared_ptr<ChildType>, Vec<3, double>>>& children_after_change, Vec<3, double>* recomended_translation) const override;
675
676};
677
678
679} // namespace plask
680
681
682#endif // STACK_H