PLaSK library

Loading...
Searching...
No Matches
container.cpp
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#include "container.hpp"
15
16 namespace plask {
17
18 template <int dim>
19 void GeometryObjectContainer<dim>::writeXMLChildAttr(XMLWriter::Element&, std::size_t, const AxisNames&) const {
20 // do nothing
21}
22
23 template <int dim>
24 void GeometryObjectContainer<dim>::writeXML(XMLWriter::Element& parent_xml_object,
25 GeometryObject::WriteXMLCallback& write_cb,
26 AxisNames axes) const {
27 XMLWriter::Element container_tag = write_cb.makeTag(parent_xml_object, *this, axes);
28 if (GeometryObject::WriteXMLCallback::isRef(container_tag)) return;
29 this->writeXMLAttr(container_tag, axes);
30 for (std::size_t i = 0; i < children.size(); ++i) {
31 XMLWriter::Element child_tag = write_cb.makeChildTag(container_tag, *this, i);
32 writeXMLChildAttr(child_tag, i, axes);
33 if (auto child = children[i]->getChild())
34 if (child) child->writeXML(child_tag, write_cb, axes);
35 }
36}
37
38 template <int dim> void GeometryObjectContainer<dim>::onChildChanged(const GeometryObject::Event& evt) {
39 this->fireChanged(evt.originalSource(), evt.flagsForParent());
40}
41
42 template <int dim> void GeometryObjectContainer<dim>::connectOnChildChanged(Translation<dim>& child) {
43 child.changedConnectMethod(this, &GeometryObjectContainer::onChildChanged);
44}
45
46 template <int dim> void GeometryObjectContainer<dim>::disconnectOnChildChanged(Translation<dim>& child) {
47 child.changedDisconnectMethod(this, &GeometryObjectContainer::onChildChanged);
48}
49
50 template <int dim>
51 bool GeometryObjectContainer<dim>::contains(const typename GeometryObjectContainer<dim>::DVec& p) const {
52 for (auto child : children)
53 if (child->contains(p)) return true;
54 return false;
55}
56
57 template <int dim> typename GeometryObjectContainer<dim>::Box GeometryObjectContainer<dim>::getBoundingBox() const {
58 if (children.empty()) return Box(Primitive<dim>::ZERO_VEC, Primitive<dim>::ZERO_VEC);
59 Box result = children[0]->getBoundingBox();
60 for (std::size_t i = 1; i < children.size(); ++i) result.makeInclude(children[i]->getBoundingBox());
61 return result;
62}
63
64 template <int dim> shared_ptr<Material> GeometryObjectContainer<dim>::getMaterial(const DVec& p) const {
65 for (auto child_it = children.rbegin(); child_it != children.rend(); ++child_it) {
66 shared_ptr<Material> r = (*child_it)->getMaterial(p);
67 if (r != nullptr) return r;
68 }
69 return shared_ptr<Material>();
70}
71
72 template <int dim>
73 void GeometryObjectContainer<dim>::getBoundingBoxesToVec(const GeometryObject::Predicate& predicate,
74 std::vector<Box>& dest,
75 const PathHints* path) const {
76 if (predicate(*this)) {
77 dest.push_back(this->getBoundingBox());
78 return;
79 }
80 forEachChild([&](const Translation<dim>& child) { child.getBoundingBoxesToVec(predicate, dest, path); }, path);
81
82 /*if (path) {
83 auto c = path->getTranslationChildren<dim>(*this);
84 if (!c.empty()) {
85 for (auto child: c) child->getBoundingBoxesToVec(predicate, dest, path);
86 return;
87 }
88 }
89 for (auto child: children) child->getBoundingBoxesToVec(predicate, dest, path);*/
90}
91
92 template <int dim>
93 void GeometryObjectContainer<dim>::getObjectsToVec(const GeometryObject::Predicate& predicate,
94 std::vector<shared_ptr<const GeometryObject>>& dest,
95 const PathHints* path) const {
96 if (predicate(*this)) {
97 dest.push_back(this->shared_from_this());
98 return;
99 }
100 forEachChild([&](const Translation<dim>& child) { child.getObjectsToVec(predicate, dest, path); }, path);
101
102 /*if (path) {
103 auto c = path->getTranslationChildren<dim>(*this);
104 if (!c.empty()) {
105 for (auto child: c) child->getObjectsToVec(predicate, dest, path);
106 return;
107 }
108 }
109 for (auto child: children) child->getObjectsToVec(predicate, dest, path);*/
110}
111
112 template <int dim>
113 void GeometryObjectContainer<dim>::getPositionsToVec(const GeometryObject::Predicate& predicate,
114 std::vector<DVec>& dest,
115 const PathHints* path) const {
116 if (predicate(*this)) {
117 dest.push_back(Primitive<dim>::ZERO_VEC);
118 return;
119 }
120 forEachChild([&](const Translation<dim>& child) { child.getPositionsToVec(predicate, dest, path); }, path);
121
122 /*if (path) {
123 auto c = path->getTranslationChildren<dim>(*this);
124 if (!c.empty()) {
125 for (auto child: c) child->getPositionsToVec(predicate, dest, path);
126 return;
127 }
128 }
129 for (auto child: children) child->getPositionsToVec(predicate, dest, path);*/
130}
131
132// template <int dim>
133// void GeometryObjectContainer<dim>::extractToVec(const GeometryObject::Predicate &predicate, std::vector<
134// shared_ptr<const GeometryObjectD<dim> > >& dest, const PathHints *path) const {
135// if (predicate(*this)) {
136// dest.push_back(static_pointer_cast< const GeometryObjectD<dim> >(this->shared_from_this()));
137// return;
138// }
139// if (path) {
140// auto c = path->getTranslationChildren<dim>(*this);
141// if (!c.empty()) {
142// for (auto child: c) child->extractToVec(predicate, dest, path);
143// return;
144// }
145// }
146// for (auto child: children) child->extractToVec(predicate, dest, path);
147// }
148
149 template <int dim> bool GeometryObjectContainer<dim>::hasInSubtree(const GeometryObject& el) const {
150 if (&el == this) return true;
151 for (auto child : children)
152 if (child->hasInSubtree(el)) return true;
153 return false;
154}
155
156 template <int dim>
157 GeometryObject::Subtree GeometryObjectContainer<dim>::getPathsTo(const GeometryObject& el,
158 const PathHints* path) const {
159 if (this == &el) return this->shared_from_this();
160 if (path) {
161 auto hintChildren = path->getTranslationChildren<dim>(*this);
162 if (!hintChildren.empty()) return findPathsFromChildTo(hintChildren.begin(), hintChildren.end(), el, path);
163 }
164 return findPathsFromChildTo(children.begin(), children.end(), el, path);
165}
166
167 template <int dim>
168 GeometryObject::Subtree GeometryObjectContainer<dim>::getPathsAt(const typename GeometryObjectContainer::DVec& point,
169 bool all) const {
170 GeometryObject::Subtree result;
171 if (all) {
172 for (auto child = children.begin(); child != children.end(); ++child) {
173 GeometryObject::Subtree child_path = (*child)->getPathsAt(point, true);
174 if (!child_path.empty()) result.children.push_back(std::move(child_path));
175 }
176 } else {
177 for (auto child = children.rbegin(); child != children.rend(); ++child) {
178 GeometryObject::Subtree child_path = (*child)->getPathsAt(point, false);
179 if (!child_path.empty()) {
180 result.children.push_back(std::move(child_path));
181 break;
182 }
183 }
184 }
185 if (!result.children.empty()) result.object = this->shared_from_this();
186 return result;
187}
188
189 template <int dim> std::size_t GeometryObjectContainer<dim>::getChildrenCount() const { return children.size(); }
190
191 template <int dim> shared_ptr<GeometryObject> GeometryObjectContainer<dim>::getChildNo(std::size_t child_no) const {
192 this->ensureIsValidChildNr(child_no);
193 return children[child_no];
194}
195
196 template <int dim>
197
198std::size_t GeometryObjectContainer<dim>::getChildIndex(const shared_ptr<ChildType>& el, const PathHints* path) const {
199 std::size_t index, i = 0;
200 bool found = false;
201 auto self = this->shared_from_this();
202 for (auto child_tran : children) {
203 auto child = child_tran->getChild();
204 if (child && child == el && (path == nullptr || path->includes(self, child_tran))) {
205 if (found) throw NotUniqueObjectException();
206 found = true;
207 index = i;
208 }
209 ++i;
210 }
211 if (!found) throw NoSuchGeometryObject();
212 return index;
213}
214
215 template <int dim>
216 shared_ptr<const GeometryObject> GeometryObjectContainer<dim>::changedVersion(const GeometryObject::Changer& changer,
217 Vec<3, double>* translation) const {
218 shared_ptr<GeometryObject> result(const_pointer_cast<GeometryObject>(this->shared_from_this()));
219 if (changer.apply(result, translation) || children.empty()) return result;
220
221 bool were_changes = false; // any child was changed?
222 std::vector<std::pair<shared_ptr<ChildType>, Vec<3, double>>> children_after_change;
223 for (const shared_ptr<TranslationT>& child_tran : children) {
224 Vec<3, double> trans_from_child;
225 shared_ptr<GeometryObject> old_child = child_tran->getChild();
226 if (!old_child) continue;
227 shared_ptr<GeometryObject> new_child =
228 const_pointer_cast<GeometryObject>(old_child->changedVersion(changer, &trans_from_child));
229 if (new_child != old_child) were_changes = true;
230 children_after_change.emplace_back(dynamic_pointer_cast<ChildType>(new_child), trans_from_child);
231 }
232
233 if (translation) *translation = vec(0.0, 0.0, 0.0); // we can't recommend anything special
234 if (were_changes) result = this->changedVersionForChildren(children_after_change, translation);
235 result->roles = this->roles;
236
237 return result;
238}
239
240 template <int dim>
241 bool GeometryObjectContainer<dim>::removeIfTUnsafe(
242 const std::function<bool(const shared_ptr<TranslationT>& c)>& predicate) {
243 auto dst = children.begin();
244 for (auto i : children)
245 if (predicate(i)) disconnectOnChildChanged(*i);
246 else
247 *dst++ = i;
248 if (dst != children.end()) {
249 children.erase(dst, children.end());
250 return true;
251 } else
252 return false;
253}
254
255 template <int dim>
256 bool GeometryObjectContainer<dim>::removeIfT(const std::function<bool(const shared_ptr<TranslationT>& c)>& predicate) {
257 if (removeIfTUnsafe(predicate)) {
258 this->fireChildrenChanged();
259 return true;
260 } else
261 return false;
262}
263
264 template <int dim> void GeometryObjectContainer<dim>::removeAtUnsafe(std::size_t index) {
265 disconnectOnChildChanged(*children[index]);
266 children.erase(children.begin() + index);
267}
268
269 template <int dim>
270 void GeometryObjectContainer<dim>::addPointsAlongToSet(std::set<double>& points,
271 Primitive<3>::Direction direction,
272 unsigned max_steps,
273 double min_step_size) const {
274 for (const auto& child : children) {
275 if (child)
276 child->addPointsAlongToSet(points, direction, this->max_steps ? this->max_steps : max_steps,
277 this->min_step_size ? this->min_step_size : min_step_size);
278 }
279}
280
281 template <int dim>
282 void GeometryObjectContainer<dim>::addLineSegmentsToSet(std::set<typename GeometryObjectD<dim>::LineSegment>& segments,
283 unsigned max_steps,
284 double min_step_size) const {
285 for (const auto& child : children) {
286 if (child)
287 child->addLineSegmentsToSet(segments, this->max_steps ? this->max_steps : max_steps,
288 this->min_step_size ? this->min_step_size : min_step_size);
289 }
290}
291
292 template struct PLASK_API GeometryObjectContainer<2>;
293 template struct PLASK_API GeometryObjectContainer<3>;
294
295} // namespace plask