Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4PVPlacement.cc
Go to the documentation of this file.
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$
28 //
29 //
30 // class G4PVPlacement Implementation
31 //
32 // ----------------------------------------------------------------------
33 
34 #include "G4PVPlacement.hh"
35 #include "G4AffineTransform.hh"
36 #include "G4UnitsTable.hh"
37 #include "G4LogicalVolume.hh"
38 #include "G4VSolid.hh"
39 
40 // ----------------------------------------------------------------------
41 // Constructor
42 //
44  const G4ThreeVector &tlate,
45  const G4String& pName,
46  G4LogicalVolume *pLogical,
47  G4VPhysicalVolume *pMother,
48  G4bool pMany,
49  G4int pCopyNo,
50  G4bool pSurfChk )
51  : G4VPhysicalVolume(pRot,tlate,pName,pLogical,pMother),
52  fmany(pMany), fallocatedRotM(false), fcopyNo(pCopyNo)
53 {
54  if (pMother)
55  {
56  G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
57  if (pLogical == motherLogical)
58  {
59  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
60  FatalException, "Cannot place a volume inside itself!");
61  }
62  SetMotherLogical(motherLogical);
63  motherLogical->AddDaughter(this);
64  if (pSurfChk) { CheckOverlaps(); }
65  }
66 }
67 
68 // ----------------------------------------------------------------------
69 // Constructor
70 //
72  const G4String& pName,
73  G4LogicalVolume *pLogical,
74  G4VPhysicalVolume *pMother,
75  G4bool pMany,
76  G4int pCopyNo,
77  G4bool pSurfChk )
78  : G4VPhysicalVolume(NewPtrRotMatrix(Transform3D.getRotation().inverse()),
79  Transform3D.getTranslation(),pName,pLogical,pMother),
80  fmany(pMany), fcopyNo(pCopyNo)
81 {
82  fallocatedRotM = (GetRotation() != 0);
83  if (pMother)
84  {
85  G4LogicalVolume* motherLogical = pMother->GetLogicalVolume();
86  if (pLogical == motherLogical)
87  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
88  FatalException, "Cannot place a volume inside itself!");
89  SetMotherLogical(motherLogical);
90  motherLogical->AddDaughter(this);
91  if (pSurfChk) { CheckOverlaps(); }
92  }
93 }
94 
95 // ----------------------------------------------------------------------
96 // Constructor
97 //
98 // The logical volume of the mother is utilised (not the physical)
99 //
101  const G4ThreeVector &tlate,
102  G4LogicalVolume *pCurrentLogical,
103  const G4String& pName,
104  G4LogicalVolume *pMotherLogical,
105  G4bool pMany,
106  G4int pCopyNo,
107  G4bool pSurfChk )
108  : G4VPhysicalVolume(pRot,tlate,pName,pCurrentLogical,0),
109  fmany(pMany), fallocatedRotM(false), fcopyNo(pCopyNo)
110 {
111  if (pCurrentLogical == pMotherLogical)
112  {
113  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
114  FatalException, "Cannot place a volume inside itself!");
115  }
116  SetMotherLogical(pMotherLogical);
117  if (pMotherLogical) { pMotherLogical->AddDaughter(this); }
118  if ((pSurfChk) && (pMotherLogical)) { CheckOverlaps(); }
119 }
120 
121 
122 // ----------------------------------------------------------------------
123 // Constructor
124 //
126  G4LogicalVolume *pCurrentLogical,
127  const G4String& pName,
128  G4LogicalVolume *pMotherLogical,
129  G4bool pMany,
130  G4int pCopyNo,
131  G4bool pSurfChk )
132  : G4VPhysicalVolume(0,Transform3D.getTranslation(),pName,pCurrentLogical,0),
133  fmany(pMany), fcopyNo(pCopyNo)
134 {
135  if (pCurrentLogical == pMotherLogical)
136  {
137  G4Exception("G4PVPlacement::G4PVPlacement()", "GeomVol0002",
138  FatalException, "Cannot place a volume inside itself!");
139  }
140  SetRotation( NewPtrRotMatrix(Transform3D.getRotation().inverse()) );
141  fallocatedRotM = (GetRotation() != 0);
142  SetMotherLogical(pMotherLogical);
143  if (pMotherLogical) { pMotherLogical->AddDaughter(this); }
144  if ((pSurfChk) && (pMotherLogical)) { CheckOverlaps(); }
145 }
146 
147 // ----------------------------------------------------------------------
148 // Fake default constructor - sets only member data and allocates memory
149 // for usage restricted to object persistency.
150 //
152  : G4VPhysicalVolume(a), fmany(false), fallocatedRotM(0), fcopyNo(0)
153 {
154 }
155 
156 // ----------------------------------------------------------------------
157 // Destructor
158 //
160 {
161  if( fallocatedRotM ){ delete frot; }
162 }
163 
164 // ----------------------------------------------------------------------
165 // IsMany
166 //
168 {
169  return fmany;
170 }
171 
172 // ----------------------------------------------------------------------
173 // GetCopyNo
174 //
176 {
177  return fcopyNo;
178 }
179 
180 // ----------------------------------------------------------------------
181 // SetCopyNo
182 //
184 {
185  fcopyNo= newCopyNo;
186 }
187 
188 // ----------------------------------------------------------------------
189 // IsReplicated
190 //
192 {
193  return false;
194 }
195 
196 // ----------------------------------------------------------------------
197 // IsParameterised
198 //
200 {
201  return false;
202 }
203 
204 // ----------------------------------------------------------------------
205 // GetParameterisation
206 //
208 {
209  return 0;
210 }
211 
212 // ----------------------------------------------------------------------
213 // GetReplicationData
214 //
215 void G4PVPlacement::
217 {
218  // No-operations
219 }
220 
221 // ----------------------------------------------------------------------
222 // IsRegularRepeatedStructure
223 //
224 // This is for specialised repeated volumes (replicas, parameterised vol.)
225 //
227 {
228  return false;
229 }
230 
231 // ----------------------------------------------------------------------
232 // IsRegularRepeatedStructure
233 //
234 // This is for specialised repeated volumes (replicas, parameterised vol.)
235 //
237 {
238  return 0;
239 }
240 
241 // ----------------------------------------------------------------------
242 // CheckOverlaps
243 //
245 {
246  if (res<=0) { return false; }
247 
248  G4VSolid* solid = GetLogicalVolume()->GetSolid();
249  G4LogicalVolume* motherLog = GetMotherLogical();
250  if (!motherLog) { return false; }
251 
252  G4VSolid* motherSolid = motherLog->GetSolid();
253 
254  if (verbose)
255  {
256  G4cout << "Checking overlaps for volume " << GetName() << " ... ";
257  }
258 
259  // Create the transformation from daughter to mother
260  //
262 
263  for (G4int n=0; n<res; n++)
264  {
265  // Generate a random point on the solid's surface
266  //
267  G4ThreeVector point = solid->GetPointOnSurface();
268 
269  // Transform the generated point to the mother's coordinate system
270  //
271  G4ThreeVector mp = Tm.TransformPoint(point);
272 
273  // Checking overlaps with the mother volume
274  //
275  if (motherSolid->Inside(mp)==kOutside)
276  {
277  G4double distin = motherSolid->DistanceToIn(mp);
278  if (distin > tol)
279  {
280  std::ostringstream message;
281  message << "Overlap with mother volume !" << G4endl
282  << " Overlap is detected for volume "
283  << GetName() << G4endl
284  << " with its mother volume "
285  << motherLog->GetName() << G4endl
286  << " at mother local point " << mp << ", "
287  << "overlapping by at least: "
288  << G4BestUnit(distin, "Length");
289  G4Exception("G4PVPlacement::CheckOverlaps()",
290  "GeomVol1002", JustWarning, message);
291  return true;
292  }
293  }
294 
295  // Checking overlaps with each 'sister' volume
296  //
297  for (G4int i=0; i<motherLog->GetNoDaughters(); i++)
298  {
299  G4VPhysicalVolume* daughter = motherLog->GetDaughter(i);
300 
301  if (daughter == this) { continue; }
302 
303  // Create the transformation for daughter volume and transform point
304  //
305  G4AffineTransform Td( daughter->GetRotation(),
306  daughter->GetTranslation() );
307  G4ThreeVector md = Td.Inverse().TransformPoint(mp);
308 
309  G4VSolid* daughterSolid = daughter->GetLogicalVolume()->GetSolid();
310  if (daughterSolid->Inside(md)==kInside)
311  {
312  G4double distout = daughterSolid->DistanceToOut(md);
313  if (distout > tol)
314  {
315  std::ostringstream message;
316  message << "Overlap with volume already placed !" << G4endl
317  << " Overlap is detected for volume "
318  << GetName() << G4endl
319  << " with " << daughter->GetName() << " volume's"
320  << G4endl
321  << " local point " << md << ", "
322  << "overlapping by at least: "
323  << G4BestUnit(distout,"Length");
324  G4Exception("G4PVPlacement::CheckOverlaps()",
325  "GeomVol1002", JustWarning, message);
326  return true;
327  }
328  }
329 
330  // Now checking that 'sister' volume is not totally included and
331  // overlapping. Do it only once, for the first point generated
332  //
333  if (n==0)
334  {
335  // Generate a single point on the surface of the 'sister' volume
336  // and verify that the point is NOT inside the current volume
337 
338  G4ThreeVector dPoint = daughterSolid->GetPointOnSurface();
339 
340  // Transform the generated point to the mother's coordinate system
341  // and finally to current volume's coordinate system
342  //
343  G4ThreeVector mp2 = Td.TransformPoint(dPoint);
344  G4ThreeVector msi = Tm.Inverse().TransformPoint(mp2);
345 
346  if (solid->Inside(msi)==kInside)
347  {
348  std::ostringstream message;
349  message << "Overlap with volume already placed !" << G4endl
350  << " Overlap is detected for volume "
351  << GetName() << G4endl
352  << " apparently fully encapsulating volume "
353  << daughter->GetName() << G4endl
354  << " at the same level !";
355  G4Exception("G4PVPlacement::CheckOverlaps()",
356  "GeomVol1002", JustWarning, message);
357  return true;
358  }
359  }
360  }
361  }
362 
363  if (verbose)
364  {
365  G4cout << "OK! " << G4endl;
366  }
367 
368  return false;
369 }
370 
371 // ----------------------------------------------------------------------
372 // NewPtrRotMatrix
373 //
374 // Auxiliary function for 2nd & 4th constructors (those with G4Transform3D)
375 // Creates a new rotation matrix on the heap (using "new") and copies its
376 // argument into it.
377 //
378 // NOTE: Ownership of the returned pointer is left to the caller !
379 // No entity is currently responsible to delete this memory.
380 //
382 G4PVPlacement::NewPtrRotMatrix(const G4RotationMatrix &RotMat)
383 {
384  G4RotationMatrix *pRotMatrix;
385  if ( RotMat.isIdentity() )
386  {
387  pRotMatrix = 0;
388  }
389  else
390  {
391  pRotMatrix = new G4RotationMatrix(RotMat);
392  }
393  // fallocatedRotM= ! (RotMat.isIdentity());
394 
395  return pRotMatrix;
396 }