PLaSK library
Loading...
Searching...
No Matches
prism.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 "prism.hpp"
15#include "reader.hpp"
16
17#include "../manager.hpp"
18
19#define PLASK_PRISM_NAME "prism"
20
21namespace plask {
22
23const char* Prism::NAME = PLASK_PRISM_NAME;
24
25std::string Prism::getTypeName() const { return NAME; }
26
27Prism::Prism(const Prism::Vec2& p0, const Prism::Vec2& p1, double height, const shared_ptr<Material>& material)
28 : BaseClass(material), p0(p0), p1(p1), height(height) {}
29
31 const Prism::Vec2& p1,
32 double height,
34 : BaseClass(materialTopBottom), p0(p0), p1(p1), height(height) {}
35
37 return Box3D(std::min(std::min(p0.c0, p1.c0), 0.0), std::min(std::min(p0.c1, p1.c1), 0.0), 0.,
38 std::max(std::max(p0.c0, p1.c0), 0.0), std::max(std::max(p0.c1, p1.c1), 0.0), height);
39}
40
41inline static double sign(const Vec<3, double>& p1, const Vec<2, double>& p2, const Vec<2, double>& p3) {
42 return (p1.c0 - p3.c0) * (p2.c1 - p3.c1) - (p2.c0 - p3.c0) * (p1.c1 - p3.c1);
43}
44
45// Like sign, but with p3 = (0, 0)
46inline static double sign0(const Vec<3, double>& p1, const Vec<2, double>& p2) {
47 return (p1.c0) * (p2.c1) - (p2.c0) * (p1.c1);
48}
49
50bool Prism::contains(const Prism::DVec& p) const {
51 if (p.c2 < 0 || p.c2 > height) return false;
52 // algorithm comes from:
53 // http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-triangle
54 // with: v1 -> p0, v2 -> p1, v3 -> (0, 0)
55 // maybe barycentric method would be better?
56 bool b1 = sign(p, p0, p1) < 0.0;
57 bool b2 = sign0(p, p1) < 0.0;
58 return (b1 == b2) && (b2 == (sign(p, Primitive<2>::ZERO_VEC, p0) < 0.0));
59}
60
63 materialProvider->writeXML(dest_xml_object, axes)
64 .attr("a" + axes.getNameForLong(), p0.tran())
65 .attr("a" + axes.getNameForTran(), p0.vert())
66 .attr("b" + axes.getNameForLong(), p1.tran())
67 .attr("b" + axes.getNameForTran(), p1.vert())
68 .attr("height", height);
69}
70
71void Prism::addPointsAlongToSet(std::set<double>& points,
73 unsigned max_steps,
74 double min_step_size) const {
75 if (direction == Primitive<3>::DIRECTION_VERT) {
77 points.insert(0);
78 points.insert(height);
79 } else {
80 if (this->max_steps) max_steps = this->max_steps;
81 if (this->min_step_size) min_step_size = this->min_step_size;
82 unsigned steps = min(unsigned(height / min_step_size), max_steps);
83 double step = height / steps;
84 for (unsigned i = 0; i <= steps; ++i) points.insert(i * step);
85 }
86 } else {
87 if (this->max_steps) max_steps = this->max_steps;
88 if (this->min_step_size) min_step_size = this->min_step_size;
89
90 double x[3] = {0., p0[int(direction)], p1[int(direction)]};
91
92 // Sort x
93 if (x[2] < x[0]) std::swap(x[0], x[2]);
94 if (x[1] > x[2])
95 std::swap(x[1], x[2]);
96 else if (x[1] < x[0])
97 std::swap(x[1], x[0]);
98
99 for (int i = 0; i < 3; ++i) points.insert(x[i]);
100 double dx02 = x[2] - x[0];
101 if (dx02 == 0) return;
102
103 for (int i = 0; i < 2; ++i) {
104 double dx = x[i + 1] - x[i];
105 unsigned maxsteps = max_steps * (dx / dx02);
106 unsigned steps = min(unsigned(dx / min_step_size), maxsteps);
107 double step = dx / steps;
108 for (unsigned j = 1; j < steps; ++j) points.insert(x[i] + j * step);
109 }
110 }
111}
112
114 unsigned max_steps,
115 double min_step_size) const {
117 throw NotImplemented("prismatic mesh for prisms non-uniform in longitudinal direction");
119 throw NotImplemented("prismatic mesh for prisms non-uniform in transverse direction");
120 std::set<double> vert;
122 typedef typename GeometryObjectD<3>::LineSegment Segment;
123 double pv = 0.;
124 for (double v : vert) {
125 segments.insert(Segment(DVec(0., 0., v), DVec(p0[0], p0[1], v)));
126 segments.insert(Segment(DVec(0., 0., v), DVec(p1[0], p1[1], v)));
127 segments.insert(Segment(DVec(p0[0], p0[1], v), DVec(p1[0], p1[1], v)));
128 if (v != 0.) {
129 segments.insert(Segment(DVec(0., 0., pv), DVec(0., 0., v)));
130 segments.insert(Segment(DVec(p0[0], p0[1], pv), DVec(p0[0], p0[1], v)));
131 segments.insert(Segment(DVec(p1[0], p1[1], pv), DVec(p1[0], p1[1], v)));
132 }
133 pv = v;
134 }
135}
136
139 if (reader.manager.draft) {
140 prism->p0.c0 = reader.source.getAttribute("a" + reader.getAxisLongName(), 0.0);
141 prism->p0.c1 = reader.source.getAttribute("a" + reader.getAxisTranName(), 0.0);
142 prism->p1.c0 = reader.source.getAttribute("b" + reader.getAxisLongName(), 0.0);
143 prism->p1.c1 = reader.source.getAttribute("b" + reader.getAxisTranName(), 0.0);
144 prism->height = reader.source.getAttribute("height", 0.0);
145 } else {
146 prism->p0.c0 = reader.source.requireAttribute<double>("a" + reader.getAxisLongName());
147 prism->p0.c1 = reader.source.requireAttribute<double>("a" + reader.getAxisTranName());
148 prism->p1.c0 = reader.source.requireAttribute<double>("b" + reader.getAxisLongName());
149 prism->p1.c1 = reader.source.requireAttribute<double>("b" + reader.getAxisTranName());
150 prism->height = reader.source.requireAttribute<double>("height");
151 }
152 prism->readMaterial(reader);
153 reader.source.requireTagEnd();
154 return prism;
155}
156
157static GeometryReader::RegisterObjectReader prism_reader(PLASK_PRISM_NAME, read_prism);
158
159} // namespace plask