PLaSK library

Loading...
Searching...
No Matches
transform_space_cylindric.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 "transform_space_cylindric.hpp"
15#include "../manager.hpp"
16#include "reader.hpp"
17
18#define PLASK_REVOLUTION_NAME "revolution"
19
20 namespace plask {
21
22 const char* Revolution::NAME = PLASK_REVOLUTION_NAME;
23
24std::string Revolution::getTypeName() const { return NAME; }
25
26 bool Revolution::contains(const GeometryObjectD<3>::DVec& p) const {
27 return this->hasChild() && this->_child->contains(childVec(p));
28}
29
30/*bool Revolution::intersects(const Box& area) const {
31 return getChild()->intersects(childBox(area));
32}*/
33
34 shared_ptr<Material> Revolution::getMaterial(const DVec& p) const {
35 return this->hasChild() ? this->_child->getMaterial(childVec(p)) : shared_ptr<Material>();
36}
37
38 Revolution::Box Revolution::fromChildCoords(const Revolution::ChildType::Box& child_bbox) const {
39 return parentBox(child_bbox);
40}
41
42 shared_ptr<GeometryObject> Revolution::shallowCopy() const { return plask::make_shared<Revolution>(this->_child); }
43
44 GeometryObject::Subtree Revolution::getPathsAt(const DVec& point, bool all) const {
45 if (!this->hasChild()) return GeometryObject::Subtree();
46 return GeometryObject::Subtree::extendIfNotEmpty(this, this->_child->getPathsAt(childVec(point), all));
47}
48
49 void Revolution::getPositionsToVec(const GeometryObject::Predicate& predicate,
50 std::vector<GeometryObjectTransformSpace::DVec>& dest,
51 const PathHints* path) const {
52 if (predicate(*this)) {
53 dest.push_back(Primitive<3>::ZERO_VEC);
54 return;
55 }
56 if (!this->hasChild()) return;
57 auto child_pos_vec = this->_child->getPositions(predicate, path);
58 for (const auto& v : child_pos_vec)
59 dest.emplace_back(0., 0., v.vert() // only vert component is well defined
60 );
61}
62
63 bool Revolution::childIsClipped() const {
64 return this->hasChild() && (this->_child->getBoundingBox().lower.tran() < 0);
65}
66
67// void Revolution::extractToVec(const GeometryObject::Predicate &predicate, std::vector< shared_ptr<const
68// GeometryObjectD<3> > >&dest, const PathHints *path) const {
69// if (predicate(*this)) {
70// dest.push_back(static_pointer_cast< const GeometryObjectD<3> >(this->shared_from_this()));
71// return;
72// }
73// std::vector< shared_ptr<const GeometryObjectD<2> > > child_res = getChild()->extract(predicate, path);
74// for (shared_ptr<const GeometryObjectD<2>>& c: child_res)
75// dest.emplace_back(new Revolution(const_pointer_cast<GeometryObjectD<2>>(c)));
76// }
77
78/*Box2D Revolution::childBox(const plask::Box3D& r) {
79 Box2D result(childVec(r.lower), childVec(r.upper));
80 result.fix();
81 return result;
82}*/ //TODO bugy
83
84 Box3D Revolution::parentBox(const ChildBox& r) {
85 double tran = std::max(r.upper.tran(), 0.0);
86 return Box3D(vec(-tran, -tran, r.lower.vert()), vec(tran, tran, r.upper.vert()));
87}
88
89 void Revolution::addPointsAlongToSet(std::set<double>& points,
90 Primitive<3>::Direction direction,
91 unsigned max_steps,
92 double min_step_size) const {
93 if (!this->hasChild()) return;
94 if (this->max_steps) max_steps = this->max_steps;
95 if (this->min_step_size) min_step_size = this->min_step_size;
96 if (direction == Primitive<3>::DIRECTION_VERT) {
97 this->_child->addPointsAlongToSet(points, Primitive<3>::DIRECTION_VERT, max_steps, min_step_size);
98 } else {
99 std::set<double> child_points;
100 this->_child->addPointsAlongToSet(child_points, Primitive<3>::DIRECTION_TRAN, max_steps, min_step_size);
101 if (child_points.size() == 0) return;
102 // Finer separation
103 std::vector<double> pts;
104 pts.reserve(child_points.size());
105 pts.insert(pts.end(), child_points.begin(), child_points.end());
106 double rr = pts[pts.size() - 1] - pts[0];
107 for (size_t i = 1; i < pts.size(); ++i) {
108 double r = pts[i - 1];
109 double dr = pts[i] - r;
110 PLASK_NO_CONVERSION_WARNING_BEGIN
111 unsigned maxsteps = rev_max_steps * (dr / rr);
112 PLASK_NO_WARNING_END
113 unsigned steps = min(unsigned(dr / rev_min_step_size), maxsteps);
114 double step = dr / steps;
115 for (unsigned j = 0; j < steps; ++j) {
116 points.insert(-r - j * step);
117 points.insert(r + j * step);
118 }
119 }
120 points.insert(-pts[pts.size() - 1]);
121 points.insert(pts[pts.size() - 1]);
122 }
123}
124
125 void Revolution::addLineSegmentsToSet(std::set<typename GeometryObjectD<3>::LineSegment>& segments,
126 unsigned max_steps,
127 double min_step_size) const {
128 if (!this->hasChild()) return;
129 typedef typename GeometryObjectD<3>::LineSegment Segment;
130 if (this->max_steps) max_steps = this->max_steps;
131 if (this->min_step_size) min_step_size = this->min_step_size;
132 std::set<typename GeometryObjectD<2>::LineSegment> segments2;
133 this->_child->addLineSegmentsToSet(segments2, max_steps, min_step_size);
134 double radius = max(abs(this->_child->getBoundingBox().left()), abs(this->_child->getBoundingBox().right()));
135 unsigned steps = min(unsigned(M_PI * radius / min_step_size), max_steps);
136 double dphi = M_PI / steps;
137 double cos0 = 1., sin0 = 0;
138 for (unsigned i = 1; i <= (steps + 1) / 2; ++i) {
139 double phi = dphi * i;
140 double cos1 = cos(phi), sin1 = sin(phi);
141 for (auto seg : segments2) {
142 double x[2], y[2], z[2];
143 for (int j = 0; j < 2; ++i) {
144 x[j] = seg[j].c0 * cos1;
145 y[j] = seg[j].c0 * sin1;
146 z[j] = seg[j].c1;
147 double x0 = seg[j].c0 * cos0, y0 = seg[j].c0 * cos0;
148 segments.insert(Segment(DVec(-x0, -y0, z[j]), DVec(-x[j], -y[j], z[j])));
149 segments.insert(Segment(DVec(x0, -y0, z[j]), DVec(x[j], -y[j], z[j])));
150 segments.insert(Segment(DVec(-x0, y0, z[j]), DVec(-x[j], y[j], z[j])));
151 segments.insert(Segment(DVec(x0, y0, z[j]), DVec(x[j], y[j], z[j])));
152 }
153 segments.insert(Segment(DVec(-x[0], -y[0], z[0]), DVec(-x[1], -y[1], z[1])));
154 segments.insert(Segment(DVec(x[0], -y[0], z[0]), DVec(x[1], -y[1], z[1])));
155 segments.insert(Segment(DVec(-x[0], y[0], z[0]), DVec(-x[1], y[1], z[1])));
156 segments.insert(Segment(DVec(x[0], y[0], z[0]), DVec(x[1], y[1], z[1])));
157 }
158 cos0 = cos1;
159 sin0 = sin1;
160 }
161}
162
163 shared_ptr<GeometryObject> read_revolution(GeometryReader& reader) {
164 GeometryReader::SetExpectedSuffix suffixSetter(reader, PLASK_GEOMETRY_TYPE_NAME_SUFFIX_2D);
165 bool auto_clip = reader.source.getAttribute("auto-clip", false);
166 auto rev_max_steps = reader.source.getAttribute<unsigned>("rev-steps-num");
167 auto rev_min_step_size = reader.source.getAttribute<double>("rev-steps-dist");
168 auto revolution = plask::make_shared<Revolution>(
169 reader.readExactlyOneChild<typename Revolution::ChildType>(), auto_clip);
170 if (rev_max_steps) revolution->rev_max_steps = *rev_max_steps;
171 if (rev_min_step_size) revolution->rev_min_step_size = *rev_min_step_size;
172 return revolution;
173 /*if (res->childIsClipped()) {
174 writelog(LOG_WARNING, "Child of <revolution>, read from XPL line {0}, is implicitly clipped (to non-negative
175 tran. coordinates).", line_nr);
176 }*/
177}
178
179 static GeometryReader::RegisterObjectReader revolution_reader(PLASK_REVOLUTION_NAME, read_revolution);
180
181} // namespace plask