source: trunk/source/geometry/volumes/src/G4PVPlacement.cc @ 1202

Last change on this file since 1202 was 1058, checked in by garnier, 15 years ago

file release beta

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