1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
5 #include <cfloat> //G.Barrand : to have DBL_EPSILON on Windows.
13 // G.Barrand : introduce iabs to avoid a mess with cmath and some compiler.
14 inline int iabs(int a) {
15 return a < 0 ? -a : a;
18 //--------------------------------------------------------------------//
20 // polyhedron was polyhedron, retrofitted to Open Inventor //
22 //--------------------------------------------------------------------//
26 // ********************************************************************
29 // * The following disclaimer summarizes all the specific disclaimers *
30 // * of contributors to this software. The specific disclaimers,which *
31 // * govern, are listed with their locations in: *
32 // * http://cern.ch/geant4/license *
34 // * Neither the authors of this software system, nor their employing *
35 // * institutes,nor the agencies providing financial support for this *
36 // * work make any representation or warranty, express or implied, *
37 // * regarding this software system or assume any liability for its *
40 // * This code implementation is the intellectual property of the *
41 // * GEANT4 collaboration. *
42 // * By copying, distributing or modifying the Program (or any work *
43 // * based on the Program) you indicate your acceptance of this *
44 // * statement, and all its terms. *
45 // ********************************************************************
51 // G4 Polyhedron library
54 // 23.07.96 E.Chernyaev <Evgueni.Tcherniaev@cern.ch> - initial version
56 // 30.09.96 E.Chernyaev
57 // - added GetNextVertexIndex, GetVertex by Yasuhide Sawada
58 // - added GetNextUnitNormal, GetNextEdgeIndeces, GetNextEdge
60 // 15.12.96 E.Chernyaev
61 // - added GetNumberOfRotationSteps, RotateEdge, RotateAroundZ, SetReferences
62 // - rewritten G4PolyhedronCons;
63 // - added G4PolyhedronPara, ...Trap, ...Pgon, ...Pcon, ...Sphere, ...Torus
65 // 01.06.97 E.Chernyaev
66 // - modified RotateAroundZ, added SetSideFacets
68 // 19.03.00 E.Chernyaev
69 // - implemented boolean operations (add, subtract, intersect) on polyhedra;
71 // 25.05.01 E.Chernyaev
72 // - added GetSurfaceArea() and GetVolume();
76 /***********************************************************************
78 * Name: polyhedron operator << Date: 09.05.96 *
79 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
81 * Function: Print contents of G4 polyhedron *
83 ***********************************************************************/
84 inline int operator==(const SbFacet& v1, const SbFacet& v2) { //G.Barrand
85 for(int i=0;i<4;i++) {
86 if(v1.edge[i].v != v2.edge[i].v) return false;
87 if(v1.edge[i].f != v2.edge[i].f) return false;
91 inline int operator!=(const SbFacet& v1, const SbFacet& v2) { //G.Barrand
94 inline std::ostream& operator<<(std::ostream & ostr, const SbFacet & facet) {
95 for (int k=0; k<4; k++) {
96 ostr << " " << facet.edge[k].v << "/" << facet.edge[k].f;
100 inline std::ostream& operator<<(std::ostream & ostr, const polyhedron & ph) {
102 ostr << "Nverteces=" << ph.nvert << ", Nfacets=" << ph.nface << std::endl;
104 for (i=1; i<=ph.nvert; i++) {
105 ostr << "xyz(" << i << ")="
106 << ph.pV[i].v0() << ' ' << ph.pV[i].v1() << ' ' << ph.pV[i].v2()
109 for (i=1; i<=ph.nface; i++) {
110 ostr << "face(" << i << ")=" << ph.pF[i] << std::endl;
115 inline polyhedron::polyhedron(const polyhedron &from)
116 /***********************************************************************
118 * Name: polyhedron copy constructor Date: 23.07.96 *
119 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
121 ***********************************************************************/
124 mem::increment(s_class().c_str());
126 //m_name = 0; //G.Barrand
127 //if(from.m_name) m_name = new std::string(*from.m_name); //G.Barrand
129 if (from.nvert > 0 && from.nface > 0) {
132 pV = new HVPoint3D[nvert + 1];
133 pF = new SbFacet[nface + 1];
135 for (i=1; i<=nvert; i++) pV[i] = from.pV[i];
136 for (i=1; i<=nface; i++) pF[i] = from.pF[i];
138 nvert = 0; nface = 0; pV = 0; pF = 0;
140 fNumberOfRotationSteps = from.fNumberOfRotationSteps;
143 inline int operator==(const polyhedron& v1,const polyhedron& v2) { //G.Barrand
144 return v1.isEqual(v2);
146 inline int operator!=(const polyhedron& v1,const polyhedron& v2) { //G.Barrand
150 inline polyhedron & polyhedron::operator=(const polyhedron &from)
151 /***********************************************************************
153 * Name: polyhedron operator = Date: 23.07.96 *
154 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
156 * Function: Copy contents of one GEANT4 polyhedron to another *
158 ***********************************************************************/
161 // ::printf("debug : polyhedron::operaot=() : on same object\n");
162 // std::cerr << "polyhedron::operaot=() :"
163 // << " on same object !"
168 //delete m_name;m_name = 0; //G.Barrand
169 //if(from.m_name) m_name = new std::string(*from.m_name); //G.Barrand
173 if (from.nvert > 0 && from.nface > 0) {
176 pV = new HVPoint3D[nvert + 1];
177 pF = new SbFacet[nface + 1];
179 for (i=1; i<=nvert; i++) pV[i] = from.pV[i];
180 for (i=1; i<=nface; i++) pF[i] = from.pF[i];
182 nvert = 0; nface = 0; pV = 0; pF = 0;
184 fNumberOfRotationSteps = from.fNumberOfRotationSteps;
189 inline bool polyhedron::isEqual(const polyhedron &from) const {
190 if (this == &from) return true;
191 if(nvert!=from.nvert) return false;
192 if(nface!=from.nface) return false;
194 for (i=1; i<=nvert; i++) {
195 if(pV[i]!=from.pV[i]) return false;
197 for (i=1; i<=nface; i++) {
198 if(!pF[i].isEqual(from.pF[i])) return false;
202 inline bool polyhedron::isConsistent(const char*) const {
203 for(int i=1;i<=nface;i++) {
204 const SbFacet& facet = pF[i];
205 for(int j=0;j<4;j++) {
207 facet.GetEdge(j,v,f);
208 if(iabs(v)>nvert) return false;
209 if(iabs(f)>nvert) return false;
214 inline void polyhedron::dump(std::ostream& a_out) const {
215 a_out << " nface = " << nface << std::endl;
216 for(int i=1;i<=nface;i++) {
217 const SbFacet& facet = pF[i];
218 for(int j=0;j<4;j++) {
220 facet.GetEdge(j,v,f);
221 a_out << " " << v << " " << f << std::endl;
226 inline int polyhedron::FindNeighbour(int iFace, int iNode, int iOrder) const
227 /***********************************************************************
229 * Name: polyhedron::FindNeighbour Date: 22.11.99 *
230 * Author: E.Chernyaev Revised: *
232 * Function: Find neighbouring face *
234 ***********************************************************************/
237 for (i=0; i<4; i++) {
238 if (iNode == iabs(pF[iFace].edge[i].v)) break;
241 #ifdef TOOLS_HEP_PH_OUT_ERR
243 << "polyhedron::FindNeighbour: face " << iFace
244 << " has no node " << iNode
251 if (pF[iFace].edge[i].v == 0) i = 2;
253 return (pF[iFace].edge[i].v > 0) ? 0 : pF[iFace].edge[i].f;
256 inline HVNormal3D polyhedron::FindNodeNormal(int iFace, int iNode) const
257 /***********************************************************************
259 * Name: polyhedron::FindNodeNormal Date: 22.11.99 *
260 * Author: E.Chernyaev Revised: *
262 * Function: Find normal at given node *
264 ***********************************************************************/
266 HVNormal3D normal = GetUnitNormal(iFace);
267 int k = iFace, iOrder = 1, n = 1;
270 k = FindNeighbour(k, iNode, iOrder);
271 if (k == iFace) break;
274 normal += GetUnitNormal(k);
276 if (iOrder < 0) break;
285 inline void polyhedron::SetNumberOfRotationSteps(int n)
286 /***********************************************************************
288 * Name: polyhedron::SetNumberOfRotationSteps Date: 24.06.97 *
289 * Author: J.Allison (Manchester University) Revised: *
291 * Function: Set number of steps for whole circle *
293 ***********************************************************************/
297 #ifdef TOOLS_HEP_PH_OUT_ERR
299 << "polyhedron::SetNumberOfRotationSteps: attempt to set the\n"
300 << "number of steps per circle < " << nMin << "; forced to " << nMin
303 fNumberOfRotationSteps = nMin;
305 fNumberOfRotationSteps = n;
309 inline void polyhedron::AllocateMemory(int Nvert, int Nface)
310 /***********************************************************************
312 * Name: polyhedron::AllocateMemory Date: 19.06.96 *
313 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
315 * Function: Allocate memory for GEANT4 polyhedron *
317 * Input: Nvert - number of nodes *
318 * Nface - number of faces *
320 ***********************************************************************/
324 pV = new HVPoint3D[nvert+1];
325 pF = new SbFacet[nface+1];
328 inline void polyhedron::CreatePrism()
329 /***********************************************************************
331 * Name: polyhedron::CreatePrism Date: 15.07.96 *
332 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
334 * Function: Set facets for a prism *
336 ***********************************************************************/
338 enum {DUMMY, BOTTOM, LEFT, BACK, RIGHT, FRONT, TOP};
340 pF[1] = SbFacet(1,LEFT, 4,BACK, 3,RIGHT, 2,FRONT);
341 pF[2] = SbFacet(5,TOP, 8,BACK, 4,BOTTOM, 1,FRONT);
342 pF[3] = SbFacet(8,TOP, 7,RIGHT, 3,BOTTOM, 4,LEFT);
343 pF[4] = SbFacet(7,TOP, 6,FRONT, 2,BOTTOM, 3,BACK);
344 pF[5] = SbFacet(6,TOP, 5,LEFT, 1,BOTTOM, 2,RIGHT);
345 pF[6] = SbFacet(5,FRONT, 6,RIGHT, 7,BACK, 8,LEFT);
348 inline void polyhedron::RotateEdge(int k1, int k2, double r1, double r2,
349 int v1, int v2, int vEdge,
350 bool ifWholeCircle, int ns, int &kface)
351 /***********************************************************************
353 * Name: polyhedron::RotateEdge Date: 05.12.96 *
354 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
356 * Function: Create set of facets by rotation of an edge around Z-axis *
358 * Input: k1, k2 - end vertices of the edge *
359 * r1, r2 - radiuses of the end vertices *
360 * v1, v2 - visibility of edges produced by rotation of the end *
362 * vEdge - visibility of the edge *
363 * ifWholeCircle - is true in case of whole circle rotation *
364 * ns - number of discrete steps *
365 * r[] - r-coordinates *
366 * kface - current free cell in the pF array *
368 ***********************************************************************/
370 if (r1 == 0. && r2 == 0) return;
375 int ii1 = ifWholeCircle ? i1 : i1+ns;
376 int ii2 = ifWholeCircle ? i2 : i2+ns;
377 int vv = ifWholeCircle ? vEdge : 1;
381 pF[kface++] = SbFacet(i1,0, v2*i2,0, (i2+1),0);
382 }else if (r2 == 0.) {
383 pF[kface++] = SbFacet(i1,0, i2,0, v1*(i1+1),0);
385 pF[kface++] = SbFacet(i1,0, v2*i2,0, (i2+1),0, v1*(i1+1),0);
389 pF[kface++] = SbFacet(vv*i1,0, v2*i2,0, vEdge*(i2+1),0);
390 for (i2++,i=1; i<ns-1; i2++,i++) {
391 pF[kface++] = SbFacet(vEdge*i1,0, v2*i2,0, vEdge*(i2+1),0);
393 pF[kface++] = SbFacet(vEdge*i1,0, v2*i2,0, vv*ii2,0);
394 }else if (r2 == 0.) {
395 pF[kface++] = SbFacet(vv*i1,0, vEdge*i2,0, v1*(i1+1),0);
396 for (i1++,i=1; i<ns-1; i1++,i++) {
397 pF[kface++] = SbFacet(vEdge*i1,0, vEdge*i2,0, v1*(i1+1),0);
399 pF[kface++] = SbFacet(vEdge*i1,0, vv*i2,0, v1*ii1,0);
401 pF[kface++] = SbFacet(vv*i1,0, v2*i2,0, vEdge*(i2+1),0,v1*(i1+1),0);
402 for (i1++,i2++,i=1; i<ns-1; i1++,i2++,i++) {
403 pF[kface++] = SbFacet(vEdge*i1,0, v2*i2,0, vEdge*(i2+1),0,v1*(i1+1),0);
405 pF[kface++] = SbFacet(vEdge*i1,0, v2*i2,0, vv*ii2,0, v1*ii1,0);
410 inline void polyhedron::SetSideFacets(int ii[4], int vv[4],
412 double dphi, int ns, int &kface)
413 /***********************************************************************
415 * Name: polyhedron::SetSideFacets Date: 20.05.97 *
416 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
418 * Function: Set side facets for the case of incomplete rotation *
420 * Input: ii[4] - indeces of original verteces *
421 * vv[4] - visibility of edges *
422 * kk[] - indeces of nodes *
425 * ns - number of discrete steps *
426 * kface - current free cell in the pF array *
428 ***********************************************************************/
430 const double perMillion = 0.000001;
433 if (fabs(dphi-_M_PI()) < perMillion) { // half a circle
434 for (int i=0; i<4; i++) {
436 k2 = (i == 3) ? ii[0] : ii[i+1];
437 if (r[k1] == 0. && r[k2] == 0.) vv[i] = -1;
441 if (ii[1] == ii[2]) {
445 pF[kface++] = SbFacet(vv[0]*k1,0, vv[2]*k2,0, vv[3]*k3,0);
446 if (r[ii[0]] != 0.) k1 += ns;
447 if (r[ii[2]] != 0.) k2 += ns;
448 if (r[ii[3]] != 0.) k3 += ns;
449 pF[kface++] = SbFacet(vv[2]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
450 }else if (kk[ii[0]] == kk[ii[1]]) {
454 pF[kface++] = SbFacet(vv[1]*k1,0, vv[2]*k2,0, vv[3]*k3,0);
455 if (r[ii[0]] != 0.) k1 += ns;
456 if (r[ii[2]] != 0.) k2 += ns;
457 if (r[ii[3]] != 0.) k3 += ns;
458 pF[kface++] = SbFacet(vv[2]*k3,0, vv[1]*k2,0, vv[3]*k1,0);
459 }else if (kk[ii[2]] == kk[ii[3]]) {
463 pF[kface++] = SbFacet(vv[0]*k1,0, vv[1]*k2,0, vv[3]*k3,0);
464 if (r[ii[0]] != 0.) k1 += ns;
465 if (r[ii[1]] != 0.) k2 += ns;
466 if (r[ii[2]] != 0.) k3 += ns;
467 pF[kface++] = SbFacet(vv[1]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
473 pF[kface++] = SbFacet(vv[0]*k1,0, vv[1]*k2,0, vv[2]*k3,0, vv[3]*k4,0);
474 if (r[ii[0]] != 0.) k1 += ns;
475 if (r[ii[1]] != 0.) k2 += ns;
476 if (r[ii[2]] != 0.) k3 += ns;
477 if (r[ii[3]] != 0.) k4 += ns;
478 pF[kface++] = SbFacet(vv[2]*k4,0, vv[1]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
482 inline void polyhedron::RotateAroundZ(int nstep, double phi, double dphi,
484 const double *z, double *r,
485 int nodeVis, int edgeVis)
486 /***********************************************************************
488 * Name: polyhedron::RotateAroundZ Date: 27.11.96 *
489 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
491 * Function: Create polyhedron for a solid produced by rotation of *
492 * two polylines around Z-axis *
494 * Input: nstep - number of discrete steps, if 0 then default *
495 * phi - starting phi angle *
497 * np1 - number of points in external polyline *
498 * (must be negative in case of closed polyline) *
499 * np2 - number of points in internal polyline (may be 1) *
500 * z[] - z-coordinates (+z >>> -z for both polylines) *
501 * r[] - r-coordinates *
502 * nodeVis - how to Draw edges joing consecutive positions of *
503 * node during rotation *
504 * edgeVis - how to Draw edges *
506 ***********************************************************************/
508 static const double wholeCircle = 2*_M_PI(); //G.Barrand : const
510 // S E T R O T A T I O N P A R A M E T E R S
512 const double perMillion = 0.000001;
514 bool ifWholeCircle = (fabs(dphi-wholeCircle) < perMillion) ?
516 double delPhi = ifWholeCircle ? wholeCircle : dphi;
518 int n_step = (nstep > 0) ? nstep : GetNumberOfRotationSteps(); //G.Barrand
519 int nSphi = int(delPhi*n_step/wholeCircle+.5);
521 if (nSphi == 0) nSphi = 1;
522 int nVphi = ifWholeCircle ? nSphi : nSphi+1;
523 bool ifClosed = np1 > 0 ? false : true;
525 // C O U N T V E R T E C E S
527 int absNp1 = iabs(np1);
528 int absNp2 = iabs(np2);
530 int i1end = absNp1-1;
532 int i2end = absNp1+absNp2-1;
535 for(i=i1beg; i<=i2end; i++) {
536 if (fabs(r[i]) < perMillion) r[i] = 0.;
539 j = 0; // external nodes
540 for (i=i1beg; i<=i1end; i++) {
541 j += (r[i] == 0.) ? 1 : nVphi;
544 bool ifSide1 = false; // internal nodes
545 bool ifSide2 = false;
547 if (r[i2beg] != r[i1beg] || z[i2beg] != z[i1beg]) {
548 j += (r[i2beg] == 0.) ? 1 : nVphi;
552 for(i=i2beg+1; i<i2end; i++) {
553 j += (r[i] == 0.) ? 1 : nVphi;
556 if (r[i2end] != r[i1end] || z[i2end] != z[i1end]) {
557 if (absNp2 > 1) j += (r[i2end] == 0.) ? 1 : nVphi;
561 // C O U N T F A C E S
563 k = ifClosed ? absNp1*nSphi : (absNp1-1)*nSphi; // external faces
565 if (absNp2 > 1) { // internal faces
566 for(i=i2beg; i<i2end; i++) {
567 if (r[i] > 0. || r[i+1] > 0.) k += nSphi;
571 if (r[i2end] > 0. || r[i2beg] > 0.) k += nSphi;
575 if (!ifClosed) { // side faces
576 if (ifSide1 && (r[i1beg] > 0. || r[i2beg] > 0.)) k += nSphi;
577 if (ifSide2 && (r[i1end] > 0. || r[i2end] > 0.)) k += nSphi;
580 if (!ifWholeCircle) { // phi_side faces
581 k += ifClosed ? 2*absNp1 : 2*(absNp1-1);
584 // A L L O C A T E M E M O R Y
586 AllocateMemory(j, k);
588 // G E N E R A T E V E R T E C E S
591 kk = new int[absNp1+absNp2];
594 for(i=i1beg; i<=i1end; i++) {
596 if (r[i] == 0.) { pV[k++] = HVPoint3D(0, 0, z[i]); } else { k += nVphi; }
602 if (r[i] == 0.) { pV[k++] = HVPoint3D(0, 0, z[i]); } else { k += nVphi; }
607 for(i=i2beg+1; i<i2end; i++) {
609 if (r[i] == 0.) { pV[k++] = HVPoint3D(0, 0, z[i]); } else { k += nVphi; }
616 if (r[i] == 0.) pV[k] = HVPoint3D(0, 0, z[i]);
622 double cosPhi, sinPhi;
624 for(j=0; j<nVphi; j++) {
625 cosPhi = cos(phi+j*delPhi/nSphi);
626 sinPhi = sin(phi+j*delPhi/nSphi);
627 for(i=i1beg; i<=i2end; i++) {
628 if (r[i] != 0.) pV[kk[i]+j] = HVPoint3D(r[i]*cosPhi,r[i]*sinPhi,z[i]);
632 // G E N E R A T E E X T E R N A L F A C E S
637 v2 = ifClosed ? nodeVis : 1;
638 for(i=i1beg; i<i1end; i++) {
640 if (!ifClosed && i == i1end-1) {
643 v2 = (r[i] == r[i+1] && r[i+1] == r[i+2]) ? -1 : nodeVis;
645 RotateEdge(kk[i], kk[i+1], r[i], r[i+1], v1, v2,
646 edgeVis, ifWholeCircle, nSphi, k);
649 RotateEdge(kk[i1end], kk[i1beg], r[i1end],r[i1beg], nodeVis, nodeVis,
650 edgeVis, ifWholeCircle, nSphi, k);
653 // G E N E R A T E I N T E R N A L F A C E S
656 v2 = ifClosed ? nodeVis : 1;
657 for(i=i2beg; i<i2end; i++) {
659 if (!ifClosed && i==i2end-1) {
662 v2 = (r[i] == r[i+1] && r[i+1] == r[i+2]) ? -1 : nodeVis;
664 RotateEdge(kk[i+1], kk[i], r[i+1], r[i], v2, v1,
665 edgeVis, ifWholeCircle, nSphi, k);
668 RotateEdge(kk[i2beg], kk[i2end], r[i2beg], r[i2end], nodeVis, nodeVis,
669 edgeVis, ifWholeCircle, nSphi, k);
673 // G E N E R A T E S I D E F A C E S
677 RotateEdge(kk[i2beg], kk[i1beg], r[i2beg], r[i1beg], 1, 1,
678 -1, ifWholeCircle, nSphi, k);
681 RotateEdge(kk[i1end], kk[i2end], r[i1end], r[i2end], 1, 1,
682 -1, ifWholeCircle, nSphi, k);
686 // G E N E R A T E S I D E F A C E S for the case of incomplete circle
688 if (!ifWholeCircle) {
693 for (i=i1beg; i<=i1end; i++) {
695 ii[3] = (i == i1end) ? i1beg : i+1;
696 ii[1] = (absNp2 == 1) ? i2beg : ii[0]+absNp1;
697 ii[2] = (absNp2 == 1) ? i2beg : ii[3]+absNp1;
702 SetSideFacets(ii, vv, kk, r, dphi, nSphi, k);
705 for (i=i1beg; i<i1end; i++) {
708 ii[1] = (absNp2 == 1) ? i2beg : ii[0]+absNp1;
709 ii[2] = (absNp2 == 1) ? i2beg : ii[3]+absNp1;
710 vv[0] = (i == i1beg) ? 1 : -1;
712 vv[2] = (i == i1end-1) ? 1 : -1;
714 SetSideFacets(ii, vv, kk, r, dphi, nSphi, k);
722 #ifdef TOOLS_HEP_PH_OUT_ERR
724 << "Polyhedron::RotateAroundZ: number of generated faces ("
725 << k-1 << ") is not equal to the number of allocated faces ("
732 inline void polyhedron::SetReferences()
733 /***********************************************************************
735 * Name: polyhedron::SetReferences Date: 04.12.96 *
736 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
738 * Function: For each edge set reference to neighbouring facet *
740 ***********************************************************************/
742 if (nface <= 0) return;
744 struct edgeListMember {
745 edgeListMember *next;
749 } *edgeList, *freeList, **headList;
752 // A L L O C A T E A N D I N I T I A T E L I S T S
754 edgeList = new edgeListMember[2*nface];
755 headList = new edgeListMember*[nvert];
758 #ifdef TOOLS_HEP_PH_NOT_OPT
759 for (i=0; i<nvert; i++) {
763 for (i=0; i<2*nface-1; i++) {
764 edgeList[i].next = &edgeList[i+1];
766 edgeList[2*nface-1].next = 0;
768 {edgeListMember** hpos = headList;
769 for (i=0; i<nvert; i++,hpos++) *hpos = 0;
772 edgeListMember* epos = edgeList;
773 for (i=0; i<num; i++,epos++) {
774 (*epos).next = epos+1;
779 // L O O P A L O N G E D G E S
781 int iface, iedge, nedge, i1, i2, k1, k2;
782 edgeListMember *prev, *cur;
784 #ifdef TOOLS_HEP_PH_NOT_OPT
786 edgeListMember** hpos;
788 SbFacet* pF_cur_iface;
791 for(iface=1; iface<=nface; iface++) {
792 #ifdef TOOLS_HEP_PH_NOT_OPT
793 nedge = (pF[iface].edge[3].v == 0) ? 3 : 4;
796 nedge = (pF_iface->edge[3].v == 0) ? 3 : 4;
798 for (iedge=0; iedge<nedge; iedge++) {
800 i2 = (iedge < nedge-1) ? iedge+1 : 0;
801 #ifdef TOOLS_HEP_PH_NOT_OPT
802 i1 = iabs(pF[iface].edge[i1].v);
803 i2 = iabs(pF[iface].edge[i2].v);
804 k1 = (i1 < i2) ? i1 : i2; // k1 = ::min(i1,i2);
805 k2 = (i1 > i2) ? i1 : i2; // k2 = ::max(i1,i2);
807 i1 = iabs(pF_iface->edge[i1].v);
808 i2 = iabs(pF_iface->edge[i2].v);
817 // check head of the List corresponding to k1
818 #ifdef TOOLS_HEP_PH_NOT_OPT
825 #ifdef TOOLS_HEP_PH_NOT_OPT
826 headList[k1] = freeList;
827 freeList = freeList->next;
831 freeList = freeList->next;
842 #ifdef TOOLS_HEP_PH_NOT_OPT
843 headList[k1] = cur->next;
847 cur->next = freeList;
849 #ifdef TOOLS_HEP_PH_NOT_OPT
850 pF[iface].edge[iedge].f = cur->iface;
851 pF[cur->iface].edge[cur->iedge].f = iface;
852 i1 = (pF[iface].edge[iedge].v < 0) ? -1 : 1;
853 i2 = (pF[cur->iface].edge[cur->iedge].v < 0) ? -1 : 1;
855 pF_iface->edge[iedge].f = cur->iface;
856 pF_cur_iface = pF+cur->iface;
857 pF_cur_iface->edge[cur->iedge].f = iface;
858 i1 = (pF_iface->edge[iedge].v < 0) ? -1 : 1;
859 i2 = (pF_cur_iface->edge[cur->iedge].v < 0) ? -1 : 1;
862 #ifdef TOOLS_HEP_PH_OUT_ERR
864 << "Polyhedron::SetReferences: different edge visibility "
865 << iface << "/" << iedge << "/"
866 << pF[iface].edge[iedge].v << " and "
867 << cur->iface << "/" << cur->iedge << "/"
868 << pF[cur->iface].edge[cur->iedge].v
880 prev->next = freeList;
881 freeList = freeList->next;
891 prev->next = cur->next;
892 cur->next = freeList;
894 #ifdef TOOLS_HEP_PH_NOT_OPT
895 pF[iface].edge[iedge].f = cur->iface;
896 pF[cur->iface].edge[cur->iedge].f = iface;
897 i1 = (pF[iface].edge[iedge].v < 0) ? -1 : 1;
898 i2 = (pF[cur->iface].edge[cur->iedge].v < 0) ? -1 : 1;
900 pF_iface->edge[iedge].f = cur->iface;
901 pF_cur_iface = pF+cur->iface;
902 pF_cur_iface->edge[cur->iedge].f = iface;
903 i1 = (pF_iface->edge[iedge].v < 0) ? -1 : 1;
904 i2 = (pF_cur_iface->edge[cur->iedge].v < 0) ? -1 : 1;
907 #ifdef TOOLS_HEP_PH_OUT_ERR
909 << "Polyhedron::SetReferences: different edge visibility "
910 << iface << "/" << iedge << "/"
911 << pF[iface].edge[iedge].v << " and "
912 << cur->iface << "/" << cur->iedge << "/"
913 << pF[cur->iface].edge[cur->iedge].v
923 // 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
925 #ifdef TOOLS_HEP_PH_OUT_ERR
926 #ifdef TOOLS_HEP_PH_NOT_OPT
927 for (i=0; i<nvert; i++) {
928 if (headList[i] != 0) {
930 << "Polyhedron::SetReferences: List " << i << " is not empty"
935 {edgeListMember** hpos = headList;
936 for (i=0; i<nvert; i++,hpos++) {
939 << "Polyhedron::SetReferences: List " << i << " is not empty"
946 // F R E E M E M O R Y
952 inline void polyhedron::InvertFacets()
953 /***********************************************************************
955 * Name: polyhedron::InvertFacets Date: 01.12.99 *
956 * Author: E.Chernyaev Revised: *
958 * Function: Invert the order of the nodes in the facets *
960 ***********************************************************************/
962 if (nface <= 0) return;
963 int i, k, nnode, v[4],f[4];
964 for (i=1; i<=nface; i++) {
965 nnode = (pF[i].edge[3].v == 0) ? 3 : 4;
966 for (k=0; k<nnode; k++) {
967 v[k] = (k+1 == nnode) ? pF[i].edge[0].v : pF[i].edge[k+1].v;
968 if (v[k] * pF[i].edge[k].v < 0) v[k] = -v[k];
969 f[k] = pF[i].edge[k].f;
971 for (k=0; k<nnode; k++) {
972 pF[i].edge[nnode-1-k].v = v[k];
973 pF[i].edge[nnode-1-k].f = f[k];
979 inline polyhedron & polyhedron::Transform(
980 const SbRotation& rotation
981 ,const SbVec3f& translation
985 for (int i=1; i<=nvert; i++) {
986 const HVPoint3D& pv = pV[i];
988 rotation.multVec(SbVec3f(pv[0],pv[1],pv[2]),tmp);
989 pV[i] = HVPoint3D(tmp[0],tmp[1],tmp[2])
990 +HVPoint3D(translation[0],translation[1],translation[2]);
993 // C H E C K D E T E R M I N A N T A N D
994 // 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
996 //FIXME : have the below done in double.
997 SbVec3f x; rotation.multVec(SbVec3f(1,0,0),x);
998 SbVec3f y; rotation.multVec(SbVec3f(0,1,0),y);
999 SbVec3f z; rotation.multVec(SbVec3f(0,0,1),z);
1000 if ((x.cross(y)).dot(z) < 0) InvertFacets();
1006 /*G.Barrand : optimized version.*/
1007 inline polyhedron & polyhedron::Translate(
1014 for (int i=1; i<=nvert; i++) {
1015 const HVPoint3D& p = pV[i];
1016 pV[i].set_value(p.x()+a_x,p.y()+a_y,p.z()+a_z);
1022 inline polyhedron & polyhedron::Transform(const rotd& rotation,double a_x,double a_y,double a_z) {
1025 for (int i=1; i<=nvert; i++) {
1026 HVPoint3D& p = pV[i];
1030 rotation.mul_3(x,y,z); //tmp = R*pV[i]
1031 p.set_value(x+a_x,y+a_y,z+a_z);
1037 rotation.mul_3(x_x,x_y,x_z);
1042 rotation.mul_3(y_x,y_y,y_z);
1047 rotation.mul_3(z_x,z_y,z_z);
1052 double x_cross_y_x = x_y*y_z-x_z*y_y;
1053 double x_cross_y_y = x_z*y_x-x_x*y_z;
1054 double x_cross_y_z = x_x*y_y-x_y*y_x;
1056 double x_cross_y_dot_z =
1057 x_cross_y_x*z_x + x_cross_y_y*z_y + x_cross_y_z*z_z;
1058 if (x_cross_y_dot_z < 0) InvertFacets();
1063 inline polyhedron & polyhedron::Transform(const rotd& rotation,const vec3d& translation) {
1067 for (int i=1; i<=nvert; i++) {
1068 rotation.mul_vec(pV[i],tmp); //tmp = R*pV[i]
1069 pV[i] = tmp+translation;
1071 vec3d x; rotation.mul_vec(vec3d::s_x(),x);
1072 vec3d y; rotation.mul_vec(vec3d::s_y(),y);
1073 vec3d z; rotation.mul_vec(vec3d::s_z(),z);
1074 if ((x.cross(y)).dot(z) < 0) InvertFacets();
1077 return Transform(rotation,translation.x(),translation.y(),translation.z());
1080 /*G.Barrand : inline
1081 bool polyhedron::GetNextVertexIndex(int &index, int &edgeFlag) const
1082 // ***********************************************************************
1084 // * Name: polyhedron::GetNextVertexIndex Date: 03.09.96 *
1085 // * Author: Yasuhide Sawada Revised: *
1089 // ***********************************************************************
1091 static int iFace = 1;
1092 static int iQVertex = 0;
1093 int vIndex = pF[iFace].edge[iQVertex].v;
1095 edgeFlag = (vIndex > 0) ? 1 : 0;
1096 index = iabs(vIndex);
1099 #ifdef TOOLS_HEP_PH_OUT_ERR
1100 std::cerr << "polyhedron::GetNextVertexIndex: pV index problem "
1101 << index << " exceed " << nvert << std::endl;
1106 if (iQVertex >= 3 || pF[iFace].edge[iQVertex+1].v == 0) {
1108 if (++iFace > nface) iFace = 1;
1109 return false; // Last Edge
1112 return true; // not Last Edge
1117 inline HVPoint3D polyhedron::GetVertex(int index) const
1118 /***********************************************************************
1120 * Name: polyhedron::GetVertex Date: 03.09.96 *
1121 * Author: Yasuhide Sawada Revised: 17.11.99 *
1123 * Function: Get vertex of the index. *
1125 ***********************************************************************/
1127 if (index <= 0 || index > nvert) {
1128 #ifdef TOOLS_HEP_PH_OUT_ERR
1130 << "polyhedron::GetVertex: irrelevant index " << index
1138 inline const HVPoint3D& polyhedron::GetVertexFast(int index) const {//G.Barrand
1142 inline bool polyhedron::GetNextVertex(HVPoint3D &vertex, int &edgeFlag) const
1143 /***********************************************************************
1145 * Name: polyhedron::GetNextVertex Date: 22.07.96 *
1146 * Author: John Allison Revised: *
1148 * Function: Get vertices of the quadrilaterals in order for each *
1149 * face in face order. Returns false when finished each *
1152 ***********************************************************************/
1155 bool rep = GetNextVertexIndex(index, edgeFlag);
1160 inline bool polyhedron::GetNextVertex(HVPoint3D &vertex, int &edgeFlag,HVNormal3D &normal) const
1161 /***********************************************************************
1163 * Name: polyhedron::GetNextVertex Date: 26.11.99 *
1164 * Author: E.Chernyaev Revised: *
1166 * Function: Get vertices with normals of the quadrilaterals in order *
1167 * for each face in face order. *
1168 * Returns false when finished each face. *
1170 ***********************************************************************/
1172 static int iFace = 1;
1173 static int iNode = 0;
1175 if (nface == 0) return false; // empty polyhedron
1177 int k = pF[iFace].edge[iNode].v;
1178 if (k > 0) { edgeFlag = 1; } else { edgeFlag = -1; k = -k; }
1180 normal = FindNodeNormal(iFace,k);
1181 if (iNode >= 3 || pF[iFace].edge[iNode+1].v == 0) {
1183 if (++iFace > nface) iFace = 1;
1184 return false; // last node
1187 return true; // not last node
1191 inline bool polyhedron::GetNextEdgeIndeces(int &i1, int &i2, int &edgeFlag,
1192 int &iface1, int &iface2) const
1193 /***********************************************************************
1195 * Name: polyhedron::GetNextEdgeIndeces Date: 30.09.96 *
1196 * Author: E.Chernyaev Revised: 17.11.99 *
1198 * Function: Get indeces of the next edge together with indeces of *
1199 * of the faces which share the edge. *
1200 * Returns false when the last edge. *
1202 ***********************************************************************/
1204 static int iFace = 1;
1205 static int iQVertex = 0;
1206 static int iOrder = 1;
1207 int k1, k2, kflag, kface1, kface2;
1209 if (iFace == 1 && iQVertex == 0) {
1210 k2 = pF[nface].edge[0].v;
1211 k1 = pF[nface].edge[3].v;
1212 if (k1 == 0) k1 = pF[nface].edge[2].v;
1213 if (iabs(k1) > iabs(k2)) iOrder = -1;
1217 k1 = pF[iFace].edge[iQVertex].v;
1221 kface2 = pF[iFace].edge[iQVertex].f;
1222 if (iQVertex >= 3 || pF[iFace].edge[iQVertex+1].v == 0) {
1224 k2 = iabs(pF[iFace].edge[iQVertex].v);
1228 k2 = iabs(pF[iFace].edge[iQVertex].v);
1230 } while (iOrder*k1 > iOrder*k2);
1232 i1 = k1; i2 = k2; edgeFlag = (kflag > 0) ? 1 : 0;
1233 iface1 = kface1; iface2 = kface2;
1235 if (iFace > nface) {
1236 iFace = 1; iOrder = 1;
1243 inline bool polyhedron::GetNextEdgeIndeces(int &i1, int &i2, int &edgeFlag) const
1244 /***********************************************************************
1246 * Name: polyhedron::GetNextEdgeIndeces Date: 17.11.99 *
1247 * Author: E.Chernyaev Revised: *
1249 * Function: Get indeces of the next edge. *
1250 * Returns false when the last edge. *
1252 ***********************************************************************/
1255 return GetNextEdgeIndeces(i1, i2, edgeFlag, kface1, kface2);
1258 inline bool polyhedron::GetNextEdge(HVPoint3D &p1,HVPoint3D &p2,int &edgeFlag) const
1259 /***********************************************************************
1261 * Name: polyhedron::GetNextEdge Date: 30.09.96 *
1262 * Author: E.Chernyaev Revised: *
1264 * Function: Get next edge. *
1265 * Returns false when the last edge. *
1267 ***********************************************************************/
1270 bool rep = GetNextEdgeIndeces(i1,i2,edgeFlag);
1276 inline bool polyhedron::GetNextEdge(HVPoint3D &p1, HVPoint3D &p2,int &edgeFlag, int &iface1, int &iface2) const
1277 /***********************************************************************
1279 * Name: polyhedron::GetNextEdge Date: 17.11.99 *
1280 * Author: E.Chernyaev Revised: *
1282 * Function: Get next edge with indeces of the faces which share *
1284 * Returns false when the last edge. *
1286 ***********************************************************************/
1289 bool rep = GetNextEdgeIndeces(i1,i2,edgeFlag,iface1,iface2);
1295 inline void polyhedron::GetFacet(int iFace, int &n, int *iNodes,int *edgeFlags, int *iFaces) const
1296 /***********************************************************************
1298 * Name: polyhedron::GetFacet Date: 15.12.99 *
1299 * Author: E.Chernyaev Revised: *
1301 * Function: Get face by index *
1303 ***********************************************************************/
1305 if (iFace < 1 || iFace > nface) {
1306 #ifdef TOOLS_HEP_PH_OUT_ERR
1308 << "polyhedron::GetFacet: irrelevant index " << iFace
1314 for (i=0; i<4; i++) {
1315 k = pF[iFace].edge[i].v;
1317 if (iFaces != 0) iFaces[i] = pF[iFace].edge[i].f;
1320 if (edgeFlags != 0) edgeFlags[i] = 1;
1323 if (edgeFlags != 0) edgeFlags[i] = -1;
1330 inline void polyhedron::GetFacet(int index, int &n, HVPoint3D *nodes,int *edgeFlags, HVNormal3D *normals) const
1331 /***********************************************************************
1333 * Name: polyhedron::GetFacet Date: 17.11.99 *
1334 * Author: E.Chernyaev Revised: *
1336 * Function: Get face by index *
1338 ***********************************************************************/
1341 GetFacet(index, n, iNodes, edgeFlags);
1343 for (int i=0; i<4; i++) {
1344 nodes[i] = pV[iNodes[i]];
1345 if (normals != 0) normals[i] = FindNodeNormal(index,iNodes[i]);
1350 inline bool polyhedron::GetNextFacet(int &n, HVPoint3D *nodes,int *edgeFlags, HVNormal3D *normals) const
1351 /***********************************************************************
1353 * Name: polyhedron::GetNextFacet Date: 19.11.99 *
1354 * Author: E.Chernyaev Revised: *
1356 * Function: Get next face with normals of unit length at the nodes. *
1357 * Returns false when finished all faces. *
1359 ***********************************************************************/
1361 static int iFace = 1;
1363 if (edgeFlags == 0) {
1364 GetFacet(iFace, n, nodes);
1365 }else if (normals == 0) {
1366 GetFacet(iFace, n, nodes, edgeFlags);
1368 GetFacet(iFace, n, nodes, edgeFlags, normals);
1371 if (++iFace > nface) {
1380 #ifdef TOOLS_HEP_PH_OUT_ERR
1381 inline bool polyhedron::CHECK_INDEX(const char* a_method,int a_index) const {
1383 std::cerr << "polyhedron::" << a_method << " :"
1384 << " index problem. "
1385 << a_index << " exceed " << nvert << std::endl;
1391 inline bool polyhedron::CHECK_INDEX(const char*,int a_index) const {
1399 inline HVNormal3D polyhedron::GetNormal(int iFace) const
1400 /***********************************************************************
1402 * Name: polyhedron::GetNormal Date: 19.11.99 *
1403 * Author: E.Chernyaev Revised: *
1405 * Function: Get normal of the face given by index *
1407 ***********************************************************************/
1409 if (iFace < 1 || iFace > nface) {
1410 #ifdef TOOLS_HEP_PH_OUT_ERR
1412 << "polyhedron::GetNormal: irrelevant index " << iFace
1415 return HVNormal3D();
1418 int i0 = iabs(pF[iFace].edge[0].v);
1419 int i1 = iabs(pF[iFace].edge[1].v);
1420 int i2 = iabs(pF[iFace].edge[2].v);
1421 int i3 = iabs(pF[iFace].edge[3].v);
1422 if (i3 == 0) i3 = i0;
1424 if(!CHECK_INDEX("GetNormal",i0)) return HVNormal3D();
1425 if(!CHECK_INDEX("GetNormal",i1)) return HVNormal3D();
1426 if(!CHECK_INDEX("GetNormal",i2)) return HVNormal3D();
1427 if(!CHECK_INDEX("GetNormal",i3)) return HVNormal3D();
1430 (pV[i2] - pV[i0]).cross(pV[i3] - pV[i1],nm);
1434 inline HVNormal3D polyhedron::GetUnitNormal(int iFace) const
1435 /***********************************************************************
1437 * Name: polyhedron::GetNormal Date: 19.11.99 *
1438 * Author: E.Chernyaev Revised: *
1440 * Function: Get unit normal of the face given by index *
1442 ***********************************************************************/
1444 if (iFace < 1 || iFace > nface) {
1445 #ifdef TOOLS_HEP_PH_OUT_ERR
1447 << "polyhedron::GetUnitNormal: irrelevant index " << iFace
1450 return HVNormal3D();
1453 int i0 = iabs(pF[iFace].edge[0].v);
1454 int i1 = iabs(pF[iFace].edge[1].v);
1455 int i2 = iabs(pF[iFace].edge[2].v);
1456 int i3 = iabs(pF[iFace].edge[3].v);
1457 if (i3 == 0) i3 = i0;
1459 if(!CHECK_INDEX("GetUnitNormal",i0)) return HVNormal3D();
1460 if(!CHECK_INDEX("GetUnitNormal",i1)) return HVNormal3D();
1461 if(!CHECK_INDEX("GetUnitNormal",i2)) return HVNormal3D();
1462 if(!CHECK_INDEX("GetUnitNormal",i3)) return HVNormal3D();
1465 (pV[i2] - pV[i0]).cross(pV[i3] - pV[i1],nm);
1470 inline bool polyhedron::GetNextNormal(HVNormal3D &normal) const
1471 /***********************************************************************
1473 * Name: polyhedron::GetNextNormal Date: 22.07.96 *
1474 * Author: John Allison Revised: 19.11.99 *
1476 * Function: Get normals of each face in face order. Returns false *
1477 * when finished all faces. *
1479 ***********************************************************************/
1481 static int iFace = 1;
1482 normal = GetNormal(iFace);
1483 if (++iFace > nface) {
1491 inline bool polyhedron::GetNextUnitNormal(HVNormal3D &normal) const
1492 /***********************************************************************
1494 * Name: polyhedron::GetNextUnitNormal Date: 16.09.96 *
1495 * Author: E.Chernyaev Revised: *
1497 * Function: Get normals of unit length of each face in face order. *
1498 * Returns false when finished all faces. *
1500 ***********************************************************************/
1502 bool rep = GetNextNormal(normal);
1507 inline double polyhedron::GetSurfaceArea() const
1508 /***********************************************************************
1510 * Name: polyhedron::GetSurfaceArea Date: 25.05.01 *
1511 * Author: E.Chernyaev Revised: *
1513 * Function: Returns area of the surface of the polyhedron. *
1515 ***********************************************************************/
1519 for (int iFace=1; iFace<=nface; iFace++) {
1520 int i0 = iabs(pF[iFace].edge[0].v);
1521 int i1 = iabs(pF[iFace].edge[1].v);
1522 int i2 = iabs(pF[iFace].edge[2].v);
1523 int i3 = iabs(pF[iFace].edge[3].v);
1524 if (i3 == 0) i3 = i0;
1525 (pV[i2] - pV[i0]).cross(pV[i3] - pV[i1],p);
1531 inline double polyhedron::GetVolume() const
1532 /***********************************************************************
1534 * Name: polyhedron::GetVolume Date: 25.05.01 *
1535 * Author: E.Chernyaev Revised: *
1537 * Function: Returns volume of the polyhedron. *
1539 ***********************************************************************/
1543 for (int iFace=1; iFace<=nface; iFace++) {
1544 int i0 = iabs(pF[iFace].edge[0].v);
1545 int i1 = iabs(pF[iFace].edge[1].v);
1546 int i2 = iabs(pF[iFace].edge[2].v);
1547 int i3 = iabs(pF[iFace].edge[3].v);
1551 g = (pV[i0]+pV[i1]+pV[i2]) * (1.0/3.0);
1553 g = (pV[i0]+pV[i1]+pV[i2]+pV[i3]) * 0.25;
1555 (pV[i2] - pV[i0]).cross(pV[i3] - pV[i1],p);
1563 bool polyhedron::set_polyhedron_trd2(double Dx1, double Dx2,
1564 double Dy1, double Dy2,
1566 /***********************************************************************
1568 * Name: polyhedron_trd2 Date: 22.07.96 *
1569 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
1571 * Function: Create GEANT4 TRD2-trapezoid *
1573 * Input: Dx1 - half-length along X at -Dz 8----7 *
1574 * Dx2 - half-length along X ay +Dz 5----6 ! *
1575 * Dy1 - half-length along Y ay -Dz ! 4-!--3 *
1576 * Dy2 - half-length along Y ay +Dz 1----2 *
1577 * Dz - half-length along Z *
1579 ***********************************************************************/
1581 _clear(); //G.Barrand
1583 //From TGeoTrd2::Capacity() :
1584 double capacity = 2*(Dx1+Dx2)*(Dy1+Dy2)*Dz +
1585 (2./3.)*(Dx1-Dx2)*(Dy1-Dy2)*Dz;
1587 //if(//(Dx1<=0.0)||(Dx2<=0.0)||
1588 // //(Dy1<=0.0)||(Dy2<=0.0)||
1589 // (Dz<=0.0)){ //G.Barrand
1591 #if defined(TOOLS_HEP_PH_OUT_ERR) || defined(TOOLS_HEP_PH_OUT_ERR_TRD2)
1592 std::cerr << "set_polyhedron_trd2: error in input parameters";
1593 std::cerr << " Dx1=" << Dx1
1603 AllocateMemory(8,6);
1605 pV[1] = HVPoint3D(-Dx1,-Dy1,-Dz);
1606 pV[2] = HVPoint3D( Dx1,-Dy1,-Dz);
1607 pV[3] = HVPoint3D( Dx1, Dy1,-Dz);
1608 pV[4] = HVPoint3D(-Dx1, Dy1,-Dz);
1609 pV[5] = HVPoint3D(-Dx2,-Dy2, Dz);
1610 pV[6] = HVPoint3D( Dx2,-Dy2, Dz);
1611 pV[7] = HVPoint3D( Dx2, Dy2, Dz);
1612 pV[8] = HVPoint3D(-Dx2, Dy2, Dz);
1620 polyhedron_trd2::polyhedron_trd2(double Dx1, double Dx2,
1621 double Dy1, double Dy2,
1624 set_polyhedron_trd2(Dx1,Dx2,Dy1,Dy2,Dz); //G.Barrand
1629 bool polyhedron::set_polyhedron_arb8(double Dz,const double* xy) {
1630 _clear(); //G.Barrand
1632 // xy as if xy[8][2]
1633 // then xy[i][j] = xy[i*2+j]
1635 // from TGeoArb8::Capacity() :
1636 double capacity = 0;
1638 for(int i=0; i<4; i++) {
1641 0.25*Dz*((vxy(xy,i,0)+vxy(xy,i+4,0))*(vxy(xy,j,1)+vxy(xy,j+4,1)) -
1642 (vxy(xy,j,0)+vxy(xy,j+4,0))*(vxy(xy,i,1)+vxy(xy,i+4,1)) +
1643 (1./3)*((vxy(xy,i+4,0)-vxy(xy,i,0))*(vxy(xy,j+4,1)-vxy(xy,j,1)) -
1644 (vxy(xy,j,0)-vxy(xy,j+4,0))*(vxy(xy,i,1)-vxy(xy,i+4,1))));
1646 capacity = ::fabs(capacity);}
1651 AllocateMemory(8,6);
1653 pV[1] = HVPoint3D( vxy(xy,0,0), vxy(xy,0,1),-Dz);
1654 pV[2] = HVPoint3D( vxy(xy,1,0), vxy(xy,1,1),-Dz);
1655 pV[3] = HVPoint3D( vxy(xy,2,0), vxy(xy,2,1),-Dz);
1656 pV[4] = HVPoint3D( vxy(xy,3,0), vxy(xy,3,1),-Dz);
1657 pV[5] = HVPoint3D( vxy(xy,4,0), vxy(xy,4,1), Dz);
1658 pV[6] = HVPoint3D( vxy(xy,5,0), vxy(xy,5,1), Dz);
1659 pV[7] = HVPoint3D( vxy(xy,6,0), vxy(xy,6,1), Dz);
1660 pV[8] = HVPoint3D( vxy(xy,7,0), vxy(xy,7,1), Dz);
1668 polyhedron_arb8::polyhedron_arb8(double Dz,const double* xy)
1670 set_polyhedron_arb8(Dz,xy); //G.Barrand
1675 int polyhedron::_ixy(
1685 return a_iz*a_npts+a_ixy;
1687 return (a_nz-1-a_iz)*a_npts+a_ixy;
1691 return a_iz*a_npts+(a_npts-1-a_ixy);
1693 return (a_nz-1-a_iz)*a_npts+(a_npts-1-a_ixy);
1699 bool polyhedron::set_polyhedron_xtru(
1700 int a_npts // number of vertices of the 2D polygon (at least 3)
1701 ,int a_nz // number of z planes (at least two)
1702 ,double* a_xs //[a_nz][a_npts] X positions for polygon vertices
1703 ,double* a_ys //[a_nz][a_npts] Y positions for polygon vertices
1704 ,double* a_zs //[a_nz] Z positions
1705 //default orientations :
1706 ,bool a_acw //= true
1707 ,bool a_zfb //= true
1709 _clear(); //G.Barrand
1711 if(a_npts<=2) return false;
1712 if(a_nz<=1) return false;
1716 {double xv = a_xs[1]-a_xs[0];
1717 double yv = a_ys[1]-a_ys[0];
1718 double xw,yw,cross_z;
1719 for(int j=2;j<a_npts;j++) {
1720 xw = a_xs[j]-a_xs[j-1];
1721 yw = a_ys[j]-a_ys[j-1];
1726 cross_z = xv*yw-yv*xw;
1728 if(cross_z<0) {convex = false;break;}
1730 if(cross_z>0) {convex = false;break;}
1736 // have to check seg(n-2,n-1) to seg(n-1,0)
1737 xw = a_xs[0]-a_xs[a_npts-1];
1738 yw = a_ys[0]-a_ys[a_npts-1];
1739 cross_z = xv*yw-yv*xw;
1741 if(cross_z<0) convex = false;
1743 if(cross_z>0) convex = false;
1749 // have to check seg(n-1,0) to seg(0,1)
1750 xw = a_xs[1]-a_xs[0];
1751 yw = a_ys[1]-a_ys[0];
1752 cross_z = xv*yw-yv*xw;
1754 if(cross_z<0) convex = false;
1756 if(cross_z>0) convex = false;
1760 #ifdef TOOLS_HEP_PH_OUT_ERR
1761 std::cerr << "tools::hep::set_polyhedron_xtru :"
1762 << " not convex polygon."
1768 // C O U N T V E R T E C E S
1772 int j = a_nz*a_npts+2;
1774 // C O U N T F A C E S
1776 int k = ((a_nz-1)+1+1)*a_npts;
1778 // A L L O C A T E M E M O R Y
1780 AllocateMemory(j, k);
1782 // G E N E R A T E V E R T E C E S
1784 int* kk = new int[a_nz+2];
1787 for(i=0; i<a_nz; i++) {
1798 for(j=0; j<a_npts; j++) {
1799 for(i=0; i<a_nz; i++) {
1802 pV[kk[i]+j] = HVPoint3D(a_xs[ixy],a_ys[ixy],a_zs[iz]);
1806 for(j=0; j<a_npts; j++) {
1807 for(i=0; i<a_nz; i++) {
1810 pV[kk[i]+j] = HVPoint3D(a_xs[ixy],a_ys[ixy],a_zs[iz]);
1816 for(j=0; j<a_npts; j++) {
1817 for(i=0; i<a_nz; i++) {
1819 ixy = iz*a_npts+a_npts-1-j;
1820 pV[kk[i]+j] = HVPoint3D(a_xs[ixy],a_ys[ixy],a_zs[iz]);
1824 for(j=0; j<a_npts; j++) {
1825 for(i=0; i<a_nz; i++) {
1827 ixy = iz*a_npts+a_npts-1-j;
1828 pV[kk[i]+j] = HVPoint3D(a_xs[ixy],a_ys[ixy],a_zs[iz]);
1836 for(j=0; j<a_npts; j++) {
1837 ixy = _ixy(j,a_npts,0,a_nz,a_acw,a_zfb);
1844 pV[kk[a_nz]] = HVPoint3D(xcbeg,ycbeg,a_zs[0]);
1846 pV[kk[a_nz]] = HVPoint3D(xcbeg,ycbeg,a_zs[a_nz-1]);
1851 for(j=0; j<a_npts; j++) {
1852 ixy = _ixy(j,a_npts,a_nz-1,a_nz,a_acw,a_zfb);
1859 pV[kk[a_nz+1]] = HVPoint3D(xcend,ycend,a_zs[a_nz-1]);
1861 pV[kk[a_nz+1]] = HVPoint3D(xcend,ycend,a_zs[0]);
1864 // G E N E R A T E E X T E R N A L F A C E S
1870 for(i=0; i<(a_nz-1); i++) {
1871 RotateEdge(kk[i], kk[i+1], 1, 1, v1, v2,
1872 edgeVis, true, a_npts, k);
1875 // G E N E R A T E S I D E F A C E S
1877 RotateEdge(kk[a_nz], kk[0], 0, 1, 1, 1,
1878 -1, true, a_npts, k);
1880 RotateEdge(kk[a_nz-1], kk[a_nz+1], 1, 0, 1, 1,
1881 -1, true, a_npts, k);
1885 if ((k-1) != nface) {
1886 #ifdef TOOLS_HEP_PH_OUT_ERR
1888 << "Polyhedron::RotateAroundZ: number of generated faces ("
1889 << k-1 << ") is not equal to the number of allocated faces ("
1900 polyhedron_xtru::polyhedron_xtru(int a_npts,int a_nz,
1901 double* a_xs,double* a_ys,double* a_zs,
1902 bool a_acw, //= true
1903 bool a_zfb){ //= true
1904 set_polyhedron_xtru(a_npts,a_nz,a_xs,a_ys,a_zs,a_acw,a_zfb);
1909 bool polyhedron::set_polyhedron_hype(double a_st_in,double a_st_out,
1910 double a_rmin,double a_rmax,double a_dz,
1911 int a_nz,int a_nphi) //G.Barrand
1913 static const double wholeCircle = 2*_M_PI(); //G.Barrand : const
1915 _clear(); //G.Barrand
1917 // C H E C K I N P U T P A R A M E T E R S
1920 if (a_rmin < 0. || a_rmax < 0.) k = 1;
1921 if (a_rmin > a_rmax) k = 1;
1922 if (a_rmin == a_rmax) k = 1;
1924 if (a_dz <= 0.) k += 2;
1926 if (a_nz <= 0) k += 4;
1927 if (a_nphi <= 0) k += 4;
1929 double tout = ::tan(a_st_in);
1930 double tin = ::tan(a_st_out);
1932 double d_in = a_rmin*a_rmin + tin*tin*a_dz*a_dz;
1933 double d_out = a_rmax*a_rmax + tout*tout*a_dz*a_dz;
1934 if(d_in>d_out) k += 8;
1937 double dphi = wholeCircle;
1940 #ifdef TOOLS_HEP_PH_OUT_ERR
1941 std::cerr << "polyhedron_cone(s)/Tube(s): error in input parameters";
1942 if ((k & 1) != 0) std::cerr << " (radiuses)";
1943 if ((k & 2) != 0) std::cerr << " (half-length)";
1944 if ((k & 4) != 0) std::cerr << " (steps)";
1945 if ((k & 8) != 0) std::cerr << " (angles)";
1946 std::cerr << std::endl;
1947 //std::cerr << " Rmn1=" << Rmn1 << " Rmx1=" << Rmx1;
1948 //std::cerr << " Rmn2=" << Rmn2 << " Rmx2=" << Rmx2;
1949 //std::cerr << " Dz=" << Dz << " Phi1=" << Phi1 << " Dphi=" << Dphi
1955 // P R E P A R E T W O P O L Y L I N E S
1957 double* zz = new double[2*(a_nz+1)];
1958 double* rr = new double[2*(a_nz+1)];
1960 double dz = 2.0f*a_dz/double(a_nz);
1964 // r^2 - (tout*z)^2 = rout^2
1965 double rout_sq = a_rmax*a_rmax;
1966 double tout_sq = tout*tout;
1967 for(int iz=0;iz<=a_nz;iz++) {
1970 rr[iz] = ::sqrt(rout_sq+tout_sq*z*z);
1973 // r^2 - (tin*z)^2 = rin^2
1974 double rin_sq = a_rmin*a_rmin;
1975 double tin_sq = tin*tin;
1976 for(int iz=0;iz<a_nz;iz++) {
1979 rr[a_nz+iz] = ::sqrt(rin_sq+tin_sq*z*z);
1982 // R O T A T E P O L Y L I N E S
1984 RotateAroundZ(a_nphi, phi1, dphi, a_nz, a_nz, zz, rr, -1, -1);
1993 polyhedron_hype::polyhedron_hype(double a_st_in,double a_st_out,
1994 double a_rmin,double a_rmax,double a_dz,
1995 int a_nz,int a_nphi) {
1996 set_polyhedron_hype(a_st_in,a_st_out,a_rmin,a_rmax,a_dz,a_nz,a_nphi);
2001 bool polyhedron::set_polyhedron_eltu(double a_dx,double a_dy,double a_dz,
2002 int a_nz,int a_nphi) //G.Barrand
2004 // elliptical tube class. An elliptical tube has 3 parameters :
2005 // a_dx - semi-axis of the ellipse along x
2006 // a_dy - semi-axis of the ellipse along y
2007 // a_dz - half length in z
2008 static const double wholeCircle = 2*_M_PI(); //G.Barrand : const
2010 _clear(); //G.Barrand
2012 // C H E C K I N P U T P A R A M E T E R S
2016 if (a_dx <= 0.) k += 1;
2017 if (a_dy <= 0.) k += 1;
2018 if (a_dz <= 0.) k += 1;
2020 if (a_nz <= 0) k += 2;
2021 if (a_nphi <= 0) k += 2;
2024 #ifdef TOOLS_HEP_PH_OUT_ERR
2025 std::cerr << "polyhedron_cone(s)/Tube(s): error in input parameters";
2026 if ((k & 1) != 0) std::cerr << " (half-length)";
2027 if ((k & 2) != 0) std::cerr << " (steps)";
2028 std::cerr << std::endl;
2029 std::cerr << " Dx=" << a_dx
2033 << " nphi=" << a_nphi
2039 // C O U N T V E R T E C E S
2043 int j = a_nz*a_nphi+2;
2045 // C O U N T F A C E S
2047 k = ((a_nz-1)+1+1)*a_nphi;
2049 // A L L O C A T E M E M O R Y
2051 AllocateMemory(j, k);
2053 // G E N E R A T E V E R T E C E S
2055 int* kk = new int[a_nz+2];
2058 for(i=0; i<a_nz; i++) {
2067 {double a2 = a_dx*a_dx;
2068 double b2 = a_dy*a_dy;
2069 double dphi = wholeCircle/a_nphi;
2071 double sph,cph,r2,r,x,y;
2072 double sz = (2.0*a_dz)/a_nz;
2073 for(j=0; j<a_nphi; j++) {
2077 r2=(a2*b2)/(b2+(a2-b2)*sph*sph);
2081 for(i=0; i<a_nz; i++) {
2082 pV[kk[i]+j] = HVPoint3D(x,y,a_dz-sz*i);
2086 pV[kk[a_nz]] = HVPoint3D(0,0,a_dz);
2087 pV[kk[a_nz+1]] = HVPoint3D(0,0,-a_dz);
2089 // G E N E R A T E E X T E R N A L F A C E S
2095 for(i=0; i<(a_nz-1); i++) {
2096 RotateEdge(kk[i], kk[i+1], 1, 1, v1, v2,
2097 edgeVis, true, a_nphi, k);
2100 // G E N E R A T E S I D E F A C E S
2102 RotateEdge(kk[a_nz], kk[0], 0, 1, 1, 1,
2103 -1, true, a_nphi, k);
2105 RotateEdge(kk[a_nz-1], kk[a_nz+1], 1, 0, 1, 1,
2106 -1, true, a_nphi, k);
2110 if ((k-1) != nface) {
2111 #ifdef TOOLS_HEP_PH_OUT_ERR
2113 << "Polyhedron::RotateAroundZ: number of generated faces ("
2114 << k-1 << ") is not equal to the number of allocated faces ("
2125 polyhedron_trd1::polyhedron_trd1(double Dx1, double Dx2,
2126 double Dy, double Dz)
2127 : polyhedron_trd2(Dx1, Dx2, Dy, Dy, Dz) {}
2130 polyhedron_box::polyhedron_box(double Dx, double Dy, double Dz)
2131 : polyhedron_trd2(Dx, Dx, Dy, Dy, Dz) {}
2135 bool polyhedron::set_polyhedron_trap(double Dz,
2146 /***********************************************************************
2148 * Name: polyhedron_trap Date: 20.11.96 *
2149 * Author: E.Chernyaev Revised: *
2151 * Function: Create GEANT4 TRAP-trapezoid *
2153 * Input: DZ - half-length in Z *
2154 * Theta,Phi - polar angles of the line joining centres of the *
2155 * faces at Z=-Dz and Z=+Dz *
2156 * Dy1 - half-length in Y of the face at Z=-Dz *
2157 * Dx1 - half-length in X of low edge of the face at Z=-Dz *
2158 * Dx2 - half-length in X of top edge of the face at Z=-Dz *
2159 * Alp1 - angle between Y-axis and the median joining top and *
2160 * low edges of the face at Z=-Dz *
2161 * Dy2 - half-length in Y of the face at Z=+Dz *
2162 * Dx3 - half-length in X of low edge of the face at Z=+Dz *
2163 * Dx4 - half-length in X of top edge of the face at Z=+Dz *
2164 * Alp2 - angle between Y-axis and the median joining top and *
2165 * low edges of the face at Z=+Dz *
2167 ***********************************************************************/
2169 _clear(); //G.Barrand
2171 //FIXME : check capacity = 0; //see TGeoTrap to set a arb8.
2173 if(//(Dx1<=0.0)||(Dx2<=0.0)||(Dx3<=0.0)||(Dx4<=0.0)||
2174 //(Dy1<=0.0)||(Dy2<=0.0)||
2175 (Dz<=0.0)){ //G.Barrand
2176 #ifdef TOOLS_HEP_PH_OUT_ERR
2177 std::cerr << "set_polyhedron_trap: error in input parameters";
2178 std::cerr << " Dx1=" << Dx1
2188 double DzTthetaCphi = Dz*tan(Theta)*cos(Phi);
2189 double DzTthetaSphi = Dz*tan(Theta)*sin(Phi);
2190 double Dy1Talp1 = Dy1*tan(Alp1);
2191 double Dy2Talp2 = Dy2*tan(Alp2);
2193 AllocateMemory(8,6);
2195 pV[1] = HVPoint3D(-DzTthetaCphi-Dy1Talp1-Dx1,-DzTthetaSphi-Dy1,-Dz);
2196 pV[2] = HVPoint3D(-DzTthetaCphi-Dy1Talp1+Dx1,-DzTthetaSphi-Dy1,-Dz);
2197 pV[3] = HVPoint3D(-DzTthetaCphi+Dy1Talp1+Dx2,-DzTthetaSphi+Dy1,-Dz);
2198 pV[4] = HVPoint3D(-DzTthetaCphi+Dy1Talp1-Dx2,-DzTthetaSphi+Dy1,-Dz);
2199 pV[5] = HVPoint3D( DzTthetaCphi-Dy2Talp2-Dx3, DzTthetaSphi-Dy2, Dz);
2200 pV[6] = HVPoint3D( DzTthetaCphi-Dy2Talp2+Dx3, DzTthetaSphi-Dy2, Dz);
2201 pV[7] = HVPoint3D( DzTthetaCphi+Dy2Talp2+Dx4, DzTthetaSphi+Dy2, Dz);
2202 pV[8] = HVPoint3D( DzTthetaCphi+Dy2Talp2-Dx4, DzTthetaSphi+Dy2, Dz);
2210 polyhedron_trap::polyhedron_trap(double Dz,
2223 set_polyhedron_trap(Dz,Theta,Phi,Dy1,Dx1,Dx2,Alp1,Dy2,Dx3,Dx4,Alp2);
2227 polyhedron_para::polyhedron_para(double Dx, double Dy, double Dz,
2228 double Alpha, double Theta,
2230 : polyhedron_trap(Dz, Theta, Phi, Dy, Dx, Dx, Alpha, Dy, Dx, Dx, Alpha) {}
2232 //G.Barrand : have the below set_ to optimize exlib/sg/polyhedron setup.
2234 bool polyhedron::set_polyhedron_cons(double Rmn1,
2241 int nstep) //G.Barrand
2242 /***********************************************************************
2244 * Name: polyhedron_cons::polyhedron_cons Date: 15.12.96 *
2245 * Author: E.Chernyaev (IHEP/Protvino) Revised: 15.12.96 *
2247 * Function: Constructor for CONS, TUBS, CONE, TUBE *
2249 * Input: Rmn1, Rmx1 - inside and outside radiuses at -Dz *
2250 * Rmn2, Rmx2 - inside and outside radiuses at +Dz *
2251 * Dz - half length in Z *
2252 * Phi1 - starting angle of the segment *
2253 * Dphi - segment range *
2255 ***********************************************************************/
2257 static const double wholeCircle = 2*_M_PI(); //G.Barrand : const
2258 _clear(); //G.Barrand
2260 // C H E C K I N P U T P A R A M E T E R S
2263 if (Rmn1 < 0. || Rmx1 < 0. || Rmn2 < 0. || Rmx2 < 0.) k = 1;
2264 if (Rmn1 > Rmx1 || Rmn2 > Rmx2) k = 1;
2265 if (Rmn1 == Rmx1 && Rmn2 == Rmx2) k = 1;
2267 //G.Barrand : for atlas.root.
2268 //if (Dz <= 0.) k += 2;
2269 const double perMillion = 0.000001;
2270 if (Dz <= 0.) Dz = perMillion*mx<double>(Rmx1,Rmx2);
2272 double phi1, phi2, dphi;
2274 phi2 = Phi1; phi1 = phi2 - Dphi;
2275 }else if (Dphi == 0.) {
2276 phi1 = Phi1; phi2 = phi1 + wholeCircle;
2278 phi1 = Phi1; phi2 = phi1 + Dphi;
2282 if (fabs(dphi-wholeCircle) < perMillion) dphi = wholeCircle;
2283 if (dphi > wholeCircle) k += 4;
2286 #ifdef TOOLS_HEP_PH_OUT_ERR
2287 std::cerr << "polyhedron_cone(s)/Tube(s): error in input parameters";
2288 if ((k & 1) != 0) std::cerr << " (radiuses)";
2289 if ((k & 2) != 0) std::cerr << " (half-length)";
2290 if ((k & 4) != 0) std::cerr << " (angles)";
2291 std::cerr << std::endl;
2292 std::cerr << " Rmn1=" << Rmn1 << " Rmx1=" << Rmx1;
2293 std::cerr << " Rmn2=" << Rmn2 << " Rmx2=" << Rmx2;
2294 std::cerr << " Dz=" << Dz << " Phi1=" << Phi1 << " Dphi=" << Dphi
2300 // P R E P A R E T W O P O L Y L I N E S
2302 double zz[4], rr[4];
2312 // R O T A T E P O L Y L I N E S
2315 RotateAroundZ(nstep, phi1, dphi, 2, 2, zz, rr, -1, -1);
2322 polyhedron_cons::polyhedron_cons(double Rmn1,
2329 int nstep) //G.Barrand
2331 set_polyhedron_cons(Rmn1,Rmx1,Rmn2,Rmx2,Dz,Phi1,Dphi,nstep); //G.Barrand
2335 polyhedron_cone::polyhedron_cone(double Rmn1, double Rmx1,
2336 double Rmn2, double Rmx2,
2338 int nstep) //G.Barrand
2339 : polyhedron_cons(Rmn1, Rmx1, Rmn2, Rmx2, Dz, 0, 2*_M_PI(), nstep) {}
2342 polyhedron_tubs::polyhedron_tubs(double Rmin, double Rmax,
2344 double Phi1, double Dphi,
2345 int nstep) //G.Barrand
2346 : polyhedron_cons(Rmin, Rmax, Rmin, Rmax, Dz, Phi1, Dphi, nstep) {}
2349 polyhedron_tube::polyhedron_tube (double Rmin, double Rmax,
2351 int nstep) //G.Barrand
2352 : polyhedron_cons(Rmin, Rmax, Rmin, Rmax, Dz, 0, 2*_M_PI(), nstep) {}
2356 bool polyhedron::set_polyhedron_pgon(double phi,
2363 /***********************************************************************
2365 * Name: polyhedron_pgon Date: 09.12.96 *
2366 * Author: E.Chernyaev Revised: *
2368 * Function: Constructor of polyhedron for PGON, PCON *
2370 * Input: phi - initial phi *
2371 * dphi - delta phi *
2372 * npdv - number of steps along phi *
2373 * nz - number of z-planes (at least two) *
2374 * z[] - z coordinates of the slices *
2375 * rmin[] - smaller r at the slices *
2376 * rmax[] - bigger r at the slices *
2378 ***********************************************************************/
2382 // C H E C K I N P U T P A R A M E T E R S
2384 if (dphi <= 0. || dphi > 2*_M_PI()) {
2385 #ifdef TOOLS_HEP_PH_OUT_ERR
2387 << "polyhedron_pgon/Pcon: wrong delta phi = " << dphi
2394 #ifdef TOOLS_HEP_PH_OUT_ERR
2396 << "polyhedron_pgon/Pcon: number of z-planes less than two = " << nz
2403 #ifdef TOOLS_HEP_PH_OUT_ERR
2405 << "polyhedron_pgon/Pcon: error in number of phi-steps =" << npdv
2412 for (i=0; i<nz; i++) {
2413 if (rmin[i] < 0. || rmax[i] < 0. || rmin[i] > rmax[i]) {
2414 #ifdef TOOLS_HEP_PH_OUT_ERR
2416 << "polyhedron_pgon: error in radiuses rmin[" << i << "]="
2417 << rmin[i] << " rmax[" << i << "]=" << rmax[i]
2424 // P R E P A R E T W O P O L Y L I N E S
2427 zz = new double[2*nz];
2428 rr = new double[2*nz];
2430 if (z[0] > z[nz-1]) {
2431 for (i=0; i<nz; i++) {
2438 for (i=0; i<nz; i++) {
2440 rr[i] = rmax[nz-i-1];
2441 zz[i+nz] = z[nz-i-1];
2442 rr[i+nz] = rmin[nz-i-1];
2446 // R O T A T E P O L Y L I N E S
2448 RotateAroundZ(npdv, phi, dphi, nz, nz, zz, rr, -1, (npdv == 0) ? -1 : 1);
2458 polyhedron_pgon::polyhedron_pgon(double phi,
2466 set_polyhedron_pgon(phi,dphi,npdv,nz,z,rmin,rmax);
2470 polyhedron_pcon::polyhedron_pcon(double phi, double dphi, int nz,
2474 : polyhedron_pgon(phi, dphi, 0, nz, z, rmin, rmax) {}
2477 bool polyhedron::set_polyhedron_sphere(double rmin, double rmax,
2478 double phi, double dphi,
2479 double the, double dthe,
2480 int nphi, //G.Barrand
2481 int nthe) //G.Barrand
2482 /***********************************************************************
2484 * Name: polyhedron_sphere Date: 11.12.96 *
2485 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
2487 * Function: Constructor of polyhedron for SPHERE *
2489 * Input: rmin - internal radius *
2490 * rmax - external radius *
2491 * phi - initial phi *
2492 * dphi - delta phi *
2493 * the - initial theta *
2494 * dthe - delta theta *
2496 ***********************************************************************/
2500 // C H E C K I N P U T P A R A M E T E R S
2502 if (dphi <= 0. || dphi > 2*_M_PI()) {
2503 #ifdef TOOLS_HEP_PH_OUT_ERR
2505 << "polyhedron_sphere: wrong delta phi = " << dphi
2511 if (the < 0. || the > _M_PI()) {
2512 #ifdef TOOLS_HEP_PH_OUT_ERR
2514 << "polyhedron_sphere: wrong theta = " << the
2520 if (dthe <= 0. || dthe > _M_PI()) {
2521 #ifdef TOOLS_HEP_PH_OUT_ERR
2523 << "polyhedron_sphere: wrong delta theta = " << dthe
2529 if ( (the+dthe >= _M_PI()) && (the+dthe < _M_PI() + 2*DBL_EPSILON) )
2530 dthe = _M_PI() - the; //G.Barrand : coming from LHCb/S.Ponce.
2532 if (the+dthe > _M_PI()) {
2533 #ifdef TOOLS_HEP_PH_OUT_ERR
2535 << "polyhedron_sphere: wrong theta + delta theta = "
2536 << the << " " << dthe
2542 if (rmin < 0. || rmin >= rmax) {
2543 #ifdef TOOLS_HEP_PH_OUT_ERR
2545 << "polyhedron_sphere: error in radiuses"
2546 << " rmin=" << rmin << " rmax=" << rmax
2552 // P R E P A R E T W O P O L Y L I N E S
2554 int n_the = (nthe>0) ? nthe : GetNumberOfRotationSteps(); //G.Barrand.
2555 int ns = (n_the + 1) / 2;
2557 int np1 = int(dthe*ns/_M_PI()+.5) + 1;
2558 if (np1 <= 1) np1 = 2;
2559 const double perMillion = 0.000001;
2560 int np2 = rmin < perMillion ? 1 : np1;
2563 zz = new double[np1+np2];
2564 rr = new double[np1+np2];
2566 double a = dthe/(np1-1);
2568 for (int i=0; i<np1; i++) {
2569 cosa = cos(the+i*a);
2570 sina = sin(the+i*a);
2574 zz[i+np1] = rmin*cosa;
2575 rr[i+np1] = rmin*sina;
2583 // R O T A T E P O L Y L I N E S
2586 RotateAroundZ(nphi, phi, dphi, np1, np2, zz, rr, -1, -1);
2596 polyhedron_sphere::polyhedron_sphere(double rmin, double rmax,
2597 double phi, double dphi,
2598 double the, double dthe,
2599 int nphi, //G.Barrand
2600 int nthe) //G.Barrand
2602 set_polyhedron_sphere(rmin,rmax,
2610 bool polyhedron::set_polyhedron_torus(double rmin,
2615 int nphi, //G.Barrand
2616 int nthe) //G.Barrand
2617 /***********************************************************************
2619 * Name: polyhedron_torus Date: 11.12.96 *
2620 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
2622 * Function: Constructor of polyhedron for TORUS *
2624 * Input: rmin - internal radius *
2625 * rmax - external radius *
2626 * rtor - radius of torus *
2627 * phi - initial phi *
2628 * dphi - delta phi *
2630 ***********************************************************************/
2634 // C H E C K I N P U T P A R A M E T E R S
2636 if (dphi <= 0. || dphi > 2*_M_PI()) {
2637 #ifdef TOOLS_HEP_PH_OUT_ERR
2639 << "polyhedron_torus: wrong delta phi = " << dphi
2645 if (rmin < 0. || rmin >= rmax || rmax >= rtor) {
2646 #ifdef TOOLS_HEP_PH_OUT_ERR
2648 << "polyhedron_torus: error in radiuses"
2649 << " rmin=" << rmin << " rmax=" << rmax << " rtorus=" << rtor
2655 // P R E P A R E T W O P O L Y L I N E S
2657 int n_the = (nthe>0) ? nthe : GetNumberOfRotationSteps(); //G.Barrand.
2660 const double perMillion = 0.000001;
2661 int np2 = rmin < perMillion ? 1 : np1;
2664 zz = new double[np1+np2];
2665 rr = new double[np1+np2];
2667 double a = 2*_M_PI()/np1;
2669 for (int i=0; i<np1; i++) {
2673 rr[i] = rtor+rmax*sina;
2675 zz[i+np1] = rmin*cosa;
2676 rr[i+np1] = rtor+rmin*sina;
2685 // R O T A T E P O L Y L I N E S
2688 RotateAroundZ(nphi, phi, dphi, -np1, -np2, zz, rr, -1,-1);
2698 polyhedron_torus::polyhedron_torus(double rmin,
2703 int nphi, //G.Barrand
2704 int nthe) //G.Barrand
2706 set_polyhedron_torus(rmin,rmax,rtor,phi,dphi,nphi,nthe); //G.Barrand
2709 //int polyhedron::fNumberOfRotationSteps = NUMBER_OF_STEPS;
2711 // G.Barrand : begin.
2712 inline int polyhedron::GetNumberOfRotationSteps() {
2713 return fNumberOfRotationSteps;
2715 inline void polyhedron::ResetNumberOfRotationSteps() {
2716 fNumberOfRotationSteps = NUMBER_OF_STEPS();
2719 /***********************************************************************
2721 * Name: polyhedron::fNumberOfRotationSteps Date: 24.06.97 *
2722 * Author: J.Allison (Manchester University) Revised: *
2724 * Function: Number of steps for whole circle *
2726 ***********************************************************************/
2730 #include "pbp.icc" //BooleanProcessor
2735 //G.Barrand : static BooleanProcessor processor;
2737 inline polyhedron polyhedron::add(const polyhedron & p) const
2738 /***********************************************************************
2740 * Name: polyhedron::add Date: 19.03.00 *
2741 * Author: E.Chernyaev Revised: *
2743 * Function: Boolean "union" of two polyhedra *
2745 ***********************************************************************/
2747 BooleanProcessor processor; //G.Barrand
2749 return processor.execute(OP_UNION, *this, p, err);
2752 inline polyhedron polyhedron::intersect(const polyhedron & p) const
2753 /***********************************************************************
2755 * Name: polyhedron::intersect Date: 19.03.00 *
2756 * Author: E.Chernyaev Revised: *
2758 * Function: Boolean "intersection" of two polyhedra *
2760 ***********************************************************************/
2762 BooleanProcessor processor; //G.Barrand
2764 return processor.execute(OP_INTERSECTION, *this, p, err);
2767 inline polyhedron polyhedron::subtract(const polyhedron & p) const
2768 /***********************************************************************
2770 * Name: polyhedron::add Date: 19.03.00 *
2771 * Author: E.Chernyaev Revised: *
2773 * Function: Boolean "subtraction" of "p" from "this" *
2775 ***********************************************************************/
2777 BooleanProcessor processor; //G.Barrand
2779 return processor.execute(OP_SUBTRACTION, *this, p, err);
2785 inline bool is_in(unsigned int a_index,
2786 const std::list<unsigned int>& a_is) {
2787 std::list<unsigned int>::const_iterator it;
2788 for(it=a_is.begin();it!=a_is.end();++it) {
2789 if(*it==a_index) return true;
2794 class bijection_visitor {
2796 TOOLS_SCLASS(tools::hep::bijection_visitor)
2799 typedef std::vector<unsigned int> is_t;
2800 virtual bool visit(const is_t&) = 0;
2802 bijection_visitor(unsigned int a_number):m_number(a_number){
2804 mem::increment(s_class().c_str());
2807 virtual ~bijection_visitor(){
2809 mem::decrement(s_class().c_str());
2813 bijection_visitor(const bijection_visitor&){
2815 mem::increment(s_class().c_str());
2818 bijection_visitor& operator=(const bijection_visitor&){return *this;}
2822 m_is.resize(m_number,0);
2823 std::list<unsigned int> is;
2827 bool visit(unsigned int a_level,std::list<unsigned int>& a_is) {
2828 for(unsigned int index=0;index<m_number;index++) {
2829 if(is_in(index,a_is)) {
2831 a_is.push_back(index);
2832 m_is[a_level] = index;
2833 if(a_level==m_number-1) {
2834 if(!visit(m_is)) return false;
2836 if(!visit(a_level+1,a_is)) return false;
2844 unsigned int m_number;
2848 //inline void dump(const std::vector<unsigned int>& a_is) {
2849 // unsigned int number = a_is.size();
2850 // for(unsigned int index=0;index<number;index++) {
2851 // printf("%d ",a_is[index]);
2856 //class bijection_dump : public bijection_visitor {
2858 // bijection_dump(unsigned int a_number)
2859 // : bijection_visitor(a_number)
2861 // virtual bool visit(const is_t& a_is) {
2863 // return true;//continue
2867 class polyhedron_exec : public bijection_visitor {
2869 TOOLS_SCLASS(tools::hep::polyhedron_exec)
2872 polyhedron_exec(unsigned int a_number,
2873 polyhedronProcessor& a_proc,
2875 : bijection_visitor(a_number)
2880 mem::increment(s_class().c_str());
2883 virtual ~polyhedron_exec(){
2885 mem::decrement(s_class().c_str());
2889 polyhedron_exec(const polyhedron_exec& a_from)
2890 :bijection_visitor(a_from)
2891 ,m_proc(a_from.m_proc)
2892 ,m_poly(a_from.m_poly)
2895 mem::increment(s_class().c_str());
2898 polyhedron_exec& operator=(const polyhedron_exec&){return *this;}
2900 virtual bool visit(const is_t& a_is) {
2901 if(m_proc.execute1(m_poly,a_is)==true) return false; //stop
2902 return true;//continue
2905 polyhedronProcessor& m_proc;
2909 inline bool polyhedronProcessor::execute(polyhedron& a_poly) {
2910 //{for(unsigned int index=0;index<5;index++) {
2911 // printf("debug : bijection : %d\n",index);
2912 // bijection_dump bd(index);
2916 polyhedron_exec e((unsigned int)m_ops.size(),*this,a_poly);
2917 if(!e.visitx()) return true;
2918 #ifdef TOOLS_HEP_PH_OUT_ERR
2919 //std::cerr << "polyhedronProcessor::execute :"
2920 // << " all shifts and combinatory tried."
2921 // << " Boolean operations failed."
2926 inline bool polyhedronProcessor::execute1(
2928 ,const std::vector<unsigned int>& a_is
2930 polyhedron result(a_poly);
2931 size_t number = m_ops.size();
2932 int num_shift = BooleanProcessor::get_num_shift();
2933 for(int ishift=0;ishift<num_shift;ishift++) {
2934 BooleanProcessor::set_shift(ishift);
2938 for(size_t index=0;index<number;index++) {
2939 BooleanProcessor processor; //take a fresh one.
2940 const op_t& elem = m_ops[a_is[index]];
2942 result = processor.execute(elem.first,result,elem.second,err);
2954 #ifdef TOOLS_HEP_PH_OUT_ERR
2955 //std::cerr << "polyhedronProcessor::execute :"
2956 // << " all shifts tried. Boolean operations failed."