PLaSK library

Loading...
Searching...
No Matches
mirror.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 "mirror.hpp"
15#include "../manager.hpp"
16#include "reader.hpp"
17
18#define PLASK_FLIP2D_NAME ("flip" PLASK_GEOMETRY_TYPE_NAME_SUFFIX_2D)
19#define PLASK_FLIP3D_NAME ("flip" PLASK_GEOMETRY_TYPE_NAME_SUFFIX_3D)
20
21#define PLASK_MIRROR2D_NAME ("mirror" PLASK_GEOMETRY_TYPE_NAME_SUFFIX_2D)
22#define PLASK_MIRROR3D_NAME ("mirror" PLASK_GEOMETRY_TYPE_NAME_SUFFIX_3D)
23
24 namespace plask {
25
26 template <int dim> const char* Flip<dim>::NAME = dim == 2 ? PLASK_FLIP2D_NAME : PLASK_FLIP3D_NAME;
27
28 template <int dim> std::string Flip<dim>::getTypeName() const { return NAME; }
29
30 template <int dim> shared_ptr<Material> Flip<dim>::getMaterial(const typename Flip<dim>::DVec& p) const {
31 return this->hasChild() ? this->_child->getMaterial(flipped(p)) : shared_ptr<Material>();
32}
33
34 template <int dim> bool Flip<dim>::contains(const typename Flip<dim>::DVec& p) const {
35 return this->hasChild() && this->_child->contains(flipped(p));
36}
37
38 template <int dim>
39 GeometryObject::Subtree Flip<dim>::getPathsAt(const typename Flip<dim>::DVec& point, bool all) const {
40 if (!this->hasChild()) return GeometryObject::Subtree();
41 return GeometryObject::Subtree::extendIfNotEmpty(this, this->_child->getPathsAt(flipped(point), all));
42}
43
44 template <int dim>
45 typename Flip<dim>::Box Flip<dim>::fromChildCoords(const typename Flip<dim>::ChildType::Box& child_bbox) const {
46 return flipped(child_bbox);
47}
48
49 template <int dim>
50 void Flip<dim>::getPositionsToVec(const GeometryObject::Predicate& predicate,
51 std::vector<DVec>& dest,
52 const PathHints* path) const {
53 if (predicate(*this)) {
54 dest.push_back(Primitive<dim>::ZERO_VEC);
55 return;
56 }
57 if (!this->hasChild()) return;
58 std::size_t s = dest.size();
59 this->_child->getPositionsToVec(predicate, dest, path);
60 for (; s < dest.size(); ++s)
61 dest[s][flipDir] =
62 std::numeric_limits<double>::quiet_NaN(); // we can't get proper position in flipDir direction
63}
64
65 template <int dim> shared_ptr<GeometryObject> Flip<dim>::shallowCopy() const { return copyShallow(); }
66
67 template <int dim>
68 void Flip<dim>::addPointsAlongToSet(std::set<double>& points,
69 Primitive<3>::Direction direction,
70 unsigned max_steps,
71 double min_step_size) const {
72 if (this->_child) {
73 if (int(direction) == int(flipDir) + 3 - dim) {
74 std::set<double> child_points;
75 this->_child->addPointsAlongToSet(child_points, direction, max_steps, min_step_size);
76 for (double p : child_points) points.insert(-p);
77 } else {
78 this->_child->addPointsAlongToSet(points, direction, max_steps, min_step_size);
79 }
80 }
81}
82
83 template <int dim>
84 void Flip<dim>::addLineSegmentsToSet(std::set<typename GeometryObjectD<dim>::LineSegment>& segments,
85 unsigned max_steps,
86 double min_step_size) const {
87 if (this->_child) {
88 std::set<typename GeometryObjectD<dim>::LineSegment> child_segments;
89 this->_child->addLineSegmentsToSet(child_segments, this->max_steps ? this->max_steps : max_steps,
90 this->min_step_size ? this->min_step_size : min_step_size);
91 for (const auto& p : child_segments)
92 segments.insert(typename GeometryObjectD<dim>::LineSegment(flipped(p[0]), flipped(p[1])));
93 }
94}
95
96 template <int dim> void Flip<dim>::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const {
97 BaseClass::writeXMLAttr(dest_xml_object, axes);
98 dest_xml_object.attr("axis", axes[direction3D(flipDir)]);
99}
100
101 template <int dim> const char* Mirror<dim>::NAME = dim == 2 ? PLASK_MIRROR2D_NAME : PLASK_MIRROR3D_NAME;
102
103 template <int dim> std::string Mirror<dim>::getTypeName() const { return NAME; }
104
105 template <int dim> typename Mirror<dim>::Box Mirror<dim>::getBoundingBox() const {
106 return this->hasChild() ? extended(this->_child->getBoundingBox())
107 : Box(Primitive<dim>::ZERO_VEC, Primitive<dim>::ZERO_VEC);
108}
109
110 template <int dim> typename Mirror<dim>::Box Mirror<dim>::getRealBoundingBox() const {
111 return this->hasChild() ? this->_child->getBoundingBox() : Box(Primitive<dim>::ZERO_VEC, Primitive<dim>::ZERO_VEC);
112}
113
114 template <int dim> shared_ptr<Material> Mirror<dim>::getMaterial(const typename Mirror<dim>::DVec& p) const {
115 return this->hasChild() ? this->_child->getMaterial(flippedIfNeg(p)) : shared_ptr<Material>();
116}
117
118 template <int dim> bool Mirror<dim>::contains(const typename Mirror<dim>::DVec& p) const {
119 return this->hasChild() && this->_child->contains(flippedIfNeg(p));
120}
121
122 template <int dim>
123 typename Mirror<dim>::Box Mirror<dim>::fromChildCoords(const typename Mirror<dim>::ChildType::Box& child_bbox) const {
124 return child_bbox.extension(child_bbox.flipped(flipDir));
125}
126
127 template <int dim>
128 void Mirror<dim>::getBoundingBoxesToVec(const GeometryObject::Predicate& predicate,
129 std::vector<Box>& dest,
130 const PathHints* path) const {
131 if (predicate(*this)) {
132 dest.push_back(getBoundingBox());
133 return;
134 }
135 if (!this->hasChild()) return;
136 std::size_t old_size = dest.size();
137 this->_child->getBoundingBoxesToVec(predicate, dest, path);
138 std::size_t new_size = dest.size();
139 for (std::size_t i = old_size; i < new_size; ++i) dest.push_back(dest[i].flipped(flipDir));
140}
141
142 template <int dim>
143 void Mirror<dim>::getObjectsToVec(const GeometryObject::Predicate& predicate,
144 std::vector<shared_ptr<const GeometryObject>>& dest,
145 const PathHints* path) const {
146 if (predicate(*this)) {
147 dest.push_back(this->shared_from_this());
148 return;
149 }
150 if (!this->hasChild()) return;
151 std::size_t old_size = dest.size();
152 this->_child->getObjectsToVec(predicate, dest, path);
153 std::size_t new_size = dest.size();
154 for (std::size_t i = old_size; i < new_size; ++i) dest.push_back(dest[i]);
155}
156
157 template <int dim>
158 void Mirror<dim>::getPositionsToVec(const GeometryObject::Predicate& predicate,
159 std::vector<DVec>& dest,
160 const PathHints* path) const {
161 if (predicate(*this)) {
162 dest.push_back(Primitive<dim>::ZERO_VEC);
163 return;
164 }
165 if (!this->hasChild()) return;
166 std::size_t old_size = dest.size();
167 this->_child->getPositionsToVec(predicate, dest, path);
168 std::size_t new_size = dest.size();
169 for (std::size_t i = old_size; i < new_size; ++i) {
170 dest.push_back(dest[i]);
171 dest.back()[flipDir] =
172 std::numeric_limits<double>::quiet_NaN(); // we can't get proper position in flipDir direction
173 }
174}
175
176 template <int dim>
177 GeometryObject::Subtree Mirror<dim>::getPathsTo(const GeometryObject& el, const PathHints* path) const {
178 GeometryObject::Subtree result = GeometryObjectTransform<dim>::getPathsTo(el, path);
179 if (!result.empty() && !result.children.empty()) // result.children[0] == getChild()
180 result.children.push_back(
181 GeometryObject::Subtree(plask::make_shared<Flip<dim>>(flipDir, getChild()), result.children[0].children));
182 return result;
183}
184
185 template <int dim>
186 GeometryObject::Subtree Mirror<dim>::getPathsAt(const typename Mirror<dim>::DVec& point, bool all) const {
187 if (!this->hasChild()) GeometryObject::Subtree();
188 return GeometryObject::Subtree::extendIfNotEmpty(this, this->_child->getPathsAt(flippedIfNeg(point), all));
189}
190
191 template <int dim> std::size_t Mirror<dim>::getChildrenCount() const { return this->hasChild() ? 2 : 0; }
192
193 template <int dim> shared_ptr<GeometryObject> Mirror<dim>::getChildNo(std::size_t child_no) const {
194 if (child_no >= getChildrenCount())
195 throw OutOfBoundsException("getChildNo", "child_no", child_no, 0, getChildrenCount() - 1);
196 // child_no is 0 or 1 now, and hasChild() is true
197 if (child_no == 0) return this->_child;
198 else
199 return plask::make_shared<Flip<dim>>(flipDir, this->_child);
200}
201
202 template <int dim> std::size_t Mirror<dim>::getRealChildrenCount() const {
203 return GeometryObjectTransform<dim>::getChildrenCount();
204}
205
206 template <int dim> shared_ptr<GeometryObject> Mirror<dim>::getRealChildNo(std::size_t child_no) const {
207 return GeometryObjectTransform<dim>::getChildNo(child_no);
208}
209
210 template <int dim> shared_ptr<GeometryObject> Mirror<dim>::shallowCopy() const { return copyShallow(); }
211
212 template <int dim>
213 void Mirror<dim>::addPointsAlongToSet(std::set<double>& points,
214 Primitive<3>::Direction direction,
215 unsigned max_steps,
216 double min_step_size) const {
217 if (this->_child) {
218 if (this->max_steps) max_steps = this->max_steps;
219 if (this->min_step_size) min_step_size = this->min_step_size;
220 if (int(direction) == int(flipDir) + 3 - dim) {
221 std::set<double> child_points;
222 this->_child->addPointsAlongToSet(child_points, direction, max_steps, min_step_size);
223 for (double p : child_points) points.insert(-p);
224 for (double p : child_points) points.insert(p);
225 } else {
226 this->_child->addPointsAlongToSet(points, direction, max_steps, min_step_size);
227 }
228 }
229}
230
231 template <int dim>
232 void Mirror<dim>::addLineSegmentsToSet(std::set<typename GeometryObjectD<dim>::LineSegment>& segments,
233 unsigned max_steps,
234 double min_step_size) const {
235 if (this->_child) {
236 std::set<typename GeometryObjectD<dim>::LineSegment> child_segments;
237 this->_child->addLineSegmentsToSet(child_segments, this->max_steps ? this->max_steps : max_steps,
238 this->min_step_size ? this->min_step_size : min_step_size);
239 for (const auto& p : child_segments) {
240 segments.insert(typename GeometryObjectD<dim>::LineSegment(flipped(p[0]), flipped(p[1])));
241 segments.insert(p);
242 }
243 }
244}
245
246 template <int dim> void Mirror<dim>::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const {
247 BaseClass::writeXMLAttr(dest_xml_object, axes);
248 dest_xml_object.attr("axis", axes[direction3D(flipDir)]);
249}
250
251//--------- XML reading: Flip and Mirror ----------------
252
253 template <typename GeometryType> shared_ptr<GeometryObject> read_flip_like(GeometryReader& reader) {
254 GeometryReader::SetExpectedSuffix suffixSetter(
255 reader, GeometryType::DIM == 2 ? PLASK_GEOMETRY_TYPE_NAME_SUFFIX_2D : PLASK_GEOMETRY_TYPE_NAME_SUFFIX_3D);
256 auto flipDir = reader.getAxisNames().get<GeometryType::DIM>(reader.source.requireAttribute("axis"));
257 return plask::make_shared<GeometryType>(
258 flipDir, reader.readExactlyOneChild<typename GeometryType::ChildType>());
259}
260
261 static GeometryReader::RegisterObjectReader flip2D_reader(PLASK_FLIP2D_NAME, read_flip_like<Flip<2>>);
262 static GeometryReader::RegisterObjectReader flip3D_reader(PLASK_FLIP3D_NAME, read_flip_like<Flip<3>>);
263 static GeometryReader::RegisterObjectReader mirror2D_reader(PLASK_MIRROR2D_NAME, read_flip_like<Mirror<2>>);
264 static GeometryReader::RegisterObjectReader mirror3D_reader(PLASK_MIRROR3D_NAME, read_flip_like<Mirror<3>>);
265
266 template struct PLASK_API Flip<2>;
267 template struct PLASK_API Flip<3>;
268
269 template struct PLASK_API Mirror<2>;
270 template struct PLASK_API Mirror<3>;
271
272} // namespace plask