PLaSK library
Loading...
Searching...
No Matches
triangle.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 "triangle.hpp"
15#include "reader.hpp"
16
17#include "../manager.hpp"
18
19#define PLASK_TRIANGLE_NAME "triangle"
20
21namespace plask {
22
24
25std::string Triangle::getTypeName() const { return NAME; }
26
28 : BaseClass(material), p0(p0), p1(p1) {}
29
34
36 return Box2D(std::min(std::min(p0.c0, p1.c0), 0.0), std::min(std::min(p0.c1, p1.c1), 0.0),
37 std::max(std::max(p0.c0, p1.c0), 0.0), std::max(std::max(p0.c1, p1.c1), 0.0));
38}
39
40inline static double sign(const Vec<2, double>& p1, const Vec<2, double>& p2, const Vec<2, double>& p3) {
41 return (p1.c0 - p3.c0) * (p2.c1 - p3.c1) - (p2.c0 - p3.c0) * (p1.c1 - p3.c1);
42}
43
44// Like sign, but with p3 = (0, 0)
45inline static double sign0(const Vec<2, double>& p1, const Vec<2, double>& p2) {
46 return (p1.c0) * (p2.c1) - (p2.c0) * (p1.c1);
47}
48
49bool Triangle::contains(const Triangle::DVec& p) const {
50 // algorithm comes from:
51 // http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-triangle
52 // with: v1 -> p0, v2 -> p1, v3 -> (0, 0)
53 // maybe barycentric method would be better?
54 bool b1 = sign(p, p0, p1) < 0.0;
55 bool b2 = sign0(p, p1) < 0.0;
56 return (b1 == b2) && (b2 == (sign(p, Primitive<2>::ZERO_VEC, p0) < 0.0));
57}
58
59void Triangle::addPointsAlongToSet(std::set<double>& points,
61 unsigned max_steps,
62 double min_step_size) const {
63 assert(0 < int(direction) && int(direction) < 3);
64 if (this->max_steps) max_steps = this->max_steps;
65 if (this->min_step_size) min_step_size = this->min_step_size;
66
67 double x[3] = {0., p0[int(direction) - 1], p1[int(direction) - 1]};
68
69 // Sort x
70 if (x[2] < x[0]) std::swap(x[0], x[2]);
71 if (x[1] > x[2])
72 std::swap(x[1], x[2]);
73 else if (x[1] < x[0])
74 std::swap(x[1], x[0]);
75
76 for (int i = 0; i < 3; ++i) points.insert(x[i]);
77 double dx02 = x[2] - x[0];
78 if (dx02 == 0) return;
79
80 for (int i = 0; i < 2; ++i) {
81 double dx = x[i + 1] - x[i];
82 unsigned maxsteps = max_steps * (dx / dx02);
83 unsigned steps = min(unsigned(dx / min_step_size), maxsteps);
84 double step = dx / steps;
85 for (unsigned j = 1; j < steps; ++j) points.insert(x[i] + j * step);
86 }
87}
88
90 unsigned max_steps,
91 double min_step_size) const {
93 throw NotImplemented("triangular mesh for triangles non-uniform in transverse direction");
94 typedef typename GeometryObjectD<2>::LineSegment Segment;
96 segments.insert(Segment(Primitive<2>::ZERO_VEC, p0));
97 segments.insert(Segment(Primitive<2>::ZERO_VEC, p1));
98 segments.insert(Segment(p0, p1));
99 } else {
100 if (this->max_steps) max_steps = this->max_steps;
101 if (this->min_step_size) min_step_size = this->min_step_size;
102
103 // Here we replace x and y for simplicity of analysis
104 double x[3] = {0., p0[1], p1[1]};
105 double y[3] = {0., p0[0], p1[0]};
106
107 // Sort x
108 if (x[2] < x[0]) {
109 std::swap(x[0], x[2]);
110 std::swap(y[0], y[2]);
111 }
112 if (x[1] > x[2]) {
113 std::swap(x[1], x[2]);
114 std::swap(y[1], y[2]);
115 } else if (x[1] < x[0]) {
116 std::swap(x[1], x[0]);
117 std::swap(y[1], y[0]);
118 }
119
120 double dx02 = x[2] - x[0];
121 if (dx02 == 0) return;
122
123 double a2 = (y[2] - y[0]) / dx02, b2 = (x[2] * y[0] - x[0] * y[2]) / dx02;
124
125 DVec d1(y[0], x[0]), d2(y[0], x[0]);
126 for (int i = 0; i < 2; ++i) {
127 double dx = x[i + 1] - x[i];
128 double a1 = (y[i + 1] - y[i]) / dx, b1 = (x[i + 1] * y[i] - x[i] * y[i + 1]) / dx;
129 unsigned maxsteps = max_steps * (dx / dx02);
130 unsigned steps = min(unsigned(dx / min_step_size), maxsteps);
131 if (steps < 2) continue;
132 double step = dx / steps;
133 for (unsigned j = 0; j < steps; ++j) {
134 double t = x[i] + j * step;
135 DVec e1(a1 * t + b1, t), e2(a2 * t + b2, t);
136 if (i != 0 || j != 0) {
137 segments.insert(Segment(d1, e1));
138 segments.insert(Segment(d2, e2));
139 segments.insert(Segment(e1, e2));
140 }
141 d1 = e1;
142 d2 = e2;
143 }
144 }
145 DVec e(y[2], x[2]);
146 segments.insert(Segment(d1, e));
147 segments.insert(Segment(d2, e));
148 }
149}
150
153 materialProvider->writeXML(dest_xml_object, axes)
154 .attr("a" + axes.getNameForTran(), p0.tran())
155 .attr("a" + axes.getNameForVert(), p0.vert())
156 .attr("b" + axes.getNameForTran(), p1.tran())
157 .attr("b" + axes.getNameForVert(), p1.vert());
158}
159
161 shared_ptr<Triangle> triangle(new Triangle());
162 if (reader.manager.draft) {
163 triangle->p0.tran() = reader.source.getAttribute("a" + reader.getAxisTranName(), 0.0);
164 triangle->p0.vert() = reader.source.getAttribute("a" + reader.getAxisVertName(), 0.0);
165 triangle->p1.tran() = reader.source.getAttribute("b" + reader.getAxisTranName(), 0.0);
166 triangle->p1.vert() = reader.source.getAttribute("b" + reader.getAxisVertName(), 0.0);
167 } else {
168 triangle->p0.tran() = reader.source.requireAttribute<double>("a" + reader.getAxisTranName());
169 triangle->p0.vert() = reader.source.requireAttribute<double>("a" + reader.getAxisVertName());
170 triangle->p1.tran() = reader.source.requireAttribute<double>("b" + reader.getAxisTranName());
171 triangle->p1.vert() = reader.source.requireAttribute<double>("b" + reader.getAxisVertName());
172 }
173 triangle->readMaterial(reader);
174 reader.source.requireTagEnd();
175 return triangle;
176}
177
178static GeometryReader::RegisterObjectReader triangle_reader(PLASK_TRIANGLE_NAME, read_triangle);
179
180} // namespace plask