PLaSK library

Loading...
Searching...
No Matches
cuboid.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 "cuboid.hpp"
15
16#define PLASK_CUBOID_NAME "cuboid"
17
18 namespace plask {
19
20 const char* RotatedCuboid::NAME = PLASK_CUBOID_NAME;
21
22std::string RotatedCuboid::getTypeName() const { return NAME; }
23
24 RotatedCuboid::Box RotatedCuboid::getBoundingBox() const {
25 DVec hl(trans(size.c0, 0.)), hh(trans(size.c0, size.c1)), lh(trans(0., size.c1));
26 if (c >= 0) {
27 if (s >= 0)
28 return Box(lh.c0, 0., 0., hl.c0, hh.c1, size.c2); // I
29 else
30 return Box(0., hl.c1, 0., hh.c0, lh.c1, size.c2); // IV
31 } else {
32 if (s >= 0)
33 return Box(hh.c0, lh.c1, 0., 0., hl.c1, size.c2); // II
34 else
35 return Box(hl.c0, hh.c1, 0., lh.c0, 0., size.c2); // III
36 }
37}
38
39 bool RotatedCuboid::contains(const RotatedCuboid::DVec& p) const { return Box(Primitive<3>::ZERO_VEC, size).contains(itrans(p)); }
40
41// Add characteristic points information along specified axis to set
42// \param[in,out] points ordered set of division points along specified axis
43// \param direction axis direction
44// \param max_steps maximum number of points to split single leaf
45// \param min_step_size minimum distance between divisions for a single leaf
46 void RotatedCuboid::addPointsAlongToSet(std::set<double>& points,
47 Primitive<3>::Direction direction,
48 unsigned max_steps,
49 double min_step_size) const {
50 if (direction == Primitive<3>::DIRECTION_VERT) {
51 if (this->materialProvider->isUniform(Primitive<3>::DIRECTION_VERT)) {
52 points.insert(0);
53 points.insert(size[2]);
54 } else {
55 if (this->max_steps) max_steps = this->max_steps;
56 if (this->min_step_size) min_step_size = this->min_step_size;
57 double length = size[2];
58 unsigned steps = min(unsigned(length / min_step_size), max_steps);
59 double step = length / steps;
60 for (unsigned i = 0; i <= steps; ++i) points.insert(i * step);
61 }
62 } else if ((this->c == 0. || this->s == 0.) && this->materialProvider->isUniform(direction)) {
63 points.insert(0);
64 points.insert(size[size_t(direction)]);
65 } else {
66 if (this->max_steps) max_steps = this->max_steps;
67 if (this->min_step_size) min_step_size = this->min_step_size;
68 DVec hl(trans(size.c0, 0.)), hh(trans(size.c0, size.c1)), lh(trans(0., size.c1));
69 const size_t dir = size_t(direction);
70 double coords[4] = {0., hl[dir], hh[dir], lh[dir]};
71 std::sort(coords, coords + 4);
72 double total = coords[3] - coords[0];
73 for (size_t i = 0; i < 3; ++i) {
74 if (coords[i] != coords[i + 1]) points.insert(coords[i]);
75 double len = coords[i + 1] - coords[i];
76 double dn = std::round(len / total * max_steps);
77 size_t n = size_t(dn);
78 if (n > 1) {
79 double step = len / dn;
80 if (step < min_step_size) {
81 dn = std::round(len / min_step_size);
82 n = size_t(dn);
83 step = len / dn;
84 }
85 for (size_t j = 1; j < n; ++j) points.insert(coords[i] + j * step);
86 }
87 }
88 points.insert(coords[3]);
89 }
90}
91
92// Add characteristic points to the set and edges connecting them
93// \param max_steps maximum number of points to split single leaf
94// \param min_step_size minimum distance between divisions for a single leaf
95// \param[in, out] segments set to extend
96 void RotatedCuboid::addLineSegmentsToSet(std::set<typename GeometryObjectD<3>::LineSegment>& segments,
97 unsigned max_steps,
98 double min_step_size) const {
99 if (!(materialProvider->isUniform(Primitive<3>::DIRECTION_TRAN) && materialProvider->isUniform(Primitive<3>::DIRECTION_LONG)))
100 throw NotImplemented("triangular mesh for rotated cuboids non-uniform in lateral directions");
101
102 std::vector<double> ptsz;
103 std::set<double> ps;
104 addPointsAlongToSet(ps, Primitive<3>::Direction(Primitive<3>::DIRECTION_VERT), max_steps, min_step_size);
105 ptsz.reserve(ps.size());
106 ptsz.insert(ptsz.end(), ps.begin(), ps.end());
107 DVec corners[4] = {Primitive<3>::ZERO_VEC, trans(size.c0, 0.), trans(size.c0, size.c1), trans(0., size.c1)};
108 for (size_t i = 0; i < 4; ++i) {
109 DVec p0 = corners[i];
110 DVec p1 = corners[(i + 1) % 4];
111 segments.insert(typename GeometryObjectD<3>::LineSegment(p0, p1));
112 for (size_t j = 1; j < ptsz.size(); ++j) {
113 DVec q0 = p0;
114 double z = ptsz[j];
115 p0[size_t(Primitive<3>::DIRECTION_VERT)] = z;
116 p1[size_t(Primitive<3>::DIRECTION_VERT)] = z;
117 segments.insert(typename GeometryObjectD<3>::LineSegment(q0, p0));
118 segments.insert(typename GeometryObjectD<3>::LineSegment(p0, p1));
119 }
120 }
121}
122
123 void RotatedCuboid::writeXMLAttr(XMLWriter::Element& dest_xml_object, const AxisNames& axes) const {
124 Block<3>::writeXMLAttr(dest_xml_object, axes);
125 dest_xml_object.attr("angle", getAngle());
126}
127
128 shared_ptr<GeometryObject> read_cuboid(GeometryReader& reader) {
129 shared_ptr<Block<3>> block;
130 if (reader.source.hasAttribute("angle")) {
131 block.reset(new RotatedCuboid(reader.source.requireAttribute<double>("angle")));
132 } else {
133 block.reset(new Block<3>());
134 }
135 block->size.lon() = details::readAlternativeAttrs(reader, "d" + reader.getAxisLongName(), "length");
136 details::setupBlock2D3D(reader, *block);
137 return block;
138}
139
140 static GeometryReader::RegisterObjectReader cuboid_reader(PLASK_CUBOID_NAME, read_cuboid);
141
142} // namespace plask