PLaSK library
Loading...
Searching...
No Matches
space.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 "space.hpp"
15
16#include <memory>
17#include <cassert>
18
19namespace plask {
20
21void Geometry::setEdges(const std::function<plask::optional<std::string>(const std::string& s)>& borderValuesGetter,
22 const AxisNames& axesNames,
23 const MaterialsDB &materialsDB,
24 bool draft)
25{
27 try {
28 v = borderValuesGetter("edges");
29 if (v) setAllEdges(*edge::Strategy::fromStrUnique(*v, materialsDB));
30 } catch (...) {
31 if (!draft) throw;
32 }
33 try {
34 v = borderValuesGetter("planar");
35 if (v) setPlanarEdges(*edge::Strategy::fromStrUnique(*v, materialsDB));
36 } catch (...) {
37 if (!draft) throw;
38 }
39 for (int dir_nr = 0; dir_nr < 3; ++dir_nr) {
40 std::string axis_name = axesNames[dir_nr];
41 try {
44 } catch (...) {
45 if (!draft) throw;
46 }
47 try {
50 if (v_lo) throw BadInput("setEdges", "edge specified by both '{0}-lo' and '{1}'", axis_name, alternativeDirectionName(dir_nr, 0));
51 else v_lo = v;
52 }
53 } catch (...) {
54 if (!draft) throw;
55 v_lo.reset();
56 }
57 try {
60 if (v_hi) throw BadInput("setEdges", "edge specified by both '{0}-hi' and '{1}'", axis_name, alternativeDirectionName(dir_nr, 1));
61 else v_hi = v;
62 }
63 } catch (...) {
64 if (!draft) throw;
65 v_hi.reset();
66 }
67 try {
68 if (v_lo && v_hi) {
69 try {
71 v_lo.reset();
72 v_hi.reset();
73 } catch (...) {
74 if (!draft) throw;
75 }
76 }
77 if (v_lo) {
78 try {
80 } catch (...) {
81 if (!draft) throw;
82 }
83 }
84 if (v_hi) {
85 try {
87 } catch (...) {
88 if (!draft) throw;
89 }
90 }
91 } catch (DimensionError&) {
92 if (!draft) throw BadInput("setEdges", "axis '{0}' is not allowed for this space", axis_name);
93 } catch (...) {
94 if (!draft) throw;
95 }
96 }
97}
98
100 const edge::Strategy& b = this->getEdge(direction, higher);
101 if (b.type() != edge::Strategy::DEFAULT)
102 dest_xml_object.attr(this->alternativeDirectionName(direction, higher), b.str());
103}
104
105template <int dim>
107 if (evt.isResize()) cachedBoundingBox = getChild()->getBoundingBox();
108 //compiler should optimized out dim == 2 condition checking
109 fireChanged(evt.originalSource(), dim == 2 ? evt.flagsForParentWithChildrenWasChangedInformation() : evt.flagsForParent());
110}
111
112template <int dim>
114 connection_with_child.disconnect();
115}
116
117template <int dim>
119 disconnectOnChildChanged(); //disconnect old child, if any
120 auto c3d = getObject3D();
121 if (c3d) {
122 if (c3d) connection_with_child = c3d->changedConnectMethod(this, &GeometryD<dim>::onChildChanged);
123 auto c = getChildUnsafe();
124 if (c) cachedBoundingBox = c->getBoundingBox();
125 }
126}
127
128template <int dim>
129int GeometryD<dim>::getDimensionsCount() const { return DIM; }
130
131template <int dim>
133 return getMaterialOrDefault(p);
134}
135
136template <int dim>
137std::set<std::string> GeometryD<dim>::getRolesAt(const typename GeometryD<dim>::CoordsType &point, const PathHints *path) const {
138 return getChild()->getRolesAt(wrapEdges(point), path);
139}
140
141template <int dim>
142std::set<std::string> GeometryD<dim>::getRolesAt(const typename GeometryD<dim>::CoordsType &point, const PathHints &path) const {
143 return getChild()->getRolesAt(wrapEdges(point), &path);
144}
145
146template <>
149 dest_xml_object.attr("axes", axes.str());
150 this->storeEdgeInXML(dest_xml_object, DIRECTION_TRAN, false);
151 this->storeEdgeInXML(dest_xml_object, DIRECTION_TRAN, true);
152 this->storeEdgeInXML(dest_xml_object, DIRECTION_VERT, false);
153 this->storeEdgeInXML(dest_xml_object, DIRECTION_VERT, true);
154}
155
156template <>
159 dest_xml_object.attr("axes", axes.str());
160 for (int dir = 0; dir < 3; ++dir) {
161 this->storeEdgeInXML(dest_xml_object, plask::Geometry::Direction(dir), false);
162 this->storeEdgeInXML(dest_xml_object, plask::Geometry::Direction(dir), true);
163 }
164}
165
166template class PLASK_API GeometryD<2>;
167template class PLASK_API GeometryD<3>;
168
170 : extrusion(extrusion)
171{
172 initNewChild();
173}
174
176 : extrusion(plask::make_shared<Extrusion>(childGeometry, length))
177{
178 initNewChild();
179}
180
182 if (!extrusion) throw NoChildException();
183 auto child = extrusion->getChild();
184 if (!child) throw NoChildException();
185 return child;
186}
187
189 return extrusion->getChild();
190}
191
193 Vec<2, double> r = p;
194 shared_ptr<Material> material;
195
196 bottomup.apply(cachedBoundingBox, r, material);
197 if (material) return material;
198
199 leftright.apply(cachedBoundingBox, r, material);
200 if (material) return material;
201
202 return getMaterialOrDefault(r);
203}
204
211
213 if (this->extrusion == extrusion) return;
214 this->extrusion = extrusion;
215 this->initNewChild();
217}
218
219// Geometry2DCartesian* Geometry2DCartesian::getSubspace(const shared_ptr<GeometryObjectD<2>>& object, const PathHints* path, bool copyEdges) const {
220// auto shifts = getChild()->getObjectPositions(object, path);
221// // auto new_child = getChild()->getUniqueObjectInThisCoordinates(object, path);
222// // if (!new_child) {
223// // new_child = object->requireUniqueObjectInThisCoordinates(getChild(), path);
224// // new_child->translation = - new_child->translation;
225// // }
226// // if (copyEdges) {
227// // std::unique_ptr<Geometry2DCartesian> result(new Geometry2DCartesian(*this));
228// // result->extrusion = plask::make_shared<Extrusion>(new_child, getExtrusion()->length);
229// // return result.release();
230// // } else
231// // return new Geometry2DCartesian(new_child, getExtrusion()->length);
232// }
233
236 if (direction == DIRECTION_TRAN)
237 leftright.setStrategies(border_lo, border_hi);
238 else
239 bottomup.setStrategies(border_lo, border_hi);
240 fireChanged(Event::EVENT_EDGES);
241}
242
245 if (direction == DIRECTION_TRAN)
246 leftright.set(higher, border_to_set);
247 else
248 bottomup.set(higher, border_to_set);
249 fireChanged(Event::EVENT_EDGES);
250}
251
254 return (direction == DIRECTION_TRAN) ? leftright.get(higher) : bottomup.get(higher);
255}
256
258 shared_ptr<Geometry2DCartesian> result = make_shared<Geometry2DCartesian>(static_pointer_cast<Extrusion>(this->extrusion->shallowCopy()));
259 result->setEdges(DIRECTION_TRAN, leftright.getLo(), leftright.getHi());
260 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
261 result->frontMaterial = frontMaterial;
262 result->backMaterial = backMaterial;
263 return result;
264}
265
267 auto found = copied.find(this);
268 if (found != copied.end()) return found->second;
269 shared_ptr<Geometry2DCartesian> result = make_shared<Geometry2DCartesian>(static_pointer_cast<Extrusion>(this->extrusion->deepCopy(copied)));
270 result->setEdges(DIRECTION_TRAN, leftright.getLo(), leftright.getHi());
271 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
272 result->frontMaterial = frontMaterial;
273 result->backMaterial = backMaterial;
274 copied[this] = result;
275 return result;
276}
277
279 XMLWriter::Element tag = write_cb.makeTag(parent_xml_object, *this, axes);
280 if (WriteXMLCallback::isRef(tag)) return;
281 writeXMLAttr(tag, axes);
282 if (auto c = getExtrusion()) {
283 if (isinf(c->getLength()) && c->hasChild()) {
284 c->getChild()->writeXML(tag, write_cb, axes);
285 } else {
286 c->writeXML(tag, write_cb, axes);
287 }
288 }
289}
290
292 : revolution(revolution)
293{
294 initNewChild();
295}
296
302
304 if (!revolution) throw NoChildException();
305 auto child = revolution->getChild();
306 if (!child) throw NoChildException();
307 return child;
308}
309
311 return revolution->getChild();
312}
313
315 Vec<2, double> r = p;
316 if (r.c0 < 0) r.c0 = -r.c0; // Structure is ALWAYS symmetric with respect to the axis
317
318 shared_ptr<Material> material;
319
320 bottomup.apply(cachedBoundingBox, r, material);
321 if (material) return material;
322
323 innerouter.apply(cachedBoundingBox, r, material);
324 if (material) return material;
325
326 return getMaterialOrDefault(r);
327}
328
335
337 if (this->revolution == revolution) return;
338 this->revolution = revolution;
339 this->initNewChild();
341}
342
343// Geometry2DCylindrical* Geometry2DCylindrical::getSubspace(const shared_ptr< GeometryObjectD<2> >& object, const PathHints* path, bool copyEdges) const {
344// }
345
348 if (direction == DIRECTION_TRAN) {
349 try {
350 innerouter.setBoth(dynamic_cast<const edge::UniversalStrategy&>(border_to_set));
351 } catch (std::bad_cast&) {
352 throw BadInput("setEdges", "wrong edge type for inner or outer edge");
353 }
354 } else
355 bottomup.setBoth(border_to_set);
356 fireChanged(Event::EVENT_EDGES);
357}
358
360 ensureBoundDirIsProper(direction/*, false*/);
361 //ensureBoundDirIsProper(direction, true);
362 if (direction == DIRECTION_TRAN) {
363 try {
364 innerouter.setStrategies(dynamic_cast<const edge::UniversalStrategy&>(border_lo),
365 dynamic_cast<const edge::UniversalStrategy&>(border_hi));
366 } catch (std::bad_cast&) {
367 throw BadInput("setEdges", "wrong edge type for inner or outer edge");
368 }
369 } else
370 bottomup.setStrategies(border_lo, border_hi); //bottomup is only one valid proper bound for lo and hi
371 fireChanged(Event::EVENT_EDGES);
372}
373
375 ensureBoundDirIsProper(direction/*, higher*/);
376 if (direction == DIRECTION_TRAN) {
377 try {
378 innerouter.set(higher, dynamic_cast<const edge::UniversalStrategy&>(border_to_set));
379 } catch (std::bad_cast&) {
380 throw BadInput("setEdge", "wrong edge type for inner or outer edge");
381 }
382 } else
383 bottomup.set(higher, border_to_set);
384 fireChanged(Event::EVENT_EDGES);
385}
386
388 ensureBoundDirIsProper(direction/*, higher*/);
389 return (direction == DIRECTION_TRAN) ? innerouter.get(higher) : bottomup.get(higher);
390}
391
393 shared_ptr<Geometry2DCylindrical> result = make_shared<Geometry2DCylindrical>(static_pointer_cast<Revolution>(static_pointer_cast<Revolution>(this->revolution->shallowCopy())));
394 result->setEdges(DIRECTION_TRAN, innerouter.getLo(), innerouter.getHi());
395 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
396 return result;
397}
398
400 auto found = copied.find(this);
401 if (found != copied.end()) return found->second;
402 shared_ptr<Geometry2DCylindrical> result = make_shared<Geometry2DCylindrical>(static_pointer_cast<Revolution>(this->revolution->deepCopy(copied)));
403 result->setEdges(DIRECTION_TRAN, innerouter.getLo(), innerouter.getHi());
404 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
405 copied[this] = result;
406 return result;
407}
408
410 XMLWriter::Element tag = write_cb.makeTag(parent_xml_object, *this, axes);
411 if (WriteXMLCallback::isRef(tag)) return;
412 writeXMLAttr(tag, axes);
413 if (auto c = getRevolution()) c->writeXML(tag, write_cb, axes);
414}
415
417 switch (direction) {
418 case DIRECTION_LONG: backfront.setStrategies(border_lo, border_hi); break;
419 case DIRECTION_TRAN: leftright.setStrategies(border_lo, border_hi); break;
420 case DIRECTION_VERT: bottomup.setStrategies(border_lo, border_hi); break;
421 }
422 fireChanged(Event::EVENT_EDGES);
423}
424
426 switch (direction) {
427 case DIRECTION_LONG: backfront.setBoth(border_to_set); break;
428 case DIRECTION_TRAN: leftright.setBoth(border_to_set); break;
429 case DIRECTION_VERT: bottomup.setBoth(border_to_set); break;
430 }
431 fireChanged(Event::EVENT_EDGES);
432}
433
435 switch (direction) {
436 case DIRECTION_LONG: backfront.set(higher, border_to_set); break;
437 case DIRECTION_TRAN: leftright.set(higher, border_to_set); break;
438 case DIRECTION_VERT: bottomup.set(higher, border_to_set); break;
439 }
440 fireChanged(Event::EVENT_EDGES);
441}
442
443const edge::Strategy &Geometry3D::getEdge(Direction direction, bool higher) const {
444 switch (direction) {
445 case DIRECTION_LONG: return backfront.get(higher);
446 case DIRECTION_TRAN: return leftright.get(higher);
447 case DIRECTION_VERT: return bottomup.get(higher);
448 }
449 assert(0);
450#ifdef _MSC_VER
451 __assume(0);
452#endif
453 std::abort(); // to silent warning in gcc/clang release build
454}
455
457: child(child) {
458 initNewChild();
459}
460
462 if (!child) throw NoChildException();
463 return child;
464}
465
469
473
475 Vec<3, double> r = p;
476 shared_ptr<Material> material;
477
478 bottomup.apply(cachedBoundingBox, r, material);
479 if (material) return material;
480
481 leftright.apply(cachedBoundingBox, r, material);
482 if (material) return material;
483
484 backfront.apply(cachedBoundingBox, r, material);
485 if (material) return material;
486
487 return getMaterialOrDefault(r);
488}
489
492 bottomup.apply(cachedBoundingBox, p, ignored);
493 leftright.apply(cachedBoundingBox, p, ignored);
494 backfront.apply(cachedBoundingBox, p, ignored);
495 return p;
496}
497
498
500 shared_ptr<Geometry3D> result = make_shared<Geometry3D>(this->child);
501 result->setEdges(DIRECTION_LONG, backfront.getLo(), backfront.getHi());
502 result->setEdges(DIRECTION_TRAN, leftright.getLo(), leftright.getHi());
503 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
504 return result;
505}
506
508 auto found = copied.find(this);
509 if (found != copied.end()) return found->second;
510 shared_ptr<Geometry3D> result = make_shared<Geometry3D>(static_pointer_cast<GeometryObjectD<3>>(this->child->deepCopy(copied)));
511 result->setEdges(DIRECTION_LONG, backfront.getLo(), backfront.getHi());
512 result->setEdges(DIRECTION_TRAN, leftright.getLo(), leftright.getHi());
513 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
514 copied[this] = result;
515 return result;
516}
517
518// Geometry3D* Geometry3D::getSubspace(const shared_ptr<GeometryObjectD<3>>& object, const PathHints* path, bool copyEdges) const {
519// }
520
522 auto child = getChild();
524 const_pointer_cast<GeometryObject>(child->changedVersion(changer, translation)));
525 if (child == newChild)
526 return shared_from_this();
527 shared_ptr<Geometry2DCartesian> result = make_shared<Geometry2DCartesian>(newChild, extrusion->getLength());
528 result->setEdges(DIRECTION_TRAN, leftright.getLo(), leftright.getHi());
529 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
530 result->frontMaterial = frontMaterial;
531 result->backMaterial = backMaterial;
532 return result;
533}
534
536 auto child = getChild();
538 const_pointer_cast<GeometryObject>(child->changedVersion(changer, translation)));
539 if (child == newChild)
540 return shared_from_this();
541 shared_ptr<Geometry2DCylindrical> result = make_shared<Geometry2DCylindrical>(newChild);
542 result->setEdges(DIRECTION_TRAN, innerouter.getLo(), innerouter.getHi());
543 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
544 return result;
545}
546
548 auto child = getChild();
550 const_pointer_cast<GeometryObject>(child->changedVersion(changer, translation)));
551 if (child == newChild)
552 return shared_from_this();
553 shared_ptr<Geometry3D> result = make_shared<Geometry3D>(newChild);
554 result->setEdges(DIRECTION_LONG, backfront.getLo(), backfront.getHi());
555 result->setEdges(DIRECTION_TRAN, leftright.getLo(), leftright.getHi());
556 result->setEdges(DIRECTION_VERT, bottomup.getLo(), bottomup.getHi());
557 return result;
558}
559
560
561
562} // namespace plask