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
21
namespace
plask
{
22
23
const
char
*
Prism::NAME
=
PLASK_PRISM_NAME
;
24
25
std::string
Prism::getTypeName
()
const
{
return
NAME
; }
26
27
Prism::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
30
Prism::Prism
(
const
Prism::Vec2
& p0,
31
const
Prism::Vec2
& p1,
32
double
height,
33
shared_ptr<MaterialsDB::MixedCompositionFactory>
materialTopBottom
)
34
:
BaseClass
(
materialTopBottom
), p0(p0), p1(p1), height(height) {}
35
36
Box3D
Prism::getBoundingBox
()
const
{
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
41
inline
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)
46
inline
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
50
bool
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
61
void
Prism::writeXMLAttr
(
XMLWriter::Element
&
dest_xml_object
,
const
AxisNames
& axes)
const
{
62
BaseClass::writeXMLAttr
(
dest_xml_object
, axes);
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
71
void
Prism::addPointsAlongToSet
(std::set<double>& points,
72
Primitive<3>::Direction
direction,
73
unsigned
max_steps,
74
double
min_step_size)
const
{
75
if
(direction ==
Primitive<3>::DIRECTION_VERT
) {
76
if
(
materialProvider
->isUniform(
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
113
void
Prism::addLineSegmentsToSet
(std::set<
typename
GeometryObjectD<3>::LineSegment
>& segments,
114
unsigned
max_steps,
115
double
min_step_size)
const
{
116
if
(!
materialProvider
->isUniform(
Primitive<3>::DIRECTION_LONG
))
117
throw
NotImplemented
(
"prismatic mesh for prisms non-uniform in longitudinal direction"
);
118
if
(!
materialProvider
->isUniform(
Primitive<3>::DIRECTION_TRAN
))
119
throw
NotImplemented
(
"prismatic mesh for prisms non-uniform in transverse direction"
);
120
std::set<double> vert;
121
addPointsAlongToSet
(vert,
Primitive<3>::DIRECTION_VERT
,
max_steps
,
min_step_size
);
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
137
shared_ptr<GeometryObject>
read_prism
(
GeometryReader
& reader) {
138
shared_ptr<Prism>
prism
(
new
Prism
());
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
157
static
GeometryReader::RegisterObjectReader prism_reader(
PLASK_PRISM_NAME
,
read_prism
);
158
159
}
// namespace plask
plask
geometry
prism.cpp
Generated by
1.9.8