Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
surface.cpp
Go to the documentation of this file.
3/*
4Copyright (c) 2000 Igor B. Smirnov
5
6The file can be used, copied, modified, and distributed
7according to the terms of GNU Lesser General Public License version 2.1
8as published by the Free Software Foundation,
9and provided that the above copyright notice, this permission notice,
10and notices about any modifications of the original text
11appear in all copies and in supporting documentation.
12The file is provided "as is" without express or implied warranty.
13*/
14
15namespace Heed {
16
17// **** splane ****
18absref absref::* splane::aref_splane[2] = {(absref absref::*)&splane::pn,
19 (absref absref::*)&splane::dir_ins};
20
23}
24
25int splane::check_point_inside(const point& fpt, const vec& dir,
26 vfloat fprec) const {
27 mfunname("int splane::check_point_inside(const point&, const vec&, vfloat)");
28 if (dir == dv0) {
29 // this is not useful
30 if (fpt == pn.Gpiv()) return 1;
31 vec v = fpt - pn.Gpiv();
32 if (cos2vec(dir_ins, v) >= -vprecision) return 1;
33 return 0;
34 }
35 if (pn.check_point_in(fpt, fprec) == 1) {
36 vfloat ca = cos2vec(dir, dir_ins);
37 if (ca < 0) return 0;
38 return 1;
39 }
40 vec v = fpt - pn.Gpiv();
41 if (cos2vec(dir_ins, v) >= 0) return 1;
42 return 0;
43}
44
45int splane::check_point_inside1(const point& fpt, int s_ext,
46 vfloat fprec) const {
47 if (pn.check_point_in(fpt, fprec) == 1) {
48 if (s_ext == 1) return 0;
49 return 1;
50 }
51 vec v = fpt - pn.Gpiv();
52 if (cos2vec(dir_ins, v) > 0) return 1;
53 return 0;
54}
55
56int splane::range(const trajestep& fts, vfloat* crange, point* cpt,
57 int* s_ext) const {
58 mfunname("int splane::range(...)");
59 if (fts.s_range_cf == 0) {
60 // straight line
61 point pt = pn.cross(straight(fts.currpos, fts.dir));
62 if (vecerror != 0) {
63 vecerror = 0;
64 return 0;
65 }
66 vfloat rng = (pt - fts.currpos).length();
67 if (pt == fts.currpos || check_par(pt - fts.currpos, fts.dir, 0.01) == 1) {
68 // looks like not matter ^
69 // otherwise the point is behind plane
70 if (fts.mrange >= rng) {
71 // otherwise it can not reach the plane
72 cpt[0] = pt;
73 crange[0] = rng;
74 vfloat t = cos2vec(fts.dir, dir_ins);
75 if (t < 0)
76 s_ext[0] = 1;
77 else if (t > 0)
78 s_ext[0] = 0;
79 else
80 s_ext[0] = 2;
81 return 1;
82 }
83 return 0;
84 } else
85 return 0;
86 } else {
87 point pt[2];
88 circumf cf(fts.currpos + fts.relcen,
89 fts.dir || fts.relcen, // if to us, moving against clock
90 fts.relcen.length());
91 int q = cf.cross(pn, pt, 0.0);
92 if (q == -1) {
93 // total circle lies in the plane
94 cpt[0] = fts.currpos;
95 crange[0] = 0.0;
96 s_ext[0] = 2;
97 return 1;
98 }
99 if (q == 0) return 0;
100 if (q == 1) {
101 vec r1 = -fts.relcen;
102 vec r2 = pt[0] - cf.Gpiv();
103 vfloat angle = ang2projvec(r1, r2, cf.Gdir());
104 vfloat rng = cf.Grad() * angle;
105 if (fts.mrange >= rng) {
106 cpt[0] = pt[0];
107 crange[0] = rng;
108 vfloat c = cos2vec(dir_ins, fts.relcen);
109 if (angle == 0.0) {
110 // cross in the current point
111 if (c > 0)
112 s_ext[0] = 0;
113 else if (c < 0)
114 s_ext[0] = 1;
115 else
116 s_ext[0] = 2;
117 } else {
118 if (c > 0)
119 s_ext[0] = 1;
120 else if (c < 0)
121 s_ext[0] = 0;
122 else
123 s_ext[0] = 2;
124 }
125 return 1;
126 } else
127 return 0;
128 }
129 if (q == 2) {
130 int qq = 0;
131 vec r = -fts.relcen;
132 vec vcr[2];
133 vcr[0] = pt[0] - cf.Gpiv();
134 vcr[1] = pt[1] - cf.Gpiv();
135 vfloat angle[2];
136 angle[0] = ang2projvec(r, vcr[0], cf.Gdir());
137 angle[1] = ang2projvec(r, vcr[1], cf.Gdir());
138 if (angle[0] > angle[1]) { // ordering
139 vfloat a = angle[0];
140 angle[0] = angle[1];
141 angle[1] = a;
142 point p = pt[0];
143 pt[0] = pt[1];
144 pt[1] = p;
145 }
146 vfloat rng;
147 rng = cf.Grad() * angle[0];
148 if (fts.mrange >= rng) {
149 // find out what the first point means
150 int ins = 0; // 1 if the point inside and exits
151 vec td = fts.dir;
152 td.turn(cf.Gdir(), angle[0]); // local dir in the crossing point
153 vfloat t = cos2vec(td, dir_ins);
154 if (t < 0)
155 ins = 1; // means the point was inside and now exiting
156 else
157 ins = 0;
158 cpt[0] = pt[0];
159 crange[0] = rng;
160 s_ext[0] = ins;
161 qq++;
162 rng = cf.Grad() * angle[1];
163 if (fts.mrange >= rng) {
164 cpt[1] = pt[1];
165 crange[1] = rng;
166 s_ext[1] = (ins == 0 ? 1 : 0);
167 qq++;
168 }
169 }
170 return qq;
171 }
172 }
173 return 0;
174}
175
176void splane::print(std::ostream& file, int l) const {
177 if (l > 0) {
178 Ifile << "splane:\n";
179 indn.n += 2;
180 file << pn;
181 Ifile << "dir_ins: " << noindent << dir_ins << '\n';
182 indn.n -= 2;
183 }
184}
185
186// **** ulsvolume ****
188 for (int n = 0; n < qsurf; n++) adrsurf[n] = surf[n].get();
190}
191
192int ulsvolume::check_point_inside(const point& fpt, const vec& dir) const {
193 mfunname("ulsvolume::check_point_inside(const point&, const vec&)");
194 check_econd11(qsurf, <= 0, mcerr);
195 for (int n = 0; n < qsurf; n++) {
196 if (!(surf[n].get()->check_point_inside(fpt, dir, prec))) {
197 return 0;
198 }
199 }
200#ifdef TRACE_find_embed_vol
201 indn.n++;
202 Imcout << "ulsvolume::check_point_inside: the point is in volume\n";
203 Imcout << "point:" << fpt;
204 print(mcout, 0);
205 indn.n--;
206#endif
207 return 1;
208}
209
210int ulsvolume::range_ext(trajestep& fts, int s_ext) const {
211 mfunnamep("int ulsvolume::range_ext(trajestep& fts, int s_ext) const");
212 check_econd11(qsurf, <= 0, mcerr);
213#ifdef DEBUG_ulsvolume_range_ext
214 mcout << "ulsvolume::range_ext, START, s_ext=" << s_ext << " qsurf=" << qsurf
215 << '\n';
216 mcout << fts;
217#endif
218 constexpr int pqcrossurf = 4;
219 vfloat crange[pqcrossurf];
220 point cpt[pqcrossurf];
221 int fs_ext[pqcrossurf];
222 int n, m, nc;
223 int s = 0; // sign of crossing
224 if (s_ext == 1) {
225 for (n = 0; n < qsurf; n++) {
226 int qc = surf[n].get()->range(fts, crange, cpt, fs_ext);
227 for (m = 0; m < qc; m++) {
228 if (fs_ext[m] == 1) {
229 s = 1;
230 // The last minute change, it was 0 somewhy instead of m
231 fts.mrange = crange[m]; // reduce the range
232 fts.mpoint = cpt[m];
233 break; // take only the first exit point, it should be closest
234 } else if (fs_ext[m] == 0) {
235 if (!(surf[n].get()->check_point_inside(fts.currpos, fts.dir,
236 prec))) {
237 funnw.ehdr(mcerr);
238 mcerr << "\nshould never happen\n"
239 << "It may happen if you call this function with s_ext==1\n"
240 << "for point outside the volume\n";
241 spexit(mcerr);
242 }
243 } else if (fs_ext[m] == 2)
244 break; // don't know what to do, safe to ignore
245 }
246 }
247
248 if (s == 1) {
249 fts.s_prec = 0;
250 }
251 return s;
252 } else { // for if(s_ext==1)
253 int ss = 0; // sign that there is cross with any of the surfaces
254 for (n = 0; n < qsurf; n++) {
255#ifdef DEBUG_ulsvolume_range_ext
256 Iprintn(mcout, n);
257#endif
258 int qc = surf[n].get()->range(fts, crange, cpt, fs_ext);
259#ifdef DEBUG_ulsvolume_range_ext
260 mcout << "ulsvolume::range_ext: qc=" << qc << "\n";
261 surf[n]->print(mcout, 1);
262#endif
263 for (nc = 0; nc < qc; nc++) // loop by crossing points
264 {
265#ifdef DEBUG_ulsvolume_range_ext
266 mcout << "nc=" << nc << " fs_ext[nc]=" << fs_ext[nc] << '\n';
267#endif
268 if (fs_ext[nc] == 0) // thus ignoring exitted surfaces
269 {
270 s = 1;
271 for (m = 0; m < qsurf; m++) // scan other surfaces and verify that
272 { // the crossing point is inside
273 if (m != n) {
274 if (surf[m].get()->check_point_inside1(cpt[nc], fs_ext[nc],
275 prec) == 0) {
276#ifdef DEBUG_ulsvolume_range_ext
277 mcout << "m=" << m << '\n';
278 mcout << "Since the point is outside of the other surface, "
279 << "it can not be border of volume\n";
280#endif
281 s = 0;
282 break;
283 }
284 }
285 }
286#ifdef DEBUG_ulsvolume_range_ext
287 Iprintn(mcout, s);
288#endif
289 if (s == 1) {
290#ifdef DEBUG_ulsvolume_range_ext
291 mcout << "The crossing point is inside all other surfaces, \n"
292 << "so it is good crossing point\n";
293#endif
294 ss = 1;
295 fts.mrange = crange[nc];
296 fts.mpoint = cpt[nc];
297 break; // since points are ordered, go to next surface,
298 // may be there is nearer crossing point
299 }
300 }
301 }
302 }
303 if (ss == 1) {
304 fts.s_prec = 0;
305 }
306#ifdef DEBUG_ulsvolume_range_ext
307 mcout << "ulsvolume::range_ext: at the end\n";
308 print(mcout, 1);
309 mcout << "ss=" << ss << '\n';
310#endif
311 return ss;
312 }
313}
314/*
315// Old comment, may be not valid, or not at the right place:
316// Straight track:
317//Two variants of behavior:
318//From outside:
319//1. For each cross section from right side to check if the crossing point is
320// from internal side from each other surfaces
321//2. Find the most father point of cross section for right side
322// and to check if it is from internal side for all other surfaces.
323
324//From inside:
325//1. For each cross section from right side to check if the crossing point is
326// from internal side from each other surfaces
327//2. Find the nearest point of cross section for right side
328//there is no need to check: cross point must exist.
329
330//I choose number 2. Reason: for outside number 1 the number of checking is
331//proportional number_of_surf**2
332*/
333
334void ulsvolume::ulsvolume_init(const std::vector<std::shared_ptr<surface> >& fsurf,
335 const std::string& fname, vfloat fprec) {
336 prec = fprec;
337 name = fname;
338 if (qsurf > 0) {
339 for (int n = 0; n < qsurf; ++n) surf[n].reset();
340 }
341 qsurf = fsurf.size();
342 for (int n = 0; n < qsurf; ++n) {
343 surf[n] = fsurf[n];
344 }
345}
346
347ulsvolume::ulsvolume(const std::vector<std::shared_ptr<surface> >& fsurf,
348 char* fname, vfloat fprec)
349 : qsurf(fsurf.size()), name(fname) {
350 mfunname("ulsvolume::ulsvolume(...)");
352 prec = fprec;
353 for (int n = 0; n < qsurf; ++n) surf[n] = fsurf[n];
354}
355
357 : absref(f), absvol(f), qsurf(f.qsurf), name(f.name) {
358 mfunname("ulsvolume::ulsvolume(...)");
360 prec = f.prec;
361 for (int n = 0; n < qsurf; ++n) surf[n] = f.surf[n];
362}
363
365 : absref(f), absvol(f), qsurf(f.qsurf), name(f.name) {
366 mfunname("ulsvolume::ulsvolume(...)");
368 prec = f.prec;
369 for (int n = 0; n < qsurf; ++n) surf[n] = f.surf[n];
370}
371
372void ulsvolume::print(std::ostream& file, int l) const {
373 char s[1000];
374 chname(s);
375 Ifile << "ulsvolume::print(l=" << l << "): " << s << '\n';
376 if (l > 0) {
377 indn.n += 2;
378 Ifile << "qsurf=" << qsurf << " prec=" << prec << '\n';
379 for (int n = 0; n < qsurf; ++n) {
380 Ifile << " nsurf=" << n << '\n';
381 surf[n].get()->print(file, l);
382 }
383 absvol::print(file, l);
384 indn.n -= 2;
385 }
386}
387
388/*
389manip_ulsvolume::manip_ulsvolume(manip_ulsvolume& f)
390 // TODO!
391 : absref(f), manip_absvol(f), ulsvolume((ulsvolume&)f) {}
392*/
393
395 : absref(f), manip_absvol(f), ulsvolume(f) {}
396
397void manip_ulsvolume::print(std::ostream& file, int l) const {
398 if (l <= 0) return;
399 char s[1000];
400 chname(s);
401 Ifile << "manip_ulsvolume::print(l=" << l << "): " << s << '\n';
402 l = l - 1;
403 if (l > 0) {
404 indn.n += 2;
405 // If to call this it calls manip_ulsvolume::print again and loop...
406 ulsvolume::print(file, l - 1);
407 indn.n -= 2;
408 }
409}
410}
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:155
#define mfunnamep(string)
Definition: FunNameStack.h:49
#define spexit(stream)
Definition: FunNameStack.h:256
#define check_econd12(a, sign, b, stream)
Definition: FunNameStack.h:163
#define mfunname(string)
Definition: FunNameStack.h:45
virtual void print(std::ostream &file, int l) const
Definition: volume.cpp:120
vfloat prec
Definition: volume.h:72
Circumference, determined by point (center), normal vector, and radius.
Definition: circumf.h:23
Abstract base classs for volume "manipulators".
Definition: volume.h:128
virtual void chname(char *nm) const
Definition: surface.h:191
virtual void print(std::ostream &file, int l) const
Definition: surface.cpp:397
point cross(const straight &sl) const
Definition: plane.cpp:75
point Gpiv() const
Definition: plane.h:32
int check_point_in(const point &fp, vfloat prec) const
Return 1 if a point is in the plane (within precision prec).
Definition: plane.cpp:68
Point.
Definition: vec.h:368
plane pn
Definition: surface.h:70
int range(const trajestep &fts, vfloat *crange, point *cpt, int *s_ext) const override
Definition: surface.cpp:56
static absref absref::* aref_splane[2]
Definition: surface.h:74
void print(std::ostream &file, int l) const override
Definition: surface.cpp:176
vec dir_ins
Definition: surface.h:71
absref_transmit get_components() override
Definition: surface.cpp:21
int check_point_inside(const point &fpt, const vec &dir, vfloat fprec) const override
Definition: surface.cpp:25
int check_point_inside1(const point &fpt, int s_ext, vfloat fprec) const override
Definition: surface.cpp:45
Straight line, as combination of vector and point.
Definition: straight.h:24
point currpos
Current position.
Definition: trajestep.h:74
vfloat mrange
Maximal possible range.
Definition: trajestep.h:93
vec dir
Unit vector.
Definition: trajestep.h:76
Unlimited surfaces volume.
Definition: surface.h:123
static constexpr int pqqsurf
Definition: surface.h:143
std::array< std::shared_ptr< surface >, pqqsurf > surf
Definition: surface.h:145
void print(std::ostream &file, int l) const override
Definition: surface.cpp:372
ulsvolume()
Default constructor.
Definition: surface.h:156
std::string name
Definition: surface.h:146
surface * adrsurf[pqqsurf]
Definition: surface.h:150
absref_transmit get_components() override
Definition: surface.cpp:187
void chname(char *nm) const override
Definition: surface.h:174
int range_ext(trajestep &fts, int s_ext) const override
Definition: surface.cpp:210
int check_point_inside(const point &fpt, const vec &dir) const override
Definition: surface.cpp:192
void ulsvolume_init(const std::vector< std::shared_ptr< surface > > &fsurf, const std::string &fname, vfloat fprec)
Definition: surface.cpp:334
Definition: vec.h:179
void turn(const vec &dir, vfloat angle) override
Turn this vector.
Definition: vec.cpp:216
vfloat length() const
Definition: vec.h:196
Definition: BGMesh.cpp:6
vfloat ang2projvec(const vec &r1, const vec &r2, const vec &normal)
Definition: vec.cpp:136
std::ostream & noindent(std::ostream &f)
Definition: prstream.cpp:17
vec dv0(0, 0, 0)
Definition: vec.h:308
int vecerror
Definition: vec.cpp:29
vfloat cos2vec(const vec &r1, const vec &r2)
Definition: vec.cpp:66
indentation indn
Definition: prstream.cpp:15
const vfloat vprecision
Definition: vfloat.h:17
double vfloat
Definition: vfloat.h:16
#define mcout
Definition: prstream.h:126
#define Ifile
Definition: prstream.h:195
#define mcerr
Definition: prstream.h:128
#define Iprintn(file, name)
Definition: prstream.h:204
#define Imcout
Definition: prstream.h:196