View Javadoc

1   package org.lcsim.detector;
2   
3   import static org.lcsim.detector.solids.Inside.INSIDE;
4   import static org.lcsim.detector.solids.Inside.OUTSIDE;
5   import hep.physics.vec.BasicHep3Vector;
6   import hep.physics.vec.Hep3Vector;
7   
8   import org.lcsim.detector.solids.Inside;
9   
10  /**
11   * IGeometryInfo provides a cache of detailed geometry
12   * information for its associated DetectorElement,
13   * including coordinate transformations and the 
14   * center position in global coordinates.
15   * 
16   * @author Jeremy McCormick <jeremym@slac.stanford.edu>
17   * @author Tim Nelson <tknelson@slac.stanford.edu>
18   */
19  public class GeometryInfo 
20  implements IGeometryInfo
21  {
22      IDetectorElement de;
23      IGeometryInfoContainer childIGeometryInfos;
24      IGeometryInfo parentIGeometryInfo;
25      IPhysicalVolumePath path;
26      ILogicalVolume logicalVolume;
27      ITransform3D globalToLocal;
28      ITransform3D localToGlobal;
29      ITransform3D parentToLocal;
30      Hep3Vector globalPosition;	
31  
32      /**
33       * 
34       * This method provides a single point of entry
35       * for setting up a GeometryInfo object.  Any
36       * of the arguments except for @param de are
37       * allowed to be null.
38       * 
39       * @param de The DetectorElement that owns this GeometryInfo.
40       * @param lv The associated LogicalVolume.
41       * @param support The path into the geometry that is associated
42       *                with this DetectorElement.
43       */
44      private void setup(
45              IDetectorElement de,
46              ILogicalVolume logicalVolume,
47              IPhysicalVolumePath support)
48      {        
49          // The DetectorElement is not allowed to be null.
50          if ( de == null )
51          {
52              throw new IllegalArgumentException("The IDetectorElement is null!");
53          }
54          
55          // Set the DetectorElement.
56          this.de = de;
57  
58          // Cache child IGeometryInfos.
59          if ( de.getChildren() != null )
60          {
61              if ( de.getChildren().size() > 0 )
62              {
63                  this.childIGeometryInfos = new GeometryInfoContainer();
64                  for (IDetectorElement child : de.getChildren())
65                  {
66                      this.childIGeometryInfos.add(child.getGeometry());
67                  }
68              }
69          }
70  
71          // Set the parent IGeometryInfo ref.
72          if (de.getParent() != null)
73          {
74              this.parentIGeometryInfo = de.getParent().getGeometry();            
75          }
76          
77          // Set the LogicalVolume, if it is given explicitly.
78          if ( logicalVolume != null )
79          {
80              this.logicalVolume = logicalVolume;
81          }
82  
83          // If the DetectorElement has support in the geometry tree,
84          // set the support variable and cache all the derivable geometry 
85          // information.
86          if ( support != null )
87          {
88              setupPath(support);
89          }
90      }
91      
92      private void setupPath(
93              IPhysicalVolumePath path
94              )
95      {
96          if ( this.path != null )
97          {
98              throw new RuntimeException("The DetectorElement already has support in the geometry!");
99          }
100         
101         if ( path == null )
102         {
103             throw new IllegalArgumentException("The IPhysicalVolumePath is null!");
104         }
105                         
106         // Set the support reference.
107         this.path = path;
108 
109         // Get the current geometry navigator.
110         IPhysicalVolumeNavigator navigator =
111             PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator();        
112 
113         // Set the LogicalVolume from the path if it hasn't been setup already.
114         if ( this.logicalVolume == null )
115         {
116             logicalVolume = this.path.getLeafVolume().getLogicalVolume();
117         }
118 
119         // Cache the local to global transform.
120         localToGlobal = navigator.getTransform(this.path);
121 
122         // Cache the global to local transform.
123         globalToLocal = localToGlobal.inverse();
124 
125         // Cache the parent to global transform.
126         if ( parentGeometry() != null ) {
127             parentToLocal = Transform3D.multiply(
128                     getGlobalToLocal(),
129                     parentGeometry().getLocalToGlobal());
130         }
131 
132         // Cache the global position.
133         globalPosition = localToGlobal.transformed(new BasicHep3Vector(0.,0.,0.));        
134     }
135 
136     /**
137      * Creates a ghost volume with no support
138      * in the geometry tree.
139      * 
140      * @param de The associated DetectorElement.
141      */
142     public GeometryInfo(
143             IDetectorElement de)
144     {
145         setup(de,null,null);
146     }
147     
148     /**
149      * Creates an orphan volume with a LogicalVolume
150      * but no support in the geometry tree.
151      * 
152      * @param de The associated DetectorElement.
153      */
154     public GeometryInfo(
155             IDetectorElement de,
156             ILogicalVolume lv)
157     {
158         setup(de,lv,null);
159     }
160 
161     /**
162      * This constructor associates this GeometryInfo 
163      * with a node in the geometry tree.
164      * 
165      * @param de
166      * @param support
167      */
168     public GeometryInfo(
169             IDetectorElement de, 
170             IPhysicalVolumePath support)
171     {			        
172         if ( support == null )
173         {
174             throw new IllegalArgumentException("The support cannot be null!");
175         }
176 
177         if ( support.size() == 0)
178         {
179             throw new IllegalArgumentException("Support is empty!");
180         }
181         
182         setup(de,null,support);
183     }
184 
185     public IGeometryInfoContainer getChildGeometries() 
186     {
187         return childIGeometryInfos;
188     }
189 
190     public IPhysicalVolumePath getPath(Hep3Vector globalPoint) 
191     {
192         return PhysicalVolumeNavigatorStore.getInstance().getDefaultNavigator().getPath(globalPoint);
193     }
194 
195     public ILogicalVolume getLogicalVolume() 
196     {
197         return logicalVolume;
198     }
199 
200     public IPhysicalVolume getPhysicalVolume(Hep3Vector globalPoint) 
201     {
202         return getPath(globalPoint).getLeafVolume();
203     }
204     
205     public IPhysicalVolume getPhysicalVolume()
206     {
207         IPhysicalVolume pv = null;
208         if ( hasPath() )
209         {
210             pv = path.getLeafVolume();
211         }
212         return pv;
213     }
214 
215     public Hep3Vector getPosition() 
216     {
217         return globalPosition;
218     }
219 
220     public IPhysicalVolumePath getPath() 
221     {
222         return path;
223     }
224 
225     public ITransform3D getGlobalToLocal() 
226     {
227         return globalToLocal;
228     }
229 
230     public Hep3Vector transformGlobalToLocal(Hep3Vector global_point) 
231     {
232         return globalToLocal.transformed(global_point);
233     }
234 
235     /** 
236      * 
237      * Check if the global point is inside this volume
238      * by transforming the point from global to local coordinates
239      * and seeing if the resulting point is inside this DetectorElement's
240      * solid. 
241      * 
242      * Check the daughters recursively if this GeometryInfo does not
243      * have a corresponding node in the geometry tree, i.e. if it 
244      * is a "ghost" that is just a container for other DetectorElements.
245      */
246     public Inside inside(Hep3Vector globalPoint) 
247     {
248         Inside inside=OUTSIDE;
249         if ( hasPath() )
250         {
251             inside = getLogicalVolume().getSolid().inside(
252             		getGlobalToLocal().transformed(globalPoint)
253             );
254         }   
255         else {
256             for ( IDetectorElement child : getDetectorElement().getChildren() )
257             {                
258                 inside = child.getGeometry().inside(globalPoint);
259                 if (inside==INSIDE) 
260                 {
261                     break;
262                 }
263             }
264         }
265         return inside;        
266     }
267 
268     public ITransform3D getLocalToGlobal() 
269     {
270         return localToGlobal;
271     }
272 
273     public Hep3Vector transformLocalToGlobal(Hep3Vector local_point) 
274     {
275         return localToGlobal.transformed(local_point);
276     }
277 
278     public IGeometryInfo parentGeometry() 
279     {
280         return parentIGeometryInfo;
281     }
282 
283     public ITransform3D getParentToLocal() 
284     {
285         return parentToLocal;
286     }
287 
288     public Hep3Vector transformParentToLocal(Hep3Vector parentPoint)
289     {
290         return parentToLocal.transformed(parentPoint);		
291     }
292     
293     public boolean isOrphan()
294     {
295         return path == null && logicalVolume != null;
296     }
297 
298     public IDetectorElement getDetectorElement()
299     {
300         return de;
301     }
302     
303     public boolean hasLogicalVolume() 
304     {
305         return logicalVolume != null;
306     }
307 
308     public boolean hasPath() 
309     {
310         return path != null;
311     }   
312     
313     public String getPathString()
314     {
315         String pathString = null;
316         if ( hasPath() )
317         {
318             pathString = path.toString();
319         }
320         return pathString;
321     }
322 }