PLaSK library
Loading...
Searching...
No Matches
leaf.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 "leaf.hpp"
15#include "cuboid.hpp"
16
17#define PLASK_BLOCK2D_NAME ("block" PLASK_GEOMETRY_TYPE_NAME_SUFFIX_2D)
18#define PLASK_BLOCK3D_NAME ("block" PLASK_GEOMETRY_TYPE_NAME_SUFFIX_3D)
19
20namespace plask {
21
22template <int dim>
26
27template <int dim>
34
38 if (!top_attr && !bottom_attr) {
41 format("'{}' attribute allowed only for layers with graded material", GeometryReader::XML_MATERIAL_GRADING_ATTR));
42 if (src.materialsAreRequired) {
46 } else {
48 if (!src.manager.draft) {
49 if (!top_attr || !bottom_attr)
50 src.source.throwException(format("If '{0}' or '{1}' attribute is given, the other one is also required",
54 } else {
55 if (!top_attr || !bottom_attr)
57 format("If '{0}' or '{1}' attribute is given, the other one is also required",
61 }
62 }
63 return src;
64}
65
67
68template <int dim>
72
73/*void GeometryObjectLeaf::getLeafsInfoToVec(std::vector<std::tuple<shared_ptr<const GeometryObject>,
74GeometryObjectLeaf::Box, GeometryObjectLeaf::DVec> > &dest, const PathHints *path) const { dest.push_back(
75std::tuple<shared_ptr<const GeometryObject>, Box, DVec>(this->shared_from_this(), this->getBoundingBox(),
76Primitive<dim>::ZERO_VEC) );
77}*/
78
79template <int dim>
81 std::vector<typename GeometryObjectLeaf<dim>::Box>& dest,
82 const PathHints*) const {
83 if (predicate(*this)) dest.push_back(this->getBoundingBox());
84}
85
86template <int dim>
89 const PathHints* /*path*/) const {
90 if (predicate(*this)) dest.push_back(this->shared_from_this());
91}
92
93template <int dim>
95 std::vector<typename GeometryObjectLeaf::DVec>& dest,
96 const PathHints*) const {
97 if (predicate(*this)) dest.push_back(Primitive<dim>::ZERO_VEC);
98}
99
100template <int dim> bool GeometryObjectLeaf<dim>::hasInSubtree(const GeometryObject& el) const { return &el == this; }
101
105
106template <int dim>
110
112 throw OutOfBoundsException("geometryObjectLeaf::getChildNo", "child_no");
113}
114
115template <int dim>
122
123template <int dim>
125 std::map<const GeometryObject*, shared_ptr<GeometryObject>>& copied) const {
126 auto found = copied.find(this);
127 if (found != copied.end()) return found->second;
129 copied[this] = result;
130 return result;
132
135
138 details::setupBlock2D3D(reader, *block);
139 return block;
140}
141
142// shared_ptr<GeometryObject> read_block3D(GeometryReader& reader) {
143// shared_ptr<Block<3>> block(new Block<3>());
144// block->size.lon() = details::readAlternativeAttrs(reader, "d" + reader.getAxisLongName(), "length");
145// details::setupBlock2D3D(reader, *block);
146// return block;
147// }
148
151 materialProvider->writeXML(dest_xml_object, axes)
152 .attr("d" + axes.getNameForTran(), size.tran())
153 .attr("d" + axes.getNameForVert(), size.vert());
154}
155
158 materialProvider->writeXML(dest_xml_object, axes)
159 .attr("d" + axes.getNameForLong(), size.lon())
160 .attr("d" + axes.getNameForTran(), size.tran())
161 .attr("d" + axes.getNameForVert(), size.vert());
162}
163
164template <int dim> const char* Block<dim>::NAME = dim == 2 ? PLASK_BLOCK2D_NAME : PLASK_BLOCK3D_NAME;
165
166template <int dim> std::string Block<dim>::getTypeName() const { return NAME; }
167
168template <int dim> typename Block<dim>::Box Block<dim>::getBoundingBox() const {
170}
171
172template <int dim> bool Block<dim>::contains(const typename Block<dim>::DVec& p) const {
173 return this->getBoundingBox().contains(p);
174}
175
176template <int dim>
177void Block<dim>::addPointsAlongToSet(std::set<double>& points,
178 Primitive<3>::Direction direction,
179 unsigned max_steps,
180 double min_step_size) const {
181 assert(int(direction) >= 3 - dim && int(direction) <= 3);
182 if (this->materialProvider->isUniform(direction)) {
183 points.insert(0);
184 points.insert(size[size_t(direction) - (3 - dim)]);
185 } else {
186 if (this->max_steps) max_steps = this->max_steps;
187 if (this->min_step_size) min_step_size = this->min_step_size;
188 double length = size[size_t(direction) - (3 - dim)];
189 unsigned steps = min(unsigned(length / min_step_size), max_steps);
190 double step = length / steps;
191 for (unsigned i = 0; i <= steps; ++i) points.insert(i * step);
192 }
193}
194
195template <>
197 unsigned max_steps,
198 double min_step_size) const {
199 typedef typename GeometryObjectD<2>::LineSegment Segment;
200 std::vector<double> pts0, pts1;
201 {
202 std::set<double> ps;
204 pts0.reserve(ps.size());
205 pts0.insert(pts0.end(), ps.begin(), ps.end());
206 }
207 {
208 std::set<double> ps;
210 pts1.reserve(ps.size());
211 pts1.insert(pts1.end(), ps.begin(), ps.end());
212 }
213 for (size_t i1 = 0; i1 < pts1.size(); ++i1) {
214 double p1 = pts1[i1];
215 for (size_t i0 = 1; i0 < pts0.size(); ++i0) segments.insert(Segment(DVec(pts0[i0 - 1], p1), DVec(pts0[i0], p1)));
216 }
217 for (size_t i0 = 0; i0 < pts0.size(); ++i0) {
218 double p0 = pts0[i0];
219 for (size_t i1 = 1; i1 < pts1.size(); ++i1) segments.insert(Segment(DVec(p0, pts1[i1 - 1]), DVec(p0, pts1[i1])));
220 }
221}
222
223template <>
225 unsigned max_steps,
226 double min_step_size) const {
227 typedef typename GeometryObjectD<3>::LineSegment Segment;
228 std::vector<double> pts0, pts1, pts2;
229 {
230 std::set<double> ps;
232 pts0.reserve(ps.size());
233 pts0.insert(pts0.end(), ps.begin(), ps.end());
234 }
236 std::set<double> ps;
238 pts1.reserve(ps.size());
239 pts1.insert(pts1.end(), ps.begin(), ps.end());
240 }
241 {
242 std::set<double> ps;
244 pts2.reserve(ps.size());
245 pts2.insert(pts2.end(), ps.begin(), ps.end());
246 }
247 for (size_t i2 = 0; i2 < pts2.size(); ++i2) {
248 double p2 = pts1[i2];
249 for (size_t i1 = 0; i1 < pts1.size(); ++i1) {
250 double p1 = pts1[i1];
251 for (size_t i0 = 1; i0 < pts0.size(); ++i0)
252 segments.insert(Segment(DVec(pts0[i0 - 1], p1, p2), DVec(pts0[i0], p1, p2)));
254 for (size_t i0 = 0; i0 < pts0.size(); ++i0) {
255 double p0 = pts0[i0];
256 for (size_t i1 = 1; i1 < pts1.size(); ++i1)
257 segments.insert(Segment(DVec(p0, pts1[i1 - 1], p2), DVec(p0, pts1[i1], p2)));
258 }
260 for (size_t i1 = 0; i1 < pts1.size(); ++i1) {
261 double p1 = pts1[i1];
262 for (size_t i0 = 0; i0 < pts0.size(); ++i0) {
263 double p0 = pts0[i0];
264 for (size_t i2 = 1; i2 < pts2.size(); ++i2)
265 segments.insert(Segment(DVec(p0, p1, pts2[i2 - 1]), DVec(p0, p1, pts2[i2])));
266 }
267 }
268}
269
270template struct PLASK_API Block<2>;
271template struct PLASK_API Block<3>;
272
274static GeometryReader::RegisterObjectReader rectangle_reader("rectangle", read_block2D);
276
277namespace detail {
278
279template <int dim> struct MakeBlockVisitor : public boost::static_visitor<shared_ptr<Block<dim>>> {
281 bool draft;
282
283 MakeBlockVisitor(const Vec<dim>& size, bool draft): size(size), draft(draft) {}
284
286 return plask::make_shared<Block<dim>>(size, material);
287 }
288
290 if (!draft)
292 else {
294 result->setMaterialDraftTopBottomCompositionFast(material_factory);
295 return result;
296 }
297 }
298};
299
300} // namespace detail
301
304 Vec<3, double>& translation, bool draft) {
305 if (to_change->getDimensionsCount() == 3) {
307 Box3D bb = el->getBoundingBox();
308 translation = bb.lower;
309 return boost::apply_visitor(detail::MakeBlockVisitor<3>(bb.size(), draft), material);
310 } else { // to_change->getDimensionsCount() == 3
312 Box2D bb = el->getBoundingBox();
313 translation = vec<3, double>(bb.lower);
314 return boost::apply_visitor(detail::MakeBlockVisitor<2>(bb.size(), draft), material);
315 }
316}
317
318} // namespace plask