ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4UGenericTrap.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4UGenericTrap.cc
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 // Implementation of G4UGenericTrap wrapper class
27 //
28 // 30.10.13 G.Cosmo, CERN
29 // --------------------------------------------------------------------
30 
31 #include "G4GenericTrap.hh"
32 #include "G4UGenericTrap.hh"
33 
34 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
35 
36 #include "G4AffineTransform.hh"
37 #include "G4VPVParameterisation.hh"
38 #include "G4BoundingEnvelope.hh"
39 
40 #include "G4Polyhedron.hh"
41 #include "G4PolyhedronArbitrary.hh"
42 
43 using namespace CLHEP;
44 
46 //
47 // Constructor (generic parameters)
48 //
49 G4UGenericTrap::G4UGenericTrap(const G4String& name, G4double halfZ,
50  const std::vector<G4TwoVector>& vertices)
51  : Base_t(name), fVisSubdivisions(0)
52 {
53  SetZHalfLength(halfZ);
54  Initialise(vertices);
55 }
56 
57 
59 //
60 // Fake default constructor - sets only member data and allocates memory
61 // for usage restricted to object persistency.
62 //
63 G4UGenericTrap::G4UGenericTrap(__void__& a)
64  : Base_t(a), fVisSubdivisions(0), fVertices()
65 {
66 }
67 
68 
70 //
71 // Destructor
72 //
73 G4UGenericTrap::~G4UGenericTrap()
74 {
75 }
76 
77 
79 //
80 // Copy constructor
81 //
82 G4UGenericTrap::G4UGenericTrap(const G4UGenericTrap& source)
83  : Base_t(source), fVisSubdivisions(source.fVisSubdivisions),
84  fVertices(source.fVertices)
85 
86 {
87 }
88 
89 
91 //
92 // Assignment operator
93 //
94 G4UGenericTrap&
95 G4UGenericTrap::operator=(const G4UGenericTrap& source)
96 {
97  if (this == &source) return *this;
98 
99  Base_t::operator=( source );
100  fVertices = source.fVertices;
101  fVisSubdivisions = source.fVisSubdivisions;
102 
103  return *this;
104 }
105 
107 //
108 // Accessors & modifiers
109 //
110 G4double G4UGenericTrap::GetZHalfLength() const
111 {
112  return GetDZ();
113 }
114 G4int G4UGenericTrap::GetNofVertices() const
115 {
116  return fVertices.size();
117 }
118 G4TwoVector G4UGenericTrap::GetVertex(G4int index) const
119 {
120  return G4TwoVector(GetVerticesX()[index], GetVerticesY()[index]);
121 }
122 const std::vector<G4TwoVector>& G4UGenericTrap::GetVertices() const
123 {
124  return fVertices;
125 }
126 G4double G4UGenericTrap::GetTwistAngle(G4int index) const
127 {
128  return GetTwist(index);
129 }
130 G4bool G4UGenericTrap::IsTwisted() const
131 {
132  return !IsPlanar();
133 }
134 G4int G4UGenericTrap::GetVisSubdivisions() const
135 {
136  return fVisSubdivisions;
137 }
138 
139 void G4UGenericTrap::SetVisSubdivisions(G4int subdiv)
140 {
141  fVisSubdivisions = subdiv;
142 }
143 
144 void G4UGenericTrap::SetZHalfLength(G4double halfZ)
145 {
146  SetDZ(halfZ);
147 }
148 
149 void G4UGenericTrap::Initialise(const std::vector<G4TwoVector>& v)
150 {
151  G4double verticesx[8], verticesy[8];
152  for (G4int i=0; i<8; ++i)
153  {
154  fVertices.push_back(v[i]);
155  verticesx[i] = v[i].x();
156  verticesy[i] = v[i].y();
157  }
158  Initialize(verticesx, verticesy, GetZHalfLength());
159 }
160 
162 //
163 // Get bounding box
164 
165 void G4UGenericTrap::BoundingLimits(G4ThreeVector& pMin,
166  G4ThreeVector& pMax) const
167 {
168  U3Vector vmin, vmax;
169  Extent(vmin,vmax);
170  pMin.set(vmin.x(),vmin.y(),vmin.z());
171  pMax.set(vmax.x(),vmax.y(),vmax.z());
172 
173  // Check correctness of the bounding box
174  //
175  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
176  {
177  std::ostringstream message;
178  message << "Bad bounding box (min >= max) for solid: "
179  << GetName() << " !"
180  << "\npMin = " << pMin
181  << "\npMax = " << pMax;
182  G4Exception("G4UGenericTrap::BoundingLimits()", "GeomMgt0001",
183  JustWarning, message);
184  StreamInfo(G4cout);
185  }
186 }
187 
189 //
190 // Calculate extent under transform and specified limit
191 
192 G4bool
193 G4UGenericTrap::CalculateExtent(const EAxis pAxis,
194  const G4VoxelLimits& pVoxelLimit,
195  const G4AffineTransform& pTransform,
196  G4double& pMin, G4double& pMax) const
197 {
198  G4ThreeVector bmin, bmax;
199  G4bool exist;
200 
201  // Check bounding box (bbox)
202  //
203  BoundingLimits(bmin,bmax);
204  G4BoundingEnvelope bbox(bmin,bmax);
205 #ifdef G4BBOX_EXTENT
206  return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
207 #endif
208  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
209  {
210  return exist = (pMin < pMax) ? true : false;
211  }
212 
213  // Set bounding envelope (benv) and calculate extent
214  //
215  // To build the bounding envelope with plane faces each side face of
216  // the trapezoid is subdivided in triangles. Subdivision is done by
217  // duplication of vertices in the bases in a way that the envelope be
218  // a convex polyhedron (some faces of the envelope can be degenerate)
219  //
220  G4double dz = GetZHalfLength();
221  G4ThreeVectorList baseA(8), baseB(8);
222  for (G4int i=0; i<4; ++i)
223  {
224  G4TwoVector va = GetVertex(i);
225  G4TwoVector vb = GetVertex(i+4);
226  baseA[2*i].set(va.x(),va.y(),-dz);
227  baseB[2*i].set(vb.x(),vb.y(), dz);
228  }
229  for (G4int i=0; i<4; ++i)
230  {
231  G4int k1=2*i, k2=(2*i+2)%8;
232  G4double ax = (baseA[k2].x()-baseA[k1].x());
233  G4double ay = (baseA[k2].y()-baseA[k1].y());
234  G4double bx = (baseB[k2].x()-baseB[k1].x());
235  G4double by = (baseB[k2].y()-baseB[k1].y());
236  G4double znorm = ax*by - ay*bx;
237  baseA[k1+1] = (znorm < 0.0) ? baseA[k2] : baseA[k1];
238  baseB[k1+1] = (znorm < 0.0) ? baseB[k1] : baseB[k2];
239  }
240 
241  std::vector<const G4ThreeVectorList *> polygons(2);
242  polygons[0] = &baseA;
243  polygons[1] = &baseB;
244 
245  G4BoundingEnvelope benv(bmin,bmax,polygons);
246  exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
247  return exist;
248 }
249 
251 //
252 // CreatePolyhedron()
253 //
254 G4Polyhedron* G4UGenericTrap::CreatePolyhedron() const
255 {
256  // Approximation of Twisted Side
257  // Construct extra Points, if Twisted Side
258  //
259  G4PolyhedronArbitrary* polyhedron;
260  size_t nVertices, nFacets;
261  G4double fDz = GetZHalfLength();
262 
263  G4int subdivisions=0;
264  G4int i;
265  if(IsTwisted())
266  {
267  if ( GetVisSubdivisions() != 0 )
268  {
269  subdivisions=GetVisSubdivisions();
270  }
271  else
272  {
273  // Estimation of Number of Subdivisions for smooth visualisation
274  //
275  G4double maxTwist=0.;
276  for(i=0; i<4; ++i)
277  {
278  if(GetTwistAngle(i)>maxTwist) { maxTwist=GetTwistAngle(i); }
279  }
280 
281  // Computes bounding vectors for the shape
282  //
283  G4double Dx,Dy;
284  G4ThreeVector minVec, maxVec;
285  BoundingLimits(minVec,maxVec);
286  Dx = 0.5*(maxVec.x()- minVec.y());
287  Dy = 0.5*(maxVec.y()- minVec.y());
288  if (Dy > Dx) { Dx=Dy; }
289 
290  subdivisions=8*G4int(maxTwist/(Dx*Dx*Dx)*fDz);
291  if (subdivisions<4) { subdivisions=4; }
292  if (subdivisions>30) { subdivisions=30; }
293  }
294  }
295  G4int sub4=4*subdivisions;
296  nVertices = 8+subdivisions*4;
297  nFacets = 6+subdivisions*4;
298  G4double cf=1./(subdivisions+1);
299  polyhedron = new G4PolyhedronArbitrary (nVertices, nFacets);
300 
301  // Add Vertex
302  //
303  for (i=0; i<4; ++i)
304  {
305  polyhedron->AddVertex(G4ThreeVector(GetVertex(i).x(),
306  GetVertex(i).y(),-fDz));
307  }
308  for(i=0; i<subdivisions; ++i)
309  {
310  for(G4int j=0; j<4 ; ++j)
311  {
312  G4TwoVector u=GetVertex(j)+cf*(i+1)*( GetVertex(j+4)-GetVertex(j));
313  polyhedron->AddVertex(G4ThreeVector(u.x(),u.y(),-fDz+cf*2*fDz*(i+1)));
314  }
315  }
316  for (i=4; i<8; ++i)
317  {
318  polyhedron->AddVertex(G4ThreeVector(GetVertex(i).x(),
319  GetVertex(i).y(),fDz));
320  }
321 
322  // Add Facets
323  //
324  polyhedron->AddFacet(1,4,3,2); //Z-plane
325  for (i=0; i<subdivisions+1; ++i)
326  {
327  G4int is=i*4;
328  polyhedron->AddFacet(5+is,8+is,4+is,1+is);
329  polyhedron->AddFacet(8+is,7+is,3+is,4+is);
330  polyhedron->AddFacet(7+is,6+is,2+is,3+is);
331  polyhedron->AddFacet(6+is,5+is,1+is,2+is);
332  }
333  polyhedron->AddFacet(5+sub4,6+sub4,7+sub4,8+sub4); //Z-plane
334 
335  polyhedron->SetReferences();
336  polyhedron->InvertFacets();
337 
338  return (G4Polyhedron*) polyhedron;
339 }
340 
341 #endif // G4GEOM_USE_USOLIDS