source: trunk/source/graphics_reps/src/HepPolyhedron.cc@ 872

Last change on this file since 872 was 850, checked in by garnier, 17 years ago

geant4.8.2 beta

File size: 84.8 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id: HepPolyhedron.cc,v 1.31 2008/04/28 16:06:06 allison Exp $
28// GEANT4 tag $Name: HEAD $
29//
30//
31//
32// G4 Polyhedron library
33//
34// History:
35// 23.07.96 E.Chernyaev <Evgueni.Tcherniaev@cern.ch> - initial version
36//
37// 30.09.96 E.Chernyaev
38// - added GetNextVertexIndex, GetVertex by Yasuhide Sawada
39// - added GetNextUnitNormal, GetNextEdgeIndeces, GetNextEdge
40//
41// 15.12.96 E.Chernyaev
42// - added GetNumberOfRotationSteps, RotateEdge, RotateAroundZ, SetReferences
43// - rewritten G4PolyhedronCons;
44// - added G4PolyhedronPara, ...Trap, ...Pgon, ...Pcon, ...Sphere, ...Torus
45//
46// 01.06.97 E.Chernyaev
47// - modified RotateAroundZ, added SetSideFacets
48//
49// 19.03.00 E.Chernyaev
50// - implemented boolean operations (add, subtract, intersect) on polyhedra;
51//
52// 25.05.01 E.Chernyaev
53// - added GetSurfaceArea() and GetVolume();
54//
55// 05.11.02 E.Chernyaev
56// - added createTwistedTrap() and createPolyhedron();
57//
58// 20.06.05 G.Cosmo
59// - added HepPolyhedronEllipsoid;
60//
61// 18.07.07 T.Nikitin
62// - added HepParaboloid;
63
64#include "HepPolyhedron.h"
65#include <CLHEP/Units/PhysicalConstants.h>
66#include <CLHEP/Geometry/Vector3D.h>
67
68#include <cstdlib> // Required on some compilers for std::abs(int) ...
69#include <cmath>
70
71using namespace HepGeom;
72using CLHEP::perMillion;
73using CLHEP::deg;
74using CLHEP::pi;
75using CLHEP::twopi;
76
77/***********************************************************************
78 * *
79 * Name: HepPolyhedron operator << Date: 09.05.96 *
80 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
81 * *
82 * Function: Print contents of G4 polyhedron *
83 * *
84 ***********************************************************************/
85std::ostream & operator<<(std::ostream & ostr, const G4Facet & facet) {
86 for (int k=0; k<4; k++) {
87 ostr << " " << facet.edge[k].v << "/" << facet.edge[k].f;
88 }
89 return ostr;
90}
91
92std::ostream & operator<<(std::ostream & ostr, const HepPolyhedron & ph) {
93 ostr << std::endl;
94 ostr << "Nverteces=" << ph.nvert << ", Nfacets=" << ph.nface << std::endl;
95 int i;
96 for (i=1; i<=ph.nvert; i++) {
97 ostr << "xyz(" << i << ")="
98 << ph.pV[i].x() << ' ' << ph.pV[i].y() << ' ' << ph.pV[i].z()
99 << std::endl;
100 }
101 for (i=1; i<=ph.nface; i++) {
102 ostr << "face(" << i << ")=" << ph.pF[i] << std::endl;
103 }
104 return ostr;
105}
106
107HepPolyhedron::HepPolyhedron(const HepPolyhedron &from)
108/***********************************************************************
109 * *
110 * Name: HepPolyhedron copy constructor Date: 23.07.96 *
111 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
112 * *
113 ***********************************************************************/
114: nvert(0), nface(0), pV(0), pF(0)
115{
116 AllocateMemory(from.nvert, from.nface);
117 for (int i=1; i<=nvert; i++) pV[i] = from.pV[i];
118 for (int k=1; k<=nface; k++) pF[k] = from.pF[k];
119}
120
121HepPolyhedron & HepPolyhedron::operator=(const HepPolyhedron &from)
122/***********************************************************************
123 * *
124 * Name: HepPolyhedron operator = Date: 23.07.96 *
125 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
126 * *
127 * Function: Copy contents of one polyhedron to another *
128 * *
129 ***********************************************************************/
130{
131 if (this != &from) {
132 AllocateMemory(from.nvert, from.nface);
133 for (int i=1; i<=nvert; i++) pV[i] = from.pV[i];
134 for (int k=1; k<=nface; k++) pF[k] = from.pF[k];
135 }
136 return *this;
137}
138
139int
140HepPolyhedron::FindNeighbour(int iFace, int iNode, int iOrder) const
141/***********************************************************************
142 * *
143 * Name: HepPolyhedron::FindNeighbour Date: 22.11.99 *
144 * Author: E.Chernyaev Revised: *
145 * *
146 * Function: Find neighbouring face *
147 * *
148 ***********************************************************************/
149{
150 int i;
151 for (i=0; i<4; i++) {
152 if (iNode == std::abs(pF[iFace].edge[i].v)) break;
153 }
154 if (i == 4) {
155 std::cerr
156 << "HepPolyhedron::FindNeighbour: face " << iFace
157 << " has no node " << iNode
158 << std::endl;
159 return 0;
160 }
161 if (iOrder < 0) {
162 if ( --i < 0) i = 3;
163 if (pF[iFace].edge[i].v == 0) i = 2;
164 }
165 return (pF[iFace].edge[i].v > 0) ? 0 : pF[iFace].edge[i].f;
166}
167
168Normal3D<double> HepPolyhedron::FindNodeNormal(int iFace, int iNode) const
169/***********************************************************************
170 * *
171 * Name: HepPolyhedron::FindNodeNormal Date: 22.11.99 *
172 * Author: E.Chernyaev Revised: *
173 * *
174 * Function: Find normal at given node *
175 * *
176 ***********************************************************************/
177{
178 Normal3D<double> normal = GetUnitNormal(iFace);
179 int k = iFace, iOrder = 1, n = 1;
180
181 for(;;) {
182 k = FindNeighbour(k, iNode, iOrder);
183 if (k == iFace) break;
184 if (k > 0) {
185 n++;
186 normal += GetUnitNormal(k);
187 }else{
188 if (iOrder < 0) break;
189 k = iFace;
190 iOrder = -iOrder;
191 }
192 }
193 return normal.unit();
194}
195
196int HepPolyhedron::GetNumberOfRotationSteps()
197/***********************************************************************
198 * *
199 * Name: HepPolyhedron::GetNumberOfRotationSteps Date: 24.06.97 *
200 * Author: J.Allison (Manchester University) Revised: *
201 * *
202 * Function: Get number of steps for whole circle *
203 * *
204 ***********************************************************************/
205{
206 return fNumberOfRotationSteps;
207}
208
209void HepPolyhedron::SetNumberOfRotationSteps(int n)
210/***********************************************************************
211 * *
212 * Name: HepPolyhedron::SetNumberOfRotationSteps Date: 24.06.97 *
213 * Author: J.Allison (Manchester University) Revised: *
214 * *
215 * Function: Set number of steps for whole circle *
216 * *
217 ***********************************************************************/
218{
219 const int nMin = 3;
220 if (n < nMin) {
221 std::cerr
222 << "HepPolyhedron::SetNumberOfRotationSteps: attempt to set the\n"
223 << "number of steps per circle < " << nMin << "; forced to " << nMin
224 << std::endl;
225 fNumberOfRotationSteps = nMin;
226 }else{
227 fNumberOfRotationSteps = n;
228 }
229}
230
231void HepPolyhedron::ResetNumberOfRotationSteps()
232/***********************************************************************
233 * *
234 * Name: HepPolyhedron::GetNumberOfRotationSteps Date: 24.06.97 *
235 * Author: J.Allison (Manchester University) Revised: *
236 * *
237 * Function: Reset number of steps for whole circle to default value *
238 * *
239 ***********************************************************************/
240{
241 fNumberOfRotationSteps = DEFAULT_NUMBER_OF_STEPS;
242}
243
244void HepPolyhedron::AllocateMemory(int Nvert, int Nface)
245/***********************************************************************
246 * *
247 * Name: HepPolyhedron::AllocateMemory Date: 19.06.96 *
248 * Author: E.Chernyaev (IHEP/Protvino) Revised: 05.11.02 *
249 * *
250 * Function: Allocate memory for GEANT4 polyhedron *
251 * *
252 * Input: Nvert - number of nodes *
253 * Nface - number of faces *
254 * *
255 ***********************************************************************/
256{
257 if (nvert == Nvert && nface == Nface) return;
258 if (pV != 0) delete [] pV;
259 if (pF != 0) delete [] pF;
260 if (Nvert > 0 && Nface > 0) {
261 nvert = Nvert;
262 nface = Nface;
263 pV = new Point3D<double>[nvert+1];
264 pF = new G4Facet[nface+1];
265 }else{
266 nvert = 0; nface = 0; pV = 0; pF = 0;
267 }
268}
269
270void HepPolyhedron::CreatePrism()
271/***********************************************************************
272 * *
273 * Name: HepPolyhedron::CreatePrism Date: 15.07.96 *
274 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
275 * *
276 * Function: Set facets for a prism *
277 * *
278 ***********************************************************************/
279{
280 enum {DUMMY, BOTTOM, LEFT, BACK, RIGHT, FRONT, TOP};
281
282 pF[1] = G4Facet(1,LEFT, 4,BACK, 3,RIGHT, 2,FRONT);
283 pF[2] = G4Facet(5,TOP, 8,BACK, 4,BOTTOM, 1,FRONT);
284 pF[3] = G4Facet(8,TOP, 7,RIGHT, 3,BOTTOM, 4,LEFT);
285 pF[4] = G4Facet(7,TOP, 6,FRONT, 2,BOTTOM, 3,BACK);
286 pF[5] = G4Facet(6,TOP, 5,LEFT, 1,BOTTOM, 2,RIGHT);
287 pF[6] = G4Facet(5,FRONT, 6,RIGHT, 7,BACK, 8,LEFT);
288}
289
290void HepPolyhedron::RotateEdge(int k1, int k2, double r1, double r2,
291 int v1, int v2, int vEdge,
292 bool ifWholeCircle, int ns, int &kface)
293/***********************************************************************
294 * *
295 * Name: HepPolyhedron::RotateEdge Date: 05.12.96 *
296 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
297 * *
298 * Function: Create set of facets by rotation of an edge around Z-axis *
299 * *
300 * Input: k1, k2 - end vertices of the edge *
301 * r1, r2 - radiuses of the end vertices *
302 * v1, v2 - visibility of edges produced by rotation of the end *
303 * vertices *
304 * vEdge - visibility of the edge *
305 * ifWholeCircle - is true in case of whole circle rotation *
306 * ns - number of discrete steps *
307 * r[] - r-coordinates *
308 * kface - current free cell in the pF array *
309 * *
310 ***********************************************************************/
311{
312 if (r1 == 0. && r2 == 0) return;
313
314 int i;
315 int i1 = k1;
316 int i2 = k2;
317 int ii1 = ifWholeCircle ? i1 : i1+ns;
318 int ii2 = ifWholeCircle ? i2 : i2+ns;
319 int vv = ifWholeCircle ? vEdge : 1;
320
321 if (ns == 1) {
322 if (r1 == 0.) {
323 pF[kface++] = G4Facet(i1,0, v2*i2,0, (i2+1),0);
324 }else if (r2 == 0.) {
325 pF[kface++] = G4Facet(i1,0, i2,0, v1*(i1+1),0);
326 }else{
327 pF[kface++] = G4Facet(i1,0, v2*i2,0, (i2+1),0, v1*(i1+1),0);
328 }
329 }else{
330 if (r1 == 0.) {
331 pF[kface++] = G4Facet(vv*i1,0, v2*i2,0, vEdge*(i2+1),0);
332 for (i2++,i=1; i<ns-1; i2++,i++) {
333 pF[kface++] = G4Facet(vEdge*i1,0, v2*i2,0, vEdge*(i2+1),0);
334 }
335 pF[kface++] = G4Facet(vEdge*i1,0, v2*i2,0, vv*ii2,0);
336 }else if (r2 == 0.) {
337 pF[kface++] = G4Facet(vv*i1,0, vEdge*i2,0, v1*(i1+1),0);
338 for (i1++,i=1; i<ns-1; i1++,i++) {
339 pF[kface++] = G4Facet(vEdge*i1,0, vEdge*i2,0, v1*(i1+1),0);
340 }
341 pF[kface++] = G4Facet(vEdge*i1,0, vv*i2,0, v1*ii1,0);
342 }else{
343 pF[kface++] = G4Facet(vv*i1,0, v2*i2,0, vEdge*(i2+1),0,v1*(i1+1),0);
344 for (i1++,i2++,i=1; i<ns-1; i1++,i2++,i++) {
345 pF[kface++] = G4Facet(vEdge*i1,0, v2*i2,0, vEdge*(i2+1),0,v1*(i1+1),0);
346 }
347 pF[kface++] = G4Facet(vEdge*i1,0, v2*i2,0, vv*ii2,0, v1*ii1,0);
348 }
349 }
350}
351
352void HepPolyhedron::SetSideFacets(int ii[4], int vv[4],
353 int *kk, double *r,
354 double dphi, int ns, int &kface)
355/***********************************************************************
356 * *
357 * Name: HepPolyhedron::SetSideFacets Date: 20.05.97 *
358 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
359 * *
360 * Function: Set side facets for the case of incomplete rotation *
361 * *
362 * Input: ii[4] - indeces of original verteces *
363 * vv[4] - visibility of edges *
364 * kk[] - indeces of nodes *
365 * r[] - radiuses *
366 * dphi - delta phi *
367 * ns - number of discrete steps *
368 * kface - current free cell in the pF array *
369 * *
370 ***********************************************************************/
371{
372 int k1, k2, k3, k4;
373
374 if (std::abs((double)(dphi-pi)) < perMillion) { // half a circle
375 for (int i=0; i<4; i++) {
376 k1 = ii[i];
377 k2 = (i == 3) ? ii[0] : ii[i+1];
378 if (r[k1] == 0. && r[k2] == 0.) vv[i] = -1;
379 }
380 }
381
382 if (ii[1] == ii[2]) {
383 k1 = kk[ii[0]];
384 k2 = kk[ii[2]];
385 k3 = kk[ii[3]];
386 pF[kface++] = G4Facet(vv[0]*k1,0, vv[2]*k2,0, vv[3]*k3,0);
387 if (r[ii[0]] != 0.) k1 += ns;
388 if (r[ii[2]] != 0.) k2 += ns;
389 if (r[ii[3]] != 0.) k3 += ns;
390 pF[kface++] = G4Facet(vv[2]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
391 }else if (kk[ii[0]] == kk[ii[1]]) {
392 k1 = kk[ii[0]];
393 k2 = kk[ii[2]];
394 k3 = kk[ii[3]];
395 pF[kface++] = G4Facet(vv[1]*k1,0, vv[2]*k2,0, vv[3]*k3,0);
396 if (r[ii[0]] != 0.) k1 += ns;
397 if (r[ii[2]] != 0.) k2 += ns;
398 if (r[ii[3]] != 0.) k3 += ns;
399 pF[kface++] = G4Facet(vv[2]*k3,0, vv[1]*k2,0, vv[3]*k1,0);
400 }else if (kk[ii[2]] == kk[ii[3]]) {
401 k1 = kk[ii[0]];
402 k2 = kk[ii[1]];
403 k3 = kk[ii[2]];
404 pF[kface++] = G4Facet(vv[0]*k1,0, vv[1]*k2,0, vv[3]*k3,0);
405 if (r[ii[0]] != 0.) k1 += ns;
406 if (r[ii[1]] != 0.) k2 += ns;
407 if (r[ii[2]] != 0.) k3 += ns;
408 pF[kface++] = G4Facet(vv[1]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
409 }else{
410 k1 = kk[ii[0]];
411 k2 = kk[ii[1]];
412 k3 = kk[ii[2]];
413 k4 = kk[ii[3]];
414 pF[kface++] = G4Facet(vv[0]*k1,0, vv[1]*k2,0, vv[2]*k3,0, vv[3]*k4,0);
415 if (r[ii[0]] != 0.) k1 += ns;
416 if (r[ii[1]] != 0.) k2 += ns;
417 if (r[ii[2]] != 0.) k3 += ns;
418 if (r[ii[3]] != 0.) k4 += ns;
419 pF[kface++] = G4Facet(vv[2]*k4,0, vv[1]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
420 }
421}
422
423void HepPolyhedron::RotateAroundZ(int nstep, double phi, double dphi,
424 int np1, int np2,
425 const double *z, double *r,
426 int nodeVis, int edgeVis)
427/***********************************************************************
428 * *
429 * Name: HepPolyhedron::RotateAroundZ Date: 27.11.96 *
430 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
431 * *
432 * Function: Create HepPolyhedron for a solid produced by rotation of *
433 * two polylines around Z-axis *
434 * *
435 * Input: nstep - number of discrete steps, if 0 then default *
436 * phi - starting phi angle *
437 * dphi - delta phi *
438 * np1 - number of points in external polyline *
439 * (must be negative in case of closed polyline) *
440 * np2 - number of points in internal polyline (may be 1) *
441 * z[] - z-coordinates (+z >>> -z for both polylines) *
442 * r[] - r-coordinates *
443 * nodeVis - how to Draw edges joing consecutive positions of *
444 * node during rotation *
445 * edgeVis - how to Draw edges *
446 * *
447 ***********************************************************************/
448{
449 static double wholeCircle = twopi;
450
451 // S E T R O T A T I O N P A R A M E T E R S
452
453 bool ifWholeCircle = (std::abs(dphi-wholeCircle) < perMillion) ? true : false;
454 double delPhi = ifWholeCircle ? wholeCircle : dphi;
455 int nSphi = (nstep > 0) ?
456 nstep : int(delPhi*GetNumberOfRotationSteps()/wholeCircle+.5);
457 if (nSphi == 0) nSphi = 1;
458 int nVphi = ifWholeCircle ? nSphi : nSphi+1;
459 bool ifClosed = np1 > 0 ? false : true;
460
461 // C O U N T V E R T E C E S
462
463 int absNp1 = std::abs(np1);
464 int absNp2 = std::abs(np2);
465 int i1beg = 0;
466 int i1end = absNp1-1;
467 int i2beg = absNp1;
468 int i2end = absNp1+absNp2-1;
469 int i, j, k;
470
471 for(i=i1beg; i<=i2end; i++) {
472 if (std::abs(r[i]) < perMillion) r[i] = 0.;
473 }
474
475 j = 0; // external nodes
476 for (i=i1beg; i<=i1end; i++) {
477 j += (r[i] == 0.) ? 1 : nVphi;
478 }
479
480 bool ifSide1 = false; // internal nodes
481 bool ifSide2 = false;
482
483 if (r[i2beg] != r[i1beg] || z[i2beg] != z[i1beg]) {
484 j += (r[i2beg] == 0.) ? 1 : nVphi;
485 ifSide1 = true;
486 }
487
488 for(i=i2beg+1; i<i2end; i++) {
489 j += (r[i] == 0.) ? 1 : nVphi;
490 }
491
492 if (r[i2end] != r[i1end] || z[i2end] != z[i1end]) {
493 if (absNp2 > 1) j += (r[i2end] == 0.) ? 1 : nVphi;
494 ifSide2 = true;
495 }
496
497 // C O U N T F A C E S
498
499 k = ifClosed ? absNp1*nSphi : (absNp1-1)*nSphi; // external faces
500
501 if (absNp2 > 1) { // internal faces
502 for(i=i2beg; i<i2end; i++) {
503 if (r[i] > 0. || r[i+1] > 0.) k += nSphi;
504 }
505
506 if (ifClosed) {
507 if (r[i2end] > 0. || r[i2beg] > 0.) k += nSphi;
508 }
509 }
510
511 if (!ifClosed) { // side faces
512 if (ifSide1 && (r[i1beg] > 0. || r[i2beg] > 0.)) k += nSphi;
513 if (ifSide2 && (r[i1end] > 0. || r[i2end] > 0.)) k += nSphi;
514 }
515
516 if (!ifWholeCircle) { // phi_side faces
517 k += ifClosed ? 2*absNp1 : 2*(absNp1-1);
518 }
519
520 // A L L O C A T E M E M O R Y
521
522 AllocateMemory(j, k);
523
524 // G E N E R A T E V E R T E C E S
525
526 int *kk;
527 kk = new int[absNp1+absNp2];
528
529 k = 1;
530 for(i=i1beg; i<=i1end; i++) {
531 kk[i] = k;
532 if (r[i] == 0.)
533 { pV[k++] = Point3D<double>(0, 0, z[i]); } else { k += nVphi; }
534 }
535
536 i = i2beg;
537 if (ifSide1) {
538 kk[i] = k;
539 if (r[i] == 0.)
540 { pV[k++] = Point3D<double>(0, 0, z[i]); } else { k += nVphi; }
541 }else{
542 kk[i] = kk[i1beg];
543 }
544
545 for(i=i2beg+1; i<i2end; i++) {
546 kk[i] = k;
547 if (r[i] == 0.)
548 { pV[k++] = Point3D<double>(0, 0, z[i]); } else { k += nVphi; }
549 }
550
551 if (absNp2 > 1) {
552 i = i2end;
553 if (ifSide2) {
554 kk[i] = k;
555 if (r[i] == 0.) pV[k] = Point3D<double>(0, 0, z[i]);
556 }else{
557 kk[i] = kk[i1end];
558 }
559 }
560
561 double cosPhi, sinPhi;
562
563 for(j=0; j<nVphi; j++) {
564 cosPhi = std::cos(phi+j*delPhi/nSphi);
565 sinPhi = std::sin(phi+j*delPhi/nSphi);
566 for(i=i1beg; i<=i2end; i++) {
567 if (r[i] != 0.)
568 pV[kk[i]+j] = Point3D<double>(r[i]*cosPhi,r[i]*sinPhi,z[i]);
569 }
570 }
571
572 // G E N E R A T E E X T E R N A L F A C E S
573
574 int v1,v2;
575
576 k = 1;
577 v2 = ifClosed ? nodeVis : 1;
578 for(i=i1beg; i<i1end; i++) {
579 v1 = v2;
580 if (!ifClosed && i == i1end-1) {
581 v2 = 1;
582 }else{
583 v2 = (r[i] == r[i+1] && r[i+1] == r[i+2]) ? -1 : nodeVis;
584 }
585 RotateEdge(kk[i], kk[i+1], r[i], r[i+1], v1, v2,
586 edgeVis, ifWholeCircle, nSphi, k);
587 }
588 if (ifClosed) {
589 RotateEdge(kk[i1end], kk[i1beg], r[i1end],r[i1beg], nodeVis, nodeVis,
590 edgeVis, ifWholeCircle, nSphi, k);
591 }
592
593 // G E N E R A T E I N T E R N A L F A C E S
594
595 if (absNp2 > 1) {
596 v2 = ifClosed ? nodeVis : 1;
597 for(i=i2beg; i<i2end; i++) {
598 v1 = v2;
599 if (!ifClosed && i==i2end-1) {
600 v2 = 1;
601 }else{
602 v2 = (r[i] == r[i+1] && r[i+1] == r[i+2]) ? -1 : nodeVis;
603 }
604 RotateEdge(kk[i+1], kk[i], r[i+1], r[i], v2, v1,
605 edgeVis, ifWholeCircle, nSphi, k);
606 }
607 if (ifClosed) {
608 RotateEdge(kk[i2beg], kk[i2end], r[i2beg], r[i2end], nodeVis, nodeVis,
609 edgeVis, ifWholeCircle, nSphi, k);
610 }
611 }
612
613 // G E N E R A T E S I D E F A C E S
614
615 if (!ifClosed) {
616 if (ifSide1) {
617 RotateEdge(kk[i2beg], kk[i1beg], r[i2beg], r[i1beg], 1, 1,
618 -1, ifWholeCircle, nSphi, k);
619 }
620 if (ifSide2) {
621 RotateEdge(kk[i1end], kk[i2end], r[i1end], r[i2end], 1, 1,
622 -1, ifWholeCircle, nSphi, k);
623 }
624 }
625
626 // G E N E R A T E S I D E F A C E S for the case of incomplete circle
627
628 if (!ifWholeCircle) {
629
630 int ii[4], vv[4];
631
632 if (ifClosed) {
633 for (i=i1beg; i<=i1end; i++) {
634 ii[0] = i;
635 ii[3] = (i == i1end) ? i1beg : i+1;
636 ii[1] = (absNp2 == 1) ? i2beg : ii[0]+absNp1;
637 ii[2] = (absNp2 == 1) ? i2beg : ii[3]+absNp1;
638 vv[0] = -1;
639 vv[1] = 1;
640 vv[2] = -1;
641 vv[3] = 1;
642 SetSideFacets(ii, vv, kk, r, dphi, nSphi, k);
643 }
644 }else{
645 for (i=i1beg; i<i1end; i++) {
646 ii[0] = i;
647 ii[3] = i+1;
648 ii[1] = (absNp2 == 1) ? i2beg : ii[0]+absNp1;
649 ii[2] = (absNp2 == 1) ? i2beg : ii[3]+absNp1;
650 vv[0] = (i == i1beg) ? 1 : -1;
651 vv[1] = 1;
652 vv[2] = (i == i1end-1) ? 1 : -1;
653 vv[3] = 1;
654 SetSideFacets(ii, vv, kk, r, dphi, nSphi, k);
655 }
656 }
657 }
658
659 delete [] kk;
660
661 if (k-1 != nface) {
662 std::cerr
663 << "Polyhedron::RotateAroundZ: number of generated faces ("
664 << k-1 << ") is not equal to the number of allocated faces ("
665 << nface << ")"
666 << std::endl;
667 }
668}
669
670void HepPolyhedron::SetReferences()
671/***********************************************************************
672 * *
673 * Name: HepPolyhedron::SetReferences Date: 04.12.96 *
674 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
675 * *
676 * Function: For each edge set reference to neighbouring facet *
677 * *
678 ***********************************************************************/
679{
680 if (nface <= 0) return;
681
682 struct edgeListMember {
683 edgeListMember *next;
684 int v2;
685 int iface;
686 int iedge;
687 } *edgeList, *freeList, **headList;
688
689
690 // A L L O C A T E A N D I N I T I A T E L I S T S
691
692 edgeList = new edgeListMember[2*nface];
693 headList = new edgeListMember*[nvert];
694
695 int i;
696 for (i=0; i<nvert; i++) {
697 headList[i] = 0;
698 }
699 freeList = edgeList;
700 for (i=0; i<2*nface-1; i++) {
701 edgeList[i].next = &edgeList[i+1];
702 }
703 edgeList[2*nface-1].next = 0;
704
705 // L O O P A L O N G E D G E S
706
707 int iface, iedge, nedge, i1, i2, k1, k2;
708 edgeListMember *prev, *cur;
709
710 for(iface=1; iface<=nface; iface++) {
711 nedge = (pF[iface].edge[3].v == 0) ? 3 : 4;
712 for (iedge=0; iedge<nedge; iedge++) {
713 i1 = iedge;
714 i2 = (iedge < nedge-1) ? iedge+1 : 0;
715 i1 = std::abs(pF[iface].edge[i1].v);
716 i2 = std::abs(pF[iface].edge[i2].v);
717 k1 = (i1 < i2) ? i1 : i2; // k1 = ::min(i1,i2);
718 k2 = (i1 > i2) ? i1 : i2; // k2 = ::max(i1,i2);
719
720 // check head of the List corresponding to k1
721 cur = headList[k1];
722 if (cur == 0) {
723 headList[k1] = freeList;
724 freeList = freeList->next;
725 cur = headList[k1];
726 cur->next = 0;
727 cur->v2 = k2;
728 cur->iface = iface;
729 cur->iedge = iedge;
730 continue;
731 }
732
733 if (cur->v2 == k2) {
734 headList[k1] = cur->next;
735 cur->next = freeList;
736 freeList = cur;
737 pF[iface].edge[iedge].f = cur->iface;
738 pF[cur->iface].edge[cur->iedge].f = iface;
739 i1 = (pF[iface].edge[iedge].v < 0) ? -1 : 1;
740 i2 = (pF[cur->iface].edge[cur->iedge].v < 0) ? -1 : 1;
741 if (i1 != i2) {
742 std::cerr
743 << "Polyhedron::SetReferences: different edge visibility "
744 << iface << "/" << iedge << "/"
745 << pF[iface].edge[iedge].v << " and "
746 << cur->iface << "/" << cur->iedge << "/"
747 << pF[cur->iface].edge[cur->iedge].v
748 << std::endl;
749 }
750 continue;
751 }
752
753 // check List itself
754 for (;;) {
755 prev = cur;
756 cur = prev->next;
757 if (cur == 0) {
758 prev->next = freeList;
759 freeList = freeList->next;
760 cur = prev->next;
761 cur->next = 0;
762 cur->v2 = k2;
763 cur->iface = iface;
764 cur->iedge = iedge;
765 break;
766 }
767
768 if (cur->v2 == k2) {
769 prev->next = cur->next;
770 cur->next = freeList;
771 freeList = cur;
772 pF[iface].edge[iedge].f = cur->iface;
773 pF[cur->iface].edge[cur->iedge].f = iface;
774 i1 = (pF[iface].edge[iedge].v < 0) ? -1 : 1;
775 i2 = (pF[cur->iface].edge[cur->iedge].v < 0) ? -1 : 1;
776 if (i1 != i2) {
777 std::cerr
778 << "Polyhedron::SetReferences: different edge visibility "
779 << iface << "/" << iedge << "/"
780 << pF[iface].edge[iedge].v << " and "
781 << cur->iface << "/" << cur->iedge << "/"
782 << pF[cur->iface].edge[cur->iedge].v
783 << std::endl;
784 }
785 break;
786 }
787 }
788 }
789 }
790
791 // C H E C K T H A T A L L L I S T S A R E E M P T Y
792
793 for (i=0; i<nvert; i++) {
794 if (headList[i] != 0) {
795 std::cerr
796 << "Polyhedron::SetReferences: List " << i << " is not empty"
797 << std::endl;
798 }
799 }
800
801 // F R E E M E M O R Y
802
803 delete [] edgeList;
804 delete [] headList;
805}
806
807void HepPolyhedron::InvertFacets()
808/***********************************************************************
809 * *
810 * Name: HepPolyhedron::InvertFacets Date: 01.12.99 *
811 * Author: E.Chernyaev Revised: *
812 * *
813 * Function: Invert the order of the nodes in the facets *
814 * *
815 ***********************************************************************/
816{
817 if (nface <= 0) return;
818 int i, k, nnode, v[4],f[4];
819 for (i=1; i<=nface; i++) {
820 nnode = (pF[i].edge[3].v == 0) ? 3 : 4;
821 for (k=0; k<nnode; k++) {
822 v[k] = (k+1 == nnode) ? pF[i].edge[0].v : pF[i].edge[k+1].v;
823 if (v[k] * pF[i].edge[k].v < 0) v[k] = -v[k];
824 f[k] = pF[i].edge[k].f;
825 }
826 for (k=0; k<nnode; k++) {
827 pF[i].edge[nnode-1-k].v = v[k];
828 pF[i].edge[nnode-1-k].f = f[k];
829 }
830 }
831}
832
833HepPolyhedron & HepPolyhedron::Transform(const Transform3D &t)
834/***********************************************************************
835 * *
836 * Name: HepPolyhedron::Transform Date: 01.12.99 *
837 * Author: E.Chernyaev Revised: *
838 * *
839 * Function: Make transformation of the polyhedron *
840 * *
841 ***********************************************************************/
842{
843 if (nvert > 0) {
844 for (int i=1; i<=nvert; i++) { pV[i] = t * pV[i]; }
845
846 // C H E C K D E T E R M I N A N T A N D
847 // I N V E R T F A C E T S I F I T I S N E G A T I V E
848
849 Vector3D<double> d = t * Vector3D<double>(0,0,0);
850 Vector3D<double> x = t * Vector3D<double>(1,0,0) - d;
851 Vector3D<double> y = t * Vector3D<double>(0,1,0) - d;
852 Vector3D<double> z = t * Vector3D<double>(0,0,1) - d;
853 if ((x.cross(y))*z < 0) InvertFacets();
854 }
855 return *this;
856}
857
858bool HepPolyhedron::GetNextVertexIndex(int &index, int &edgeFlag) const
859/***********************************************************************
860 * *
861 * Name: HepPolyhedron::GetNextVertexIndex Date: 03.09.96 *
862 * Author: Yasuhide Sawada Revised: *
863 * *
864 * Function: *
865 * *
866 ***********************************************************************/
867{
868 static int iFace = 1;
869 static int iQVertex = 0;
870 int vIndex = pF[iFace].edge[iQVertex].v;
871
872 edgeFlag = (vIndex > 0) ? 1 : 0;
873 index = std::abs(vIndex);
874
875 if (iQVertex >= 3 || pF[iFace].edge[iQVertex+1].v == 0) {
876 iQVertex = 0;
877 if (++iFace > nface) iFace = 1;
878 return false; // Last Edge
879 }else{
880 ++iQVertex;
881 return true; // not Last Edge
882 }
883}
884
885Point3D<double> HepPolyhedron::GetVertex(int index) const
886/***********************************************************************
887 * *
888 * Name: HepPolyhedron::GetVertex Date: 03.09.96 *
889 * Author: Yasuhide Sawada Revised: 17.11.99 *
890 * *
891 * Function: Get vertex of the index. *
892 * *
893 ***********************************************************************/
894{
895 if (index <= 0 || index > nvert) {
896 std::cerr
897 << "HepPolyhedron::GetVertex: irrelevant index " << index
898 << std::endl;
899 return Point3D<double>();
900 }
901 return pV[index];
902}
903
904bool
905HepPolyhedron::GetNextVertex(Point3D<double> &vertex, int &edgeFlag) const
906/***********************************************************************
907 * *
908 * Name: HepPolyhedron::GetNextVertex Date: 22.07.96 *
909 * Author: John Allison Revised: *
910 * *
911 * Function: Get vertices of the quadrilaterals in order for each *
912 * face in face order. Returns false when finished each *
913 * face. *
914 * *
915 ***********************************************************************/
916{
917 int index;
918 bool rep = GetNextVertexIndex(index, edgeFlag);
919 vertex = pV[index];
920 return rep;
921}
922
923bool HepPolyhedron::GetNextVertex(Point3D<double> &vertex, int &edgeFlag,
924 Normal3D<double> &normal) const
925/***********************************************************************
926 * *
927 * Name: HepPolyhedron::GetNextVertex Date: 26.11.99 *
928 * Author: E.Chernyaev Revised: *
929 * *
930 * Function: Get vertices with normals of the quadrilaterals in order *
931 * for each face in face order. *
932 * Returns false when finished each face. *
933 * *
934 ***********************************************************************/
935{
936 static int iFace = 1;
937 static int iNode = 0;
938
939 if (nface == 0) return false; // empty polyhedron
940
941 int k = pF[iFace].edge[iNode].v;
942 if (k > 0) { edgeFlag = 1; } else { edgeFlag = -1; k = -k; }
943 vertex = pV[k];
944 normal = FindNodeNormal(iFace,k);
945 if (iNode >= 3 || pF[iFace].edge[iNode+1].v == 0) {
946 iNode = 0;
947 if (++iFace > nface) iFace = 1;
948 return false; // last node
949 }else{
950 ++iNode;
951 return true; // not last node
952 }
953}
954
955bool HepPolyhedron::GetNextEdgeIndeces(int &i1, int &i2, int &edgeFlag,
956 int &iface1, int &iface2) const
957/***********************************************************************
958 * *
959 * Name: HepPolyhedron::GetNextEdgeIndeces Date: 30.09.96 *
960 * Author: E.Chernyaev Revised: 17.11.99 *
961 * *
962 * Function: Get indeces of the next edge together with indeces of *
963 * of the faces which share the edge. *
964 * Returns false when the last edge. *
965 * *
966 ***********************************************************************/
967{
968 static int iFace = 1;
969 static int iQVertex = 0;
970 static int iOrder = 1;
971 int k1, k2, kflag, kface1, kface2;
972
973 if (iFace == 1 && iQVertex == 0) {
974 k2 = pF[nface].edge[0].v;
975 k1 = pF[nface].edge[3].v;
976 if (k1 == 0) k1 = pF[nface].edge[2].v;
977 if (std::abs(k1) > std::abs(k2)) iOrder = -1;
978 }
979
980 do {
981 k1 = pF[iFace].edge[iQVertex].v;
982 kflag = k1;
983 k1 = std::abs(k1);
984 kface1 = iFace;
985 kface2 = pF[iFace].edge[iQVertex].f;
986 if (iQVertex >= 3 || pF[iFace].edge[iQVertex+1].v == 0) {
987 iQVertex = 0;
988 k2 = std::abs(pF[iFace].edge[iQVertex].v);
989 iFace++;
990 }else{
991 iQVertex++;
992 k2 = std::abs(pF[iFace].edge[iQVertex].v);
993 }
994 } while (iOrder*k1 > iOrder*k2);
995
996 i1 = k1; i2 = k2; edgeFlag = (kflag > 0) ? 1 : 0;
997 iface1 = kface1; iface2 = kface2;
998
999 if (iFace > nface) {
1000 iFace = 1; iOrder = 1;
1001 return false;
1002 }else{
1003 return true;
1004 }
1005}
1006
1007bool
1008HepPolyhedron::GetNextEdgeIndeces(int &i1, int &i2, int &edgeFlag) const
1009/***********************************************************************
1010 * *
1011 * Name: HepPolyhedron::GetNextEdgeIndeces Date: 17.11.99 *
1012 * Author: E.Chernyaev Revised: *
1013 * *
1014 * Function: Get indeces of the next edge. *
1015 * Returns false when the last edge. *
1016 * *
1017 ***********************************************************************/
1018{
1019 int kface1, kface2;
1020 return GetNextEdgeIndeces(i1, i2, edgeFlag, kface1, kface2);
1021}
1022
1023bool
1024HepPolyhedron::GetNextEdge(Point3D<double> &p1,
1025 Point3D<double> &p2,
1026 int &edgeFlag) const
1027/***********************************************************************
1028 * *
1029 * Name: HepPolyhedron::GetNextEdge Date: 30.09.96 *
1030 * Author: E.Chernyaev Revised: *
1031 * *
1032 * Function: Get next edge. *
1033 * Returns false when the last edge. *
1034 * *
1035 ***********************************************************************/
1036{
1037 int i1,i2;
1038 bool rep = GetNextEdgeIndeces(i1,i2,edgeFlag);
1039 p1 = pV[i1];
1040 p2 = pV[i2];
1041 return rep;
1042}
1043
1044bool
1045HepPolyhedron::GetNextEdge(Point3D<double> &p1, Point3D<double> &p2,
1046 int &edgeFlag, int &iface1, int &iface2) const
1047/***********************************************************************
1048 * *
1049 * Name: HepPolyhedron::GetNextEdge Date: 17.11.99 *
1050 * Author: E.Chernyaev Revised: *
1051 * *
1052 * Function: Get next edge with indeces of the faces which share *
1053 * the edge. *
1054 * Returns false when the last edge. *
1055 * *
1056 ***********************************************************************/
1057{
1058 int i1,i2;
1059 bool rep = GetNextEdgeIndeces(i1,i2,edgeFlag,iface1,iface2);
1060 p1 = pV[i1];
1061 p2 = pV[i2];
1062 return rep;
1063}
1064
1065void HepPolyhedron::GetFacet(int iFace, int &n, int *iNodes,
1066 int *edgeFlags, int *iFaces) const
1067/***********************************************************************
1068 * *
1069 * Name: HepPolyhedron::GetFacet Date: 15.12.99 *
1070 * Author: E.Chernyaev Revised: *
1071 * *
1072 * Function: Get face by index *
1073 * *
1074 ***********************************************************************/
1075{
1076 if (iFace < 1 || iFace > nface) {
1077 std::cerr
1078 << "HepPolyhedron::GetFacet: irrelevant index " << iFace
1079 << std::endl;
1080 n = 0;
1081 }else{
1082 int i, k;
1083 for (i=0; i<4; i++) {
1084 k = pF[iFace].edge[i].v;
1085 if (k == 0) break;
1086 if (iFaces != 0) iFaces[i] = pF[iFace].edge[i].f;
1087 if (k > 0) {
1088 iNodes[i] = k;
1089 if (edgeFlags != 0) edgeFlags[i] = 1;
1090 }else{
1091 iNodes[i] = -k;
1092 if (edgeFlags != 0) edgeFlags[i] = -1;
1093 }
1094 }
1095 n = i;
1096 }
1097}
1098
1099void HepPolyhedron::GetFacet(int index, int &n, Point3D<double> *nodes,
1100 int *edgeFlags, Normal3D<double> *normals) const
1101/***********************************************************************
1102 * *
1103 * Name: HepPolyhedron::GetFacet Date: 17.11.99 *
1104 * Author: E.Chernyaev Revised: *
1105 * *
1106 * Function: Get face by index *
1107 * *
1108 ***********************************************************************/
1109{
1110 int iNodes[4];
1111 GetFacet(index, n, iNodes, edgeFlags);
1112 if (n != 0) {
1113 for (int i=0; i<n; i++) {
1114 nodes[i] = pV[iNodes[i]];
1115 if (normals != 0) normals[i] = FindNodeNormal(index,iNodes[i]);
1116 }
1117 }
1118}
1119
1120bool
1121HepPolyhedron::GetNextFacet(int &n, Point3D<double> *nodes,
1122 int *edgeFlags, Normal3D<double> *normals) const
1123/***********************************************************************
1124 * *
1125 * Name: HepPolyhedron::GetNextFacet Date: 19.11.99 *
1126 * Author: E.Chernyaev Revised: *
1127 * *
1128 * Function: Get next face with normals of unit length at the nodes. *
1129 * Returns false when finished all faces. *
1130 * *
1131 ***********************************************************************/
1132{
1133 static int iFace = 1;
1134
1135 if (edgeFlags == 0) {
1136 GetFacet(iFace, n, nodes);
1137 }else if (normals == 0) {
1138 GetFacet(iFace, n, nodes, edgeFlags);
1139 }else{
1140 GetFacet(iFace, n, nodes, edgeFlags, normals);
1141 }
1142
1143 if (++iFace > nface) {
1144 iFace = 1;
1145 return false;
1146 }else{
1147 return true;
1148 }
1149}
1150
1151Normal3D<double> HepPolyhedron::GetNormal(int iFace) const
1152/***********************************************************************
1153 * *
1154 * Name: HepPolyhedron::GetNormal Date: 19.11.99 *
1155 * Author: E.Chernyaev Revised: *
1156 * *
1157 * Function: Get normal of the face given by index *
1158 * *
1159 ***********************************************************************/
1160{
1161 if (iFace < 1 || iFace > nface) {
1162 std::cerr
1163 << "HepPolyhedron::GetNormal: irrelevant index " << iFace
1164 << std::endl;
1165 return Normal3D<double>();
1166 }
1167
1168 int i0 = std::abs(pF[iFace].edge[0].v);
1169 int i1 = std::abs(pF[iFace].edge[1].v);
1170 int i2 = std::abs(pF[iFace].edge[2].v);
1171 int i3 = std::abs(pF[iFace].edge[3].v);
1172 if (i3 == 0) i3 = i0;
1173 return (pV[i2] - pV[i0]).cross(pV[i3] - pV[i1]);
1174}
1175
1176Normal3D<double> HepPolyhedron::GetUnitNormal(int iFace) const
1177/***********************************************************************
1178 * *
1179 * Name: HepPolyhedron::GetNormal Date: 19.11.99 *
1180 * Author: E.Chernyaev Revised: *
1181 * *
1182 * Function: Get unit normal of the face given by index *
1183 * *
1184 ***********************************************************************/
1185{
1186 if (iFace < 1 || iFace > nface) {
1187 std::cerr
1188 << "HepPolyhedron::GetUnitNormal: irrelevant index " << iFace
1189 << std::endl;
1190 return Normal3D<double>();
1191 }
1192
1193 int i0 = std::abs(pF[iFace].edge[0].v);
1194 int i1 = std::abs(pF[iFace].edge[1].v);
1195 int i2 = std::abs(pF[iFace].edge[2].v);
1196 int i3 = std::abs(pF[iFace].edge[3].v);
1197 if (i3 == 0) i3 = i0;
1198 return ((pV[i2] - pV[i0]).cross(pV[i3] - pV[i1])).unit();
1199}
1200
1201bool HepPolyhedron::GetNextNormal(Normal3D<double> &normal) const
1202/***********************************************************************
1203 * *
1204 * Name: HepPolyhedron::GetNextNormal Date: 22.07.96 *
1205 * Author: John Allison Revised: 19.11.99 *
1206 * *
1207 * Function: Get normals of each face in face order. Returns false *
1208 * when finished all faces. *
1209 * *
1210 ***********************************************************************/
1211{
1212 static int iFace = 1;
1213 normal = GetNormal(iFace);
1214 if (++iFace > nface) {
1215 iFace = 1;
1216 return false;
1217 }else{
1218 return true;
1219 }
1220}
1221
1222bool HepPolyhedron::GetNextUnitNormal(Normal3D<double> &normal) const
1223/***********************************************************************
1224 * *
1225 * Name: HepPolyhedron::GetNextUnitNormal Date: 16.09.96 *
1226 * Author: E.Chernyaev Revised: *
1227 * *
1228 * Function: Get normals of unit length of each face in face order. *
1229 * Returns false when finished all faces. *
1230 * *
1231 ***********************************************************************/
1232{
1233 bool rep = GetNextNormal(normal);
1234 normal = normal.unit();
1235 return rep;
1236}
1237
1238double HepPolyhedron::GetSurfaceArea() const
1239/***********************************************************************
1240 * *
1241 * Name: HepPolyhedron::GetSurfaceArea Date: 25.05.01 *
1242 * Author: E.Chernyaev Revised: *
1243 * *
1244 * Function: Returns area of the surface of the polyhedron. *
1245 * *
1246 ***********************************************************************/
1247{
1248 double s = 0.;
1249 for (int iFace=1; iFace<=nface; iFace++) {
1250 int i0 = std::abs(pF[iFace].edge[0].v);
1251 int i1 = std::abs(pF[iFace].edge[1].v);
1252 int i2 = std::abs(pF[iFace].edge[2].v);
1253 int i3 = std::abs(pF[iFace].edge[3].v);
1254 if (i3 == 0) i3 = i0;
1255 s += ((pV[i2] - pV[i0]).cross(pV[i3] - pV[i1])).mag();
1256 }
1257 return s/2.;
1258}
1259
1260double HepPolyhedron::GetVolume() const
1261/***********************************************************************
1262 * *
1263 * Name: HepPolyhedron::GetVolume Date: 25.05.01 *
1264 * Author: E.Chernyaev Revised: *
1265 * *
1266 * Function: Returns volume of the polyhedron. *
1267 * *
1268 ***********************************************************************/
1269{
1270 double v = 0.;
1271 for (int iFace=1; iFace<=nface; iFace++) {
1272 int i0 = std::abs(pF[iFace].edge[0].v);
1273 int i1 = std::abs(pF[iFace].edge[1].v);
1274 int i2 = std::abs(pF[iFace].edge[2].v);
1275 int i3 = std::abs(pF[iFace].edge[3].v);
1276 Point3D<double> g;
1277 if (i3 == 0) {
1278 i3 = i0;
1279 g = (pV[i0]+pV[i1]+pV[i2]) * (1./3.);
1280 }else{
1281 g = (pV[i0]+pV[i1]+pV[i2]+pV[i3]) * 0.25;
1282 }
1283 v += ((pV[i2] - pV[i0]).cross(pV[i3] - pV[i1])).dot(g);
1284 }
1285 return v/6.;
1286}
1287
1288int
1289HepPolyhedron::createTwistedTrap(double Dz,
1290 const double xy1[][2],
1291 const double xy2[][2])
1292/***********************************************************************
1293 * *
1294 * Name: createTwistedTrap Date: 05.11.02 *
1295 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
1296 * *
1297 * Function: Creates polyhedron for twisted trapezoid *
1298 * *
1299 * Input: Dz - half-length along Z 8----7 *
1300 * xy1[2,4] - quadrilateral at Z=-Dz 5----6 ! *
1301 * xy2[2,4] - quadrilateral at Z=+Dz ! 4-!--3 *
1302 * 1----2 *
1303 * *
1304 ***********************************************************************/
1305{
1306 AllocateMemory(12,18);
1307
1308 pV[ 1] = Point3D<double>(xy1[0][0],xy1[0][1],-Dz);
1309 pV[ 2] = Point3D<double>(xy1[1][0],xy1[1][1],-Dz);
1310 pV[ 3] = Point3D<double>(xy1[2][0],xy1[2][1],-Dz);
1311 pV[ 4] = Point3D<double>(xy1[3][0],xy1[3][1],-Dz);
1312
1313 pV[ 5] = Point3D<double>(xy2[0][0],xy2[0][1], Dz);
1314 pV[ 6] = Point3D<double>(xy2[1][0],xy2[1][1], Dz);
1315 pV[ 7] = Point3D<double>(xy2[2][0],xy2[2][1], Dz);
1316 pV[ 8] = Point3D<double>(xy2[3][0],xy2[3][1], Dz);
1317
1318 pV[ 9] = (pV[1]+pV[2]+pV[5]+pV[6])/4.;
1319 pV[10] = (pV[2]+pV[3]+pV[6]+pV[7])/4.;
1320 pV[11] = (pV[3]+pV[4]+pV[7]+pV[8])/4.;
1321 pV[12] = (pV[4]+pV[1]+pV[8]+pV[5])/4.;
1322
1323 enum {DUMMY, BOTTOM,
1324 LEFT_BOTTOM, LEFT_FRONT, LEFT_TOP, LEFT_BACK,
1325 BACK_BOTTOM, BACK_LEFT, BACK_TOP, BACK_RIGHT,
1326 RIGHT_BOTTOM, RIGHT_BACK, RIGHT_TOP, RIGHT_FRONT,
1327 FRONT_BOTTOM, FRONT_RIGHT, FRONT_TOP, FRONT_LEFT,
1328 TOP};
1329
1330 pF[ 1]=G4Facet(1,LEFT_BOTTOM, 4,BACK_BOTTOM, 3,RIGHT_BOTTOM, 2,FRONT_BOTTOM);
1331
1332 pF[ 2]=G4Facet(4,BOTTOM, -1,LEFT_FRONT, -12,LEFT_BACK, 0,0);
1333 pF[ 3]=G4Facet(1,FRONT_LEFT, -5,LEFT_TOP, -12,LEFT_BOTTOM, 0,0);
1334 pF[ 4]=G4Facet(5,TOP, -8,LEFT_BACK, -12,LEFT_FRONT, 0,0);
1335 pF[ 5]=G4Facet(8,BACK_LEFT, -4,LEFT_BOTTOM, -12,LEFT_TOP, 0,0);
1336
1337 pF[ 6]=G4Facet(3,BOTTOM, -4,BACK_LEFT, -11,BACK_RIGHT, 0,0);
1338 pF[ 7]=G4Facet(4,LEFT_BACK, -8,BACK_TOP, -11,BACK_BOTTOM, 0,0);
1339 pF[ 8]=G4Facet(8,TOP, -7,BACK_RIGHT, -11,BACK_LEFT, 0,0);
1340 pF[ 9]=G4Facet(7,RIGHT_BACK, -3,BACK_BOTTOM, -11,BACK_TOP, 0,0);
1341
1342 pF[10]=G4Facet(2,BOTTOM, -3,RIGHT_BACK, -10,RIGHT_FRONT, 0,0);
1343 pF[11]=G4Facet(3,BACK_RIGHT, -7,RIGHT_TOP, -10,RIGHT_BOTTOM, 0,0);
1344 pF[12]=G4Facet(7,TOP, -6,RIGHT_FRONT, -10,RIGHT_BACK, 0,0);
1345 pF[13]=G4Facet(6,FRONT_RIGHT,-2,RIGHT_BOTTOM,-10,RIGHT_TOP, 0,0);
1346
1347 pF[14]=G4Facet(1,BOTTOM, -2,FRONT_RIGHT, -9,FRONT_LEFT, 0,0);
1348 pF[15]=G4Facet(2,RIGHT_FRONT,-6,FRONT_TOP, -9,FRONT_BOTTOM, 0,0);
1349 pF[16]=G4Facet(6,TOP, -5,FRONT_LEFT, -9,FRONT_RIGHT, 0,0);
1350 pF[17]=G4Facet(5,LEFT_FRONT, -1,FRONT_BOTTOM, -9,FRONT_TOP, 0,0);
1351
1352 pF[18]=G4Facet(5,FRONT_TOP, 6,RIGHT_TOP, 7,BACK_TOP, 8,LEFT_TOP);
1353
1354 return 0;
1355}
1356
1357int
1358HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
1359 const double xyz[][3],
1360 const int faces[][4])
1361/***********************************************************************
1362 * *
1363 * Name: createPolyhedron Date: 05.11.02 *
1364 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
1365 * *
1366 * Function: Creates user defined polyhedron *
1367 * *
1368 * Input: Nnodes - number of nodes *
1369 * Nfaces - number of faces *
1370 * nodes[][3] - node coordinates *
1371 * faces[][4] - faces *
1372 * *
1373 ***********************************************************************/
1374{
1375 AllocateMemory(Nnodes, Nfaces);
1376 if (nvert == 0) return 1;
1377
1378 for (int i=0; i<Nnodes; i++) {
1379 pV[i+1] = Point3D<double>(xyz[i][0], xyz[i][1], xyz[i][2]);
1380 }
1381 for (int k=0; k<Nfaces; k++) {
1382 pF[k+1] = G4Facet(faces[k][0],0,faces[k][1],0,faces[k][2],0,faces[k][3],0);
1383 }
1384 SetReferences();
1385 return 0;
1386}
1387
1388HepPolyhedronTrd2::HepPolyhedronTrd2(double Dx1, double Dx2,
1389 double Dy1, double Dy2,
1390 double Dz)
1391/***********************************************************************
1392 * *
1393 * Name: HepPolyhedronTrd2 Date: 22.07.96 *
1394 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
1395 * *
1396 * Function: Create GEANT4 TRD2-trapezoid *
1397 * *
1398 * Input: Dx1 - half-length along X at -Dz 8----7 *
1399 * Dx2 - half-length along X ay +Dz 5----6 ! *
1400 * Dy1 - half-length along Y ay -Dz ! 4-!--3 *
1401 * Dy2 - half-length along Y ay +Dz 1----2 *
1402 * Dz - half-length along Z *
1403 * *
1404 ***********************************************************************/
1405{
1406 AllocateMemory(8,6);
1407
1408 pV[1] = Point3D<double>(-Dx1,-Dy1,-Dz);
1409 pV[2] = Point3D<double>( Dx1,-Dy1,-Dz);
1410 pV[3] = Point3D<double>( Dx1, Dy1,-Dz);
1411 pV[4] = Point3D<double>(-Dx1, Dy1,-Dz);
1412 pV[5] = Point3D<double>(-Dx2,-Dy2, Dz);
1413 pV[6] = Point3D<double>( Dx2,-Dy2, Dz);
1414 pV[7] = Point3D<double>( Dx2, Dy2, Dz);
1415 pV[8] = Point3D<double>(-Dx2, Dy2, Dz);
1416
1417 CreatePrism();
1418}
1419
1420HepPolyhedronTrd2::~HepPolyhedronTrd2() {}
1421
1422HepPolyhedronTrd1::HepPolyhedronTrd1(double Dx1, double Dx2,
1423 double Dy, double Dz)
1424 : HepPolyhedronTrd2(Dx1, Dx2, Dy, Dy, Dz) {}
1425
1426HepPolyhedronTrd1::~HepPolyhedronTrd1() {}
1427
1428HepPolyhedronBox::HepPolyhedronBox(double Dx, double Dy, double Dz)
1429 : HepPolyhedronTrd2(Dx, Dx, Dy, Dy, Dz) {}
1430
1431HepPolyhedronBox::~HepPolyhedronBox() {}
1432
1433HepPolyhedronTrap::HepPolyhedronTrap(double Dz,
1434 double Theta,
1435 double Phi,
1436 double Dy1,
1437 double Dx1,
1438 double Dx2,
1439 double Alp1,
1440 double Dy2,
1441 double Dx3,
1442 double Dx4,
1443 double Alp2)
1444/***********************************************************************
1445 * *
1446 * Name: HepPolyhedronTrap Date: 20.11.96 *
1447 * Author: E.Chernyaev Revised: *
1448 * *
1449 * Function: Create GEANT4 TRAP-trapezoid *
1450 * *
1451 * Input: DZ - half-length in Z *
1452 * Theta,Phi - polar angles of the line joining centres of the *
1453 * faces at Z=-Dz and Z=+Dz *
1454 * Dy1 - half-length in Y of the face at Z=-Dz *
1455 * Dx1 - half-length in X of low edge of the face at Z=-Dz *
1456 * Dx2 - half-length in X of top edge of the face at Z=-Dz *
1457 * Alp1 - angle between Y-axis and the median joining top and *
1458 * low edges of the face at Z=-Dz *
1459 * Dy2 - half-length in Y of the face at Z=+Dz *
1460 * Dx3 - half-length in X of low edge of the face at Z=+Dz *
1461 * Dx4 - half-length in X of top edge of the face at Z=+Dz *
1462 * Alp2 - angle between Y-axis and the median joining top and *
1463 * low edges of the face at Z=+Dz *
1464 * *
1465 ***********************************************************************/
1466{
1467 double DzTthetaCphi = Dz*std::tan(Theta)*std::cos(Phi);
1468 double DzTthetaSphi = Dz*std::tan(Theta)*std::sin(Phi);
1469 double Dy1Talp1 = Dy1*std::tan(Alp1);
1470 double Dy2Talp2 = Dy2*std::tan(Alp2);
1471
1472 AllocateMemory(8,6);
1473
1474 pV[1] = Point3D<double>(-DzTthetaCphi-Dy1Talp1-Dx1,-DzTthetaSphi-Dy1,-Dz);
1475 pV[2] = Point3D<double>(-DzTthetaCphi-Dy1Talp1+Dx1,-DzTthetaSphi-Dy1,-Dz);
1476 pV[3] = Point3D<double>(-DzTthetaCphi+Dy1Talp1+Dx2,-DzTthetaSphi+Dy1,-Dz);
1477 pV[4] = Point3D<double>(-DzTthetaCphi+Dy1Talp1-Dx2,-DzTthetaSphi+Dy1,-Dz);
1478 pV[5] = Point3D<double>( DzTthetaCphi-Dy2Talp2-Dx3, DzTthetaSphi-Dy2, Dz);
1479 pV[6] = Point3D<double>( DzTthetaCphi-Dy2Talp2+Dx3, DzTthetaSphi-Dy2, Dz);
1480 pV[7] = Point3D<double>( DzTthetaCphi+Dy2Talp2+Dx4, DzTthetaSphi+Dy2, Dz);
1481 pV[8] = Point3D<double>( DzTthetaCphi+Dy2Talp2-Dx4, DzTthetaSphi+Dy2, Dz);
1482
1483 CreatePrism();
1484}
1485
1486HepPolyhedronTrap::~HepPolyhedronTrap() {}
1487
1488HepPolyhedronPara::HepPolyhedronPara(double Dx, double Dy, double Dz,
1489 double Alpha, double Theta,
1490 double Phi)
1491 : HepPolyhedronTrap(Dz, Theta, Phi, Dy, Dx, Dx, Alpha, Dy, Dx, Dx, Alpha) {}
1492
1493HepPolyhedronPara::~HepPolyhedronPara() {}
1494
1495HepPolyhedronParaboloid::HepPolyhedronParaboloid(double r1,
1496 double r2,
1497 double dz,
1498 double sPhi,
1499 double dPhi)
1500/***********************************************************************
1501 * *
1502 * Name: HepPolyhedronParaboloid Date: 28.06.07 *
1503 * Author: L.Lindroos, T.Nikitina (CERN), July 2007 Revised: 28.06.07 *
1504 * *
1505 * Function: Constructor for paraboloid *
1506 * *
1507 * Input: r1 - inside and outside radiuses at -Dz *
1508 * r2 - inside and outside radiuses at +Dz *
1509 * dz - half length in Z *
1510 * sPhi - starting angle of the segment *
1511 * dPhi - segment range *
1512 * *
1513 ***********************************************************************/
1514{
1515 static double wholeCircle=twopi;
1516
1517 // C H E C K I N P U T P A R A M E T E R S
1518
1519 int k = 0;
1520 if (r1 < 0. || r2 <= 0.) k = 1;
1521
1522 if (dz <= 0.) k += 2;
1523
1524 double phi1, phi2, dphi;
1525
1526 if(dPhi < 0.)
1527 {
1528 phi2 = sPhi; phi1 = phi2 + dPhi;
1529 }
1530 else if(dPhi == 0.)
1531 {
1532 phi1 = sPhi; phi2 = phi1 + wholeCircle;
1533 }
1534 else
1535 {
1536 phi1 = sPhi; phi2 = phi1 + dPhi;
1537 }
1538 dphi = phi2 - phi1;
1539
1540 if (std::abs(dphi-wholeCircle) < perMillion) dphi = wholeCircle;
1541 if (dphi > wholeCircle) k += 4;
1542
1543 if (k != 0) {
1544 std::cerr << "HepPolyhedronParaboloid: error in input parameters";
1545 if ((k & 1) != 0) std::cerr << " (radiuses)";
1546 if ((k & 2) != 0) std::cerr << " (half-length)";
1547 if ((k & 4) != 0) std::cerr << " (angles)";
1548 std::cerr << std::endl;
1549 std::cerr << " r1=" << r1;
1550 std::cerr << " r2=" << r2;
1551 std::cerr << " dz=" << dz << " sPhi=" << sPhi << " dPhi=" << dPhi
1552 << std::endl;
1553 return;
1554 }
1555
1556 // P R E P A R E T W O P O L Y L I N E S
1557
1558 int n = GetNumberOfRotationSteps();
1559 double dl = (r2 - r1) / n;
1560 double k1 = (r2*r2 - r1*r1) / 2 / dz;
1561 double k2 = (r2*r2 + r1*r1) / 2;
1562
1563 double *zz = new double[n + 2], *rr = new double[n + 2];
1564
1565 zz[0] = dz;
1566 rr[0] = r2;
1567
1568 for(int i = 1; i < n - 1; i++)
1569 {
1570 rr[i] = rr[i-1] - dl;
1571 zz[i] = (rr[i]*rr[i] - k2) / k1;
1572 if(rr[i] < 0)
1573 {
1574 rr[i] = 0;
1575 zz[i] = 0;
1576 }
1577 }
1578
1579 zz[n-1] = -dz;
1580 rr[n-1] = r1;
1581
1582 zz[n] = dz;
1583 rr[n] = 0;
1584
1585 zz[n+1] = -dz;
1586 rr[n+1] = 0;
1587
1588 // R O T A T E P O L Y L I N E S
1589
1590 RotateAroundZ(0, phi1, dphi, n, 2, zz, rr, -1, -1);
1591 SetReferences();
1592
1593 delete zz;
1594 delete rr;
1595}
1596
1597HepPolyhedronParaboloid::~HepPolyhedronParaboloid() {}
1598
1599HepPolyhedronHype::HepPolyhedronHype(double r1,
1600 double r2,
1601 double sqrtan1,
1602 double sqrtan2,
1603 double halfZ)
1604/***********************************************************************
1605 * *
1606 * Name: HepPolyhedronHype Date: 14.04.08 *
1607 * Author: Tatiana Nikitina (CERN) Revised: 14.04.08 *
1608 * *
1609 * Function: Constructor for Hype *
1610 * *
1611 * Input: r1 - inside radius at z=0 *
1612 * r2 - outside radiuses at z=0 *
1613 * sqrtan1 - sqr of tan of Inner Stereo Angle *
1614 * sqrtan2 - sqr of tan of Outer Stereo Angle *
1615 * halfZ - half length in Z *
1616 * *
1617 ***********************************************************************/
1618{
1619 static double wholeCircle=twopi;
1620
1621 // C H E C K I N P U T P A R A M E T E R S
1622
1623 int k = 0;
1624 if (r2 < 0. || r1 < 0. ) k = 1;
1625 if (r1 > r2 ) k = 1;
1626 if (r1 == r2) k = 1;
1627
1628 if (halfZ <= 0.) k += 2;
1629
1630 if (sqrtan1<0.||sqrtan2<0.) k += 4;
1631
1632 if (k != 0) {
1633 std::cerr << "HepPolyhedronHype: error in input parameters";
1634 if ((k & 1) != 0) std::cerr << " (radiuses)";
1635 if ((k & 2) != 0) std::cerr << " (half-length)";
1636 if ((k & 4) != 0) std::cerr << " (angles)";
1637 std::cerr << std::endl;
1638 std::cerr << " r1=" << r1 << " r2=" << r2;
1639 std::cerr << " halfZ=" << halfZ << " sqrTan1=" << sqrtan1
1640 << " sqrTan2=" << sqrtan2
1641 << std::endl;
1642 return;
1643 }
1644
1645 // P R E P A R E T W O P O L Y L I N E S
1646
1647 int n = GetNumberOfRotationSteps();
1648 double dz = 2.*halfZ / n;
1649 double k1 = r1*r1;
1650 double k2 = r2*r2;
1651
1652 double *zz = new double[n + n], *rr = new double[n + n];
1653
1654 zz[0] = halfZ;
1655 rr[0] = std::sqrt(sqrtan2*halfZ*halfZ+k2);
1656
1657 for(int i = 1; i < n - 1; i++)
1658 {
1659 zz[i] = zz[i-1] - dz;
1660 rr[i] =std::sqrt(sqrtan2*zz[i]*zz[i]+k2) ;
1661
1662 }
1663
1664 zz[n-1] = -halfZ;
1665 rr[n-1] = rr[0];
1666
1667
1668 zz[n] = halfZ;
1669 rr[n] = std::sqrt(sqrtan1*halfZ*halfZ+k1);
1670 for(int i = n+1; i < n +n; i++)
1671 {
1672 zz[i] = zz[i-1] - dz;
1673 rr[i] =std::sqrt(sqrtan1*zz[i]*zz[i]+k1) ;
1674
1675 }
1676 zz[n+n] = -halfZ;
1677 rr[n+n] = rr[n];
1678
1679 // R O T A T E P O L Y L I N E S
1680
1681 RotateAroundZ(0, 0., wholeCircle, n, n, zz, rr, -1, -1);
1682 SetReferences();
1683}
1684
1685HepPolyhedronHype::~HepPolyhedronHype() {}
1686
1687HepPolyhedronCons::HepPolyhedronCons(double Rmn1,
1688 double Rmx1,
1689 double Rmn2,
1690 double Rmx2,
1691 double Dz,
1692 double Phi1,
1693 double Dphi)
1694/***********************************************************************
1695 * *
1696 * Name: HepPolyhedronCons::HepPolyhedronCons Date: 15.12.96 *
1697 * Author: E.Chernyaev (IHEP/Protvino) Revised: 15.12.96 *
1698 * *
1699 * Function: Constructor for CONS, TUBS, CONE, TUBE *
1700 * *
1701 * Input: Rmn1, Rmx1 - inside and outside radiuses at -Dz *
1702 * Rmn2, Rmx2 - inside and outside radiuses at +Dz *
1703 * Dz - half length in Z *
1704 * Phi1 - starting angle of the segment *
1705 * Dphi - segment range *
1706 * *
1707 ***********************************************************************/
1708{
1709 static double wholeCircle=twopi;
1710
1711 // C H E C K I N P U T P A R A M E T E R S
1712
1713 int k = 0;
1714 if (Rmn1 < 0. || Rmx1 < 0. || Rmn2 < 0. || Rmx2 < 0.) k = 1;
1715 if (Rmn1 > Rmx1 || Rmn2 > Rmx2) k = 1;
1716 if (Rmn1 == Rmx1 && Rmn2 == Rmx2) k = 1;
1717
1718 if (Dz <= 0.) k += 2;
1719
1720 double phi1, phi2, dphi;
1721 if (Dphi < 0.) {
1722 phi2 = Phi1; phi1 = phi2 - Dphi;
1723 }else if (Dphi == 0.) {
1724 phi1 = Phi1; phi2 = phi1 + wholeCircle;
1725 }else{
1726 phi1 = Phi1; phi2 = phi1 + Dphi;
1727 }
1728 dphi = phi2 - phi1;
1729 if (std::abs(dphi-wholeCircle) < perMillion) dphi = wholeCircle;
1730 if (dphi > wholeCircle) k += 4;
1731
1732 if (k != 0) {
1733 std::cerr << "HepPolyhedronCone(s)/Tube(s): error in input parameters";
1734 if ((k & 1) != 0) std::cerr << " (radiuses)";
1735 if ((k & 2) != 0) std::cerr << " (half-length)";
1736 if ((k & 4) != 0) std::cerr << " (angles)";
1737 std::cerr << std::endl;
1738 std::cerr << " Rmn1=" << Rmn1 << " Rmx1=" << Rmx1;
1739 std::cerr << " Rmn2=" << Rmn2 << " Rmx2=" << Rmx2;
1740 std::cerr << " Dz=" << Dz << " Phi1=" << Phi1 << " Dphi=" << Dphi
1741 << std::endl;
1742 return;
1743 }
1744
1745 // P R E P A R E T W O P O L Y L I N E S
1746
1747 double zz[4], rr[4];
1748 zz[0] = Dz;
1749 zz[1] = -Dz;
1750 zz[2] = Dz;
1751 zz[3] = -Dz;
1752 rr[0] = Rmx2;
1753 rr[1] = Rmx1;
1754 rr[2] = Rmn2;
1755 rr[3] = Rmn1;
1756
1757 // R O T A T E P O L Y L I N E S
1758
1759 RotateAroundZ(0, phi1, dphi, 2, 2, zz, rr, -1, -1);
1760 SetReferences();
1761}
1762
1763HepPolyhedronCons::~HepPolyhedronCons() {}
1764
1765HepPolyhedronCone::HepPolyhedronCone(double Rmn1, double Rmx1,
1766 double Rmn2, double Rmx2,
1767 double Dz) :
1768 HepPolyhedronCons(Rmn1, Rmx1, Rmn2, Rmx2, Dz, 0*deg, 360*deg) {}
1769
1770HepPolyhedronCone::~HepPolyhedronCone() {}
1771
1772HepPolyhedronTubs::HepPolyhedronTubs(double Rmin, double Rmax,
1773 double Dz,
1774 double Phi1, double Dphi)
1775 : HepPolyhedronCons(Rmin, Rmax, Rmin, Rmax, Dz, Phi1, Dphi) {}
1776
1777HepPolyhedronTubs::~HepPolyhedronTubs() {}
1778
1779HepPolyhedronTube::HepPolyhedronTube (double Rmin, double Rmax,
1780 double Dz)
1781 : HepPolyhedronCons(Rmin, Rmax, Rmin, Rmax, Dz, 0*deg, 360*deg) {}
1782
1783HepPolyhedronTube::~HepPolyhedronTube () {}
1784
1785HepPolyhedronPgon::HepPolyhedronPgon(double phi,
1786 double dphi,
1787 int npdv,
1788 int nz,
1789 const double *z,
1790 const double *rmin,
1791 const double *rmax)
1792/***********************************************************************
1793 * *
1794 * Name: HepPolyhedronPgon Date: 09.12.96 *
1795 * Author: E.Chernyaev Revised: *
1796 * *
1797 * Function: Constructor of polyhedron for PGON, PCON *
1798 * *
1799 * Input: phi - initial phi *
1800 * dphi - delta phi *
1801 * npdv - number of steps along phi *
1802 * nz - number of z-planes (at least two) *
1803 * z[] - z coordinates of the slices *
1804 * rmin[] - smaller r at the slices *
1805 * rmax[] - bigger r at the slices *
1806 * *
1807 ***********************************************************************/
1808{
1809 // C H E C K I N P U T P A R A M E T E R S
1810
1811 if (dphi <= 0. || dphi > twopi) {
1812 std::cerr
1813 << "HepPolyhedronPgon/Pcon: wrong delta phi = " << dphi
1814 << std::endl;
1815 return;
1816 }
1817
1818 if (nz < 2) {
1819 std::cerr
1820 << "HepPolyhedronPgon/Pcon: number of z-planes less than two = " << nz
1821 << std::endl;
1822 return;
1823 }
1824
1825 if (npdv < 0) {
1826 std::cerr
1827 << "HepPolyhedronPgon/Pcon: error in number of phi-steps =" << npdv
1828 << std::endl;
1829 return;
1830 }
1831
1832 int i;
1833 for (i=0; i<nz; i++) {
1834 if (rmin[i] < 0. || rmax[i] < 0. || rmin[i] > rmax[i]) {
1835 std::cerr
1836 << "HepPolyhedronPgon: error in radiuses rmin[" << i << "]="
1837 << rmin[i] << " rmax[" << i << "]=" << rmax[i]
1838 << std::endl;
1839 return;
1840 }
1841 }
1842
1843 // P R E P A R E T W O P O L Y L I N E S
1844
1845 double *zz, *rr;
1846 zz = new double[2*nz];
1847 rr = new double[2*nz];
1848
1849 if (z[0] > z[nz-1]) {
1850 for (i=0; i<nz; i++) {
1851 zz[i] = z[i];
1852 rr[i] = rmax[i];
1853 zz[i+nz] = z[i];
1854 rr[i+nz] = rmin[i];
1855 }
1856 }else{
1857 for (i=0; i<nz; i++) {
1858 zz[i] = z[nz-i-1];
1859 rr[i] = rmax[nz-i-1];
1860 zz[i+nz] = z[nz-i-1];
1861 rr[i+nz] = rmin[nz-i-1];
1862 }
1863 }
1864
1865 // R O T A T E P O L Y L I N E S
1866
1867 RotateAroundZ(npdv, phi, dphi, nz, nz, zz, rr, -1, (npdv == 0) ? -1 : 1);
1868 SetReferences();
1869
1870 delete [] zz;
1871 delete [] rr;
1872}
1873
1874HepPolyhedronPgon::~HepPolyhedronPgon() {}
1875
1876HepPolyhedronPcon::HepPolyhedronPcon(double phi, double dphi, int nz,
1877 const double *z,
1878 const double *rmin,
1879 const double *rmax)
1880 : HepPolyhedronPgon(phi, dphi, 0, nz, z, rmin, rmax) {}
1881
1882HepPolyhedronPcon::~HepPolyhedronPcon() {}
1883
1884HepPolyhedronSphere::HepPolyhedronSphere(double rmin, double rmax,
1885 double phi, double dphi,
1886 double the, double dthe)
1887/***********************************************************************
1888 * *
1889 * Name: HepPolyhedronSphere Date: 11.12.96 *
1890 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
1891 * *
1892 * Function: Constructor of polyhedron for SPHERE *
1893 * *
1894 * Input: rmin - internal radius *
1895 * rmax - external radius *
1896 * phi - initial phi *
1897 * dphi - delta phi *
1898 * the - initial theta *
1899 * dthe - delta theta *
1900 * *
1901 ***********************************************************************/
1902{
1903 // C H E C K I N P U T P A R A M E T E R S
1904
1905 if (dphi <= 0. || dphi > twopi) {
1906 std::cerr
1907 << "HepPolyhedronSphere: wrong delta phi = " << dphi
1908 << std::endl;
1909 return;
1910 }
1911
1912 if (the < 0. || the > pi) {
1913 std::cerr
1914 << "HepPolyhedronSphere: wrong theta = " << the
1915 << std::endl;
1916 return;
1917 }
1918
1919 if (dthe <= 0. || dthe > pi) {
1920 std::cerr
1921 << "HepPolyhedronSphere: wrong delta theta = " << dthe
1922 << std::endl;
1923 return;
1924 }
1925
1926 if (the+dthe > pi) {
1927 std::cerr
1928 << "HepPolyhedronSphere: wrong theta + delta theta = "
1929 << the << " " << dthe
1930 << std::endl;
1931 return;
1932 }
1933
1934 if (rmin < 0. || rmin >= rmax) {
1935 std::cerr
1936 << "HepPolyhedronSphere: error in radiuses"
1937 << " rmin=" << rmin << " rmax=" << rmax
1938 << std::endl;
1939 return;
1940 }
1941
1942 // P R E P A R E T W O P O L Y L I N E S
1943
1944 int ns = (GetNumberOfRotationSteps() + 1) / 2;
1945 int np1 = int(dthe*ns/pi+.5) + 1;
1946 if (np1 <= 1) np1 = 2;
1947 int np2 = rmin < perMillion ? 1 : np1;
1948
1949 double *zz, *rr;
1950 zz = new double[np1+np2];
1951 rr = new double[np1+np2];
1952
1953 double a = dthe/(np1-1);
1954 double cosa, sina;
1955 for (int i=0; i<np1; i++) {
1956 cosa = std::cos(the+i*a);
1957 sina = std::sin(the+i*a);
1958 zz[i] = rmax*cosa;
1959 rr[i] = rmax*sina;
1960 if (np2 > 1) {
1961 zz[i+np1] = rmin*cosa;
1962 rr[i+np1] = rmin*sina;
1963 }
1964 }
1965 if (np2 == 1) {
1966 zz[np1] = 0.;
1967 rr[np1] = 0.;
1968 }
1969
1970 // R O T A T E P O L Y L I N E S
1971
1972 RotateAroundZ(0, phi, dphi, np1, np2, zz, rr, -1, -1);
1973 SetReferences();
1974
1975 delete [] zz;
1976 delete [] rr;
1977}
1978
1979HepPolyhedronSphere::~HepPolyhedronSphere() {}
1980
1981HepPolyhedronTorus::HepPolyhedronTorus(double rmin,
1982 double rmax,
1983 double rtor,
1984 double phi,
1985 double dphi)
1986/***********************************************************************
1987 * *
1988 * Name: HepPolyhedronTorus Date: 11.12.96 *
1989 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
1990 * *
1991 * Function: Constructor of polyhedron for TORUS *
1992 * *
1993 * Input: rmin - internal radius *
1994 * rmax - external radius *
1995 * rtor - radius of torus *
1996 * phi - initial phi *
1997 * dphi - delta phi *
1998 * *
1999 ***********************************************************************/
2000{
2001 // C H E C K I N P U T P A R A M E T E R S
2002
2003 if (dphi <= 0. || dphi > twopi) {
2004 std::cerr
2005 << "HepPolyhedronTorus: wrong delta phi = " << dphi
2006 << std::endl;
2007 return;
2008 }
2009
2010 if (rmin < 0. || rmin >= rmax || rmax >= rtor) {
2011 std::cerr
2012 << "HepPolyhedronTorus: error in radiuses"
2013 << " rmin=" << rmin << " rmax=" << rmax << " rtorus=" << rtor
2014 << std::endl;
2015 return;
2016 }
2017
2018 // P R E P A R E T W O P O L Y L I N E S
2019
2020 int np1 = GetNumberOfRotationSteps();
2021 int np2 = rmin < perMillion ? 1 : np1;
2022
2023 double *zz, *rr;
2024 zz = new double[np1+np2];
2025 rr = new double[np1+np2];
2026
2027 double a = twopi/np1;
2028 double cosa, sina;
2029 for (int i=0; i<np1; i++) {
2030 cosa = std::cos(i*a);
2031 sina = std::sin(i*a);
2032 zz[i] = rmax*cosa;
2033 rr[i] = rtor+rmax*sina;
2034 if (np2 > 1) {
2035 zz[i+np1] = rmin*cosa;
2036 rr[i+np1] = rtor+rmin*sina;
2037 }
2038 }
2039 if (np2 == 1) {
2040 zz[np1] = 0.;
2041 rr[np1] = rtor;
2042 np2 = -1;
2043 }
2044
2045 // R O T A T E P O L Y L I N E S
2046
2047 RotateAroundZ(0, phi, dphi, -np1, -np2, zz, rr, -1,-1);
2048 SetReferences();
2049
2050 delete [] zz;
2051 delete [] rr;
2052}
2053
2054HepPolyhedronTorus::~HepPolyhedronTorus() {}
2055
2056HepPolyhedronEllipsoid::HepPolyhedronEllipsoid(double ax, double by,
2057 double cz, double zCut1,
2058 double zCut2)
2059/***********************************************************************
2060 * *
2061 * Name: HepPolyhedronEllipsoid Date: 25.02.05 *
2062 * Author: G.Guerrieri Revised: *
2063 * *
2064 * Function: Constructor of polyhedron for ELLIPSOID *
2065 * *
2066 * Input: ax - semiaxis x *
2067 * by - semiaxis y *
2068 * cz - semiaxis z *
2069 * zCut1 - lower cut plane level (solid lies above this plane) *
2070 * zCut2 - upper cut plane level (solid lies below this plane) *
2071 * *
2072 ***********************************************************************/
2073{
2074 // C H E C K I N P U T P A R A M E T E R S
2075
2076 if (zCut1 >= cz || zCut2 <= -cz || zCut1 > zCut2) {
2077 std::cerr << "HepPolyhedronEllipsoid: wrong zCut1 = " << zCut1
2078 << " zCut2 = " << zCut2
2079 << " for given cz = " << cz << std::endl;
2080 return;
2081 }
2082 if (cz <= 0.0) {
2083 std::cerr << "HepPolyhedronEllipsoid: bad z semi-axis: cz = " << cz
2084 << std::endl;
2085 return;
2086 }
2087
2088 double dthe;
2089 double sthe;
2090 int cutflag;
2091 cutflag= 0;
2092 if (zCut2 >= cz)
2093 {
2094 sthe= 0.0;
2095 }
2096 else
2097 {
2098 sthe= std::acos(zCut2/cz);
2099 cutflag++;
2100 }
2101 if (zCut1 <= -cz)
2102 {
2103 dthe= pi - sthe;
2104 }
2105 else
2106 {
2107 dthe= std::acos(zCut1/cz)-sthe;
2108 cutflag++;
2109 }
2110
2111 // P R E P A R E T W O P O L Y L I N E S
2112 // generate sphere of radius cz first, then rescale x and y later
2113
2114 int ns = (GetNumberOfRotationSteps() + 1) / 2;
2115 int np1 = int(dthe*ns/pi) + 2 + cutflag;
2116
2117 double *zz, *rr;
2118 zz = new double[np1+1];
2119 rr = new double[np1+1];
2120 if (!zz || !rr)
2121 {
2122 std::cerr << "Out of memory in HepPolyhedronEllipsoid!" << std::endl;
2123 //Exception("Out of memory in HepPolyhedronEllipsoid!");
2124 }
2125
2126 double a = dthe/(np1-cutflag-1);
2127 double cosa, sina;
2128 int j=0;
2129 if (sthe > 0.0)
2130 {
2131 zz[j]= zCut2;
2132 rr[j]= 0.;
2133 j++;
2134 }
2135 for (int i=0; i<np1-cutflag; i++) {
2136 cosa = std::cos(sthe+i*a);
2137 sina = std::sin(sthe+i*a);
2138 zz[j] = cz*cosa;
2139 rr[j] = cz*sina;
2140 j++;
2141 }
2142 if (j < np1)
2143 {
2144 zz[j]= zCut1;
2145 rr[j]= 0.;
2146 j++;
2147 }
2148 if (j > np1)
2149 {
2150 std::cerr << "Logic error in HepPolyhedronEllipsoid, memory corrupted!"
2151 << std::endl;
2152 }
2153 if (j < np1)
2154 {
2155 std::cerr << "Warning: logic error in HepPolyhedronEllipsoid."
2156 << std::endl;
2157 np1= j;
2158 }
2159 zz[j] = 0.;
2160 rr[j] = 0.;
2161
2162
2163 // R O T A T E P O L Y L I N E S
2164
2165 RotateAroundZ(0, 0.0, twopi, np1, 1, zz, rr, -1, 1);
2166 SetReferences();
2167
2168 delete [] zz;
2169 delete [] rr;
2170
2171 // rescale x and y vertex coordinates
2172 {
2173 Point3D<double> * p= pV;
2174 for (int i=0; i<nvert; i++, p++) {
2175 p->setX( p->x() * ax/cz );
2176 p->setY( p->y() * by/cz );
2177 }
2178 }
2179}
2180
2181HepPolyhedronEllipsoid::~HepPolyhedronEllipsoid() {}
2182
2183HepPolyhedronEllipticalCone::HepPolyhedronEllipticalCone(double ax,
2184 double ay,
2185 double h,
2186 double zTopCut)
2187/***********************************************************************
2188 * *
2189 * Name: HepPolyhedronEllipticalCone Date: 8.9.2005 *
2190 * Author: D.Anninos Revised: 9.9.2005 *
2191 * *
2192 * Function: Constructor for EllipticalCone *
2193 * *
2194 * Input: ax, ay - X & Y semi axes at z = 0 *
2195 * h - height of full cone *
2196 * zTopCut - Top Cut in Z Axis *
2197 * *
2198 ***********************************************************************/
2199{
2200 // C H E C K I N P U T P A R A M E T E R S
2201
2202 int k = 0;
2203 if ( (ax <= 0.) || (ay <= 0.) || (h <= 0.) || (zTopCut <= 0.) ) { k = 1; }
2204
2205 if (k != 0) {
2206 std::cerr << "HepPolyhedronCone: error in input parameters";
2207 std::cerr << std::endl;
2208 return;
2209 }
2210
2211 // P R E P A R E T W O P O L Y L I N E S
2212
2213 zTopCut = (h >= zTopCut ? zTopCut : h);
2214
2215 double *zz, *rr;
2216 zz = new double[4];
2217 rr = new double[4];
2218 zz[0] = zTopCut;
2219 zz[1] = -zTopCut;
2220 zz[2] = zTopCut;
2221 zz[3] = -zTopCut;
2222 rr[0] = (h-zTopCut);
2223 rr[1] = (h+zTopCut);
2224 rr[2] = 0.;
2225 rr[3] = 0.;
2226
2227 // R O T A T E P O L Y L I N E S
2228
2229 RotateAroundZ(0, 0., twopi, 2, 2, zz, rr, -1, -1);
2230 SetReferences();
2231
2232 delete [] zz;
2233 delete [] rr;
2234
2235 // rescale x and y vertex coordinates
2236 {
2237 Point3D<double> * p= pV;
2238 for (int i=0; i<nvert; i++, p++) {
2239 p->setX( p->x() * ax );
2240 p->setY( p->y() * ay );
2241 }
2242 }
2243}
2244
2245HepPolyhedronEllipticalCone::~HepPolyhedronEllipticalCone() {}
2246
2247int HepPolyhedron::fNumberOfRotationSteps = DEFAULT_NUMBER_OF_STEPS;
2248/***********************************************************************
2249 * *
2250 * Name: HepPolyhedron::fNumberOfRotationSteps Date: 24.06.97 *
2251 * Author: J.Allison (Manchester University) Revised: *
2252 * *
2253 * Function: Number of steps for whole circle *
2254 * *
2255 ***********************************************************************/
2256
2257#include "BooleanProcessor.src"
2258static BooleanProcessor processor;
2259
2260HepPolyhedron HepPolyhedron::add(const HepPolyhedron & p) const
2261/***********************************************************************
2262 * *
2263 * Name: HepPolyhedron::add Date: 19.03.00 *
2264 * Author: E.Chernyaev Revised: *
2265 * *
2266 * Function: Boolean "union" of two polyhedra *
2267 * *
2268 ***********************************************************************/
2269{
2270 return processor.execute(OP_UNION, *this, p);
2271}
2272
2273HepPolyhedron HepPolyhedron::intersect(const HepPolyhedron & p) const
2274/***********************************************************************
2275 * *
2276 * Name: HepPolyhedron::intersect Date: 19.03.00 *
2277 * Author: E.Chernyaev Revised: *
2278 * *
2279 * Function: Boolean "intersection" of two polyhedra *
2280 * *
2281 ***********************************************************************/
2282{
2283 return processor.execute(OP_INTERSECTION, *this, p);
2284}
2285
2286HepPolyhedron HepPolyhedron::subtract(const HepPolyhedron & p) const
2287/***********************************************************************
2288 * *
2289 * Name: HepPolyhedron::add Date: 19.03.00 *
2290 * Author: E.Chernyaev Revised: *
2291 * *
2292 * Function: Boolean "subtraction" of "p" from "this" *
2293 * *
2294 ***********************************************************************/
2295{
2296 return processor.execute(OP_SUBTRACTION, *this, p);
2297}
2298
2299bool HepPolyhedron::IsErrorBooleanProcess() const {
2300 return processor.get_processor_error();
2301}
Note: See TracBrowser for help on using the repository browser.