Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
SolidTube.cc
Go to the documentation of this file.
1#include <cmath>
2#include <iostream>
3
5#include "Garfield/Polygon.hh"
7
8namespace Garfield {
9
10SolidTube::SolidTube(const double cx, const double cy, const double cz,
11 const double rt, const double lz)
12 : Solid(cx, cy, cz, "SolidTube"),
13 m_rMax(rt),
14 m_lZ(lz) {
15 UpdatePolygon();
16}
17
18SolidTube::SolidTube(const double cx, const double cy, const double cz,
19 const double rt, const double lz,
20 const double dx, const double dy, const double dz)
21 : SolidTube(cx, cy, cz, rt, lz) {
22 SetDirection(dx, dy, dz);
23}
24
25void SolidTube::UpdatePolygon() {
26 std::lock_guard<std::mutex> guard(m_mutex);
27 const unsigned int nP = 4. * (m_n - 1);
28 const double alpha = Pi / nP;
29 const double calpha = cos(alpha);
30 // Set the radius of the approximating polygon.
31 m_rp = m_rMax;
32 if (m_average) {
33 const double f = 2. / (1. + asinh(tan(alpha)) * calpha / tan(alpha));
34 m_rp *= f;
35 }
36 // Set the inradius of the polygon.
37 m_ri = m_rp * calpha;
38 // Set the coordinates of the polygon corners.
39 m_xp.clear();
40 m_yp.clear();
41 for (unsigned int i = 0; i < nP; ++i) {
42 const double phi = m_rot + HalfPi * i / (m_n - 1.);
43 const double cphi = cos(phi);
44 const double sphi = sin(phi);
45 m_xp.push_back(m_rp * cphi);
46 m_yp.push_back(m_rp * sphi);
47 }
48}
49
50bool SolidTube::IsInside(const double x, const double y, const double z,
51 const bool tesselated) const {
52 // Transform the point to local coordinates.
53 double u = x, v = y, w = z;
54 ToLocal(x, y, z, u, v, w);
55
56 if (fabs(w) > m_lZ) return false;
57
58 const double rho = sqrt(u * u + v * v);
59 if (!tesselated) return (rho <= m_rMax);
60
61 if (rho > m_rp) return false;
62 if (rho < m_ri) return true;
63 bool inside = false;
64 bool edge = false;
65 Polygon::Inside(m_xp, m_yp, u, v, inside, edge);
66 return inside;
67}
68
69bool SolidTube::GetBoundingBox(double& xmin, double& ymin, double& zmin,
70 double& xmax, double& ymax, double& zmax) const {
71 if (m_cTheta == 1. && m_cPhi == 1.) {
72 xmin = m_cX - m_rMax;
73 xmax = m_cX + m_rMax;
74 ymin = m_cY - m_rMax;
75 ymax = m_cY + m_rMax;
76 zmin = m_cZ - m_lZ;
77 zmax = m_cZ + m_lZ;
78 return true;
79 }
80
81 const double dd = sqrt(m_rMax * m_rMax + m_lZ * m_lZ);
82 xmin = m_cX - dd;
83 xmax = m_cX + dd;
84 ymin = m_cY - dd;
85 ymax = m_cY + dd;
86 zmin = m_cZ - dd;
87 zmax = m_cZ + dd;
88 return true;
89}
90
91void SolidTube::SetRadius(const double r) {
92 if (r <= 0.) {
93 std::cerr << "SolidTube::SetRadius: Radius must be > 0.\n";
94 return;
95 }
96 m_rMax = r;
97 UpdatePolygon();
98}
99
100void SolidTube::SetHalfLength(const double lz) {
101 if (lz <= 0.) {
102 std::cerr << "SolidTube::SetHalfLength: Half-length must be > 0.\n";
103 return;
104 }
105 m_lZ = lz;
106 UpdatePolygon();
107}
108
109void SolidTube::SetSectors(const unsigned int n) {
110 if (n < 1) {
111 std::cerr << "SolidTube::SetSectors: Number must be > 0.\n";
112 return;
113 }
114 m_n = n;
115 UpdatePolygon();
116}
117
118bool SolidTube::SolidPanels(std::vector<Panel>& panels) {
119
120 const auto id = GetId();
121 const auto nPanels = panels.size();
122 // Direction vector.
123 const double fnorm = sqrt(m_dX * m_dX + m_dY * m_dY + m_dZ * m_dZ);
124 if (fnorm <= 0) {
125 std::cerr << "SolidTube::SolidPanels:\n"
126 << " Zero norm direction vector; no panels generated.\n";
127 return false;
128 }
129
130 double r = m_rp;
131 const unsigned int nPoints = 4 * (m_n - 1);
132 // Create the top lid.
133 if (m_toplid) {
134 std::vector<double> xv;
135 std::vector<double> yv;
136 std::vector<double> zv;
137 for (unsigned int i = 1; i <= nPoints; i++) {
138 const double alpha = m_rot + HalfPi * (i - 1.) / (m_n - 1.);
139 // Rotate into place.
140 double x, y, z;
141 ToGlobal(r * cos(alpha), r * sin(alpha), m_lZ, x, y, z);
142 xv.push_back(x);
143 yv.push_back(y);
144 zv.push_back(z);
145 }
146 Panel panel;
147 panel.a = m_cPhi * m_sTheta;
148 panel.b = m_sPhi * m_sTheta;
149 panel.c = m_cTheta;
150 panel.xv = xv;
151 panel.yv = yv;
152 panel.zv = zv;
153 panel.colour = m_colour;
154 panel.volume = id;
155 panels.push_back(std::move(panel));
156 }
157 // Create the bottom lid.
158 if (m_botlid) {
159 std::vector<double> xv;
160 std::vector<double> yv;
161 std::vector<double> zv;
162 for (unsigned int i = 1; i <= nPoints; i++) {
163 const double alpha = m_rot + HalfPi * (i - 1.) / (m_n - 1.);
164 // Rotate into place.
165 double x, y, z;
166 ToGlobal(r * cos(alpha), r * sin(alpha), -m_lZ, x, y, z);
167 xv.push_back(x);
168 yv.push_back(y);
169 zv.push_back(z);
170 }
171 Panel panel;
172 panel.a = -m_cPhi * m_sTheta;
173 panel.b = -m_sPhi * m_sTheta;
174 panel.c = -m_cTheta;
175 panel.xv = xv;
176 panel.yv = yv;
177 panel.zv = zv;
178 panel.colour = m_colour;
179 panel.volume = id;
180 panels.push_back(std::move(panel));
181 }
182 // Create the side panels.
183 double u = r * cos(m_rot);
184 double v = r * sin(m_rot);
185 // Rotate into place.
186 double xv0, yv0, zv0;
187 ToGlobal(u, v, -m_lZ, xv0, yv0, zv0);
188 double xv1, yv1, zv1;
189 ToGlobal(u, v, +m_lZ, xv1, yv1, zv1);
190 // Go around the cylinder.
191 for (unsigned int i = 2; i <= nPoints + 1; i++) {
192 // Bottom and top of the line along the axis of the cylinder.
193 double alpha = m_rot + HalfPi * (i - 1.) / (m_n - 1.);
194 u = r * cos(alpha);
195 v = r * sin(alpha);
196 // Rotate into place.
197 double xv2, yv2, zv2;
198 ToGlobal(u, v, +m_lZ, xv2, yv2, zv2);
199 double xv3, yv3, zv3;
200 ToGlobal(u, v, -m_lZ, xv3, yv3, zv3);
201 // Store the plane.
202 Panel panel;
203 alpha = m_rot + HalfPi * (i - 1.5) / (m_n - 1.);
204 const double cAlpha = cos(alpha);
205 const double sAlpha = sin(alpha);
206 panel.a = m_cPhi * m_cTheta * cAlpha - m_sPhi * sAlpha;
207 panel.b = m_sPhi * m_cTheta * cAlpha + m_cPhi * sAlpha;
208 panel.c = -m_sTheta * cAlpha;
209 panel.xv = {xv0, xv1, xv2, xv3};
210 panel.yv = {yv0, yv1, yv2, yv3};
211 panel.zv = {zv0, zv1, zv2, zv3};
212 panel.colour = m_colour;
213 panel.volume = id;
214 panels.push_back(std::move(panel));
215 // Shift the points.
216 xv0 = xv3;
217 yv0 = yv3;
218 zv0 = zv3;
219 xv1 = xv2;
220 yv1 = yv2;
221 zv1 = zv2;
222 }
223 std::cout << "SolidTube::SolidPanels: " << panels.size() - nPanels
224 << " panels.\n";
225 return true;
226}
227
229
230 // Transform the normal vector to local coordinates.
231 double u = 0., v = 0., w = 0.;
232 VectorToLocal(panel.a, panel.b, panel.c, u, v, w);
233 // Identify the vector.
234 if (w > std::max(std::abs(u), std::abs(v))) {
235 return m_dis[0];
236 } else if (w < -std::max(std::abs(u), std::abs(v))) {
237 return m_dis[1];
238 }
239 return m_dis[2];
240}
241
242void SolidTube::Cut(const double x0, const double y0, const double z0,
243 const double xn, const double yn, const double zn,
244 std::vector<Panel>& panels) {
245
246 // -----------------------------------------------------------------------
247 // PLACYC - Cuts cylinder with a plane.
248 // -----------------------------------------------------------------------
249 std::vector<double> xv;
250 std::vector<double> yv;
251 std::vector<double> zv;
252 double r = m_rp;
253 const unsigned int nPoints = 4 * (m_n - 1);
254 const double dphi = HalfPi / (m_n - 1.);
255 // Go through the lines of the top and bottom lids.
256 for (const auto zLid : {-m_lZ, +m_lZ}) {
257 double x1, y1, z1;
258 ToGlobal(r * cos(m_rot), r * sin(m_rot), zLid, x1, y1, z1);
259 // Loop over the points.
260 for (unsigned int i = 2; i <= nPoints + 1; ++i) {
261 const double phi = m_rot + (i - 1.) * dphi;
262 double x2, y2, z2;
263 ToGlobal(r * cos(phi), r * sin(phi), zLid, x2, y2, z2);
264 // Cut with the plane.
265 double xc, yc, zc;
266 if (Intersect(x1, y1, z1, x2, y2, z2, x0, y0, z0,
267 xn, yn, zn, xc, yc, zc)) {
268 xv.push_back(xc);
269 yv.push_back(yc);
270 zv.push_back(zc);
271 }
272 // Shift the coordinates.
273 x1 = x2;
274 y1 = y2;
275 z1 = z2;
276 }
277 }
278 // Go through the ribs.
279 for (unsigned int i = 2; i <= nPoints + 1; ++i) {
280 // Bottom and top of the line along the axis of the cylinder.
281 const double phi = m_rot + (i - 1.) * dphi;
282 const double u = r * cos(phi);
283 const double v = r * sin(phi);
284 double x1, y1, z1;
285 ToGlobal(u, v, +m_lZ, x1, y1, z1);
286 double x2, y2, z2;
287 ToGlobal(u, v, -m_lZ, x2, y2, z2);
288 // Cut with the plane.
289 double xc, yc, zc;
290 if (Intersect(x1, y1, z1, x2, y2, z2, x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
291 xv.push_back(xc);
292 yv.push_back(yc);
293 zv.push_back(zc);
294 }
295 }
296 // Get rid of butterflies.
298
299 if (xv.size() >= 3) {
300 Panel panel;
301 panel.a = xn;
302 panel.b = yn;
303 panel.c = zn;
304 panel.xv = xv;
305 panel.yv = yv;
306 panel.zv = zv;
307 panel.colour = m_colour;
308 panel.volume = GetId();
309 panels.push_back(std::move(panel));
310 }
311}
312
313}
Cylindrical tube.
Definition: SolidTube.hh:12
bool SolidPanels(std::vector< Panel > &panels) override
Retrieve the surface panels of the solid.
Definition: SolidTube.cc:118
double GetDiscretisationLevel(const Panel &panel) override
Retrieve the discretisation level of a panel.
Definition: SolidTube.cc:228
void SetSectors(const unsigned int n)
Definition: SolidTube.cc:109
SolidTube(const double cx, const double cy, const double cz, const double r, const double lz)
Constructor from centre, outer radius, and half-length.
Definition: SolidTube.cc:10
void SetHalfLength(const double lz)
Definition: SolidTube.cc:100
void SetRadius(const double r)
Definition: SolidTube.cc:91
void Cut(const double x0, const double y0, const double z0, const double xn, const double yn, const double zn, std::vector< Panel > &panels) override
Definition: SolidTube.cc:242
bool IsInside(const double x, const double y, const double z, const bool tesselated) const override
Definition: SolidTube.cc:50
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const override
Return the bounding box of the solid.
Definition: SolidTube.cc:69
Abstract base class for solids.
Definition: Solid.hh:28
double m_dZ
Definition: Solid.hh:205
double m_cZ
Definition: Solid.hh:202
void VectorToLocal(const double x, const double y, const double z, double &u, double &v, double &w)
Transform a vector from global to local coordinates.
Definition: Solid.hh:253
double m_cTheta
Polar angle.
Definition: Solid.hh:209
static bool Intersect(const double x1, const double y1, const double z1, const double x2, const double y2, const double z2, const double x0, const double y0, const double z0, const double a, const double b, const double c, double &xc, double &yc, double &zc)
Definition: Solid.cc:52
double m_dX
Direction vector.
Definition: Solid.hh:205
unsigned int GetId() const
Get the ID of the solid.
Definition: Solid.hh:137
void ToLocal(const double x, const double y, const double z, double &u, double &v, double &w) const
Definition: Solid.hh:234
void SetDirection(const double dx, const double dy, const double dz)
Definition: Solid.cc:12
int m_colour
Colour.
Definition: Solid.hh:230
double m_sPhi
Definition: Solid.hh:207
void ToGlobal(const double u, const double v, const double w, double &x, double &y, double &z) const
Definition: Solid.hh:246
double m_sTheta
Definition: Solid.hh:209
double m_cY
Definition: Solid.hh:202
double m_dY
Definition: Solid.hh:205
double m_cX
Centre of the solid.
Definition: Solid.hh:202
double m_cPhi
Azimuthal angle.
Definition: Solid.hh:207
void EliminateButterflies(std::vector< double > &xp, std::vector< double > &yp, std::vector< double > &zp)
Definition: Polygon.cc:355
void Inside(const std::vector< double > &xpl, const std::vector< double > &ypl, const double x, const double y, bool &inside, bool &edge)
Definition: Polygon.cc:187
Surface panel.
Definition: Solid.hh:11
std::vector< double > zv
Z-coordinates of vertices.
Definition: Solid.hh:19
int volume
Reference to solid to which the panel belongs.
Definition: Solid.hh:23
double a
Perpendicular vector.
Definition: Solid.hh:13
double c
Definition: Solid.hh:13
double b
Definition: Solid.hh:13
std::vector< double > xv
X-coordinates of vertices.
Definition: Solid.hh:15
std::vector< double > yv
Y-coordinates of vertices.
Definition: Solid.hh:17
int colour
Colour index.
Definition: Solid.hh:21