View Javadoc

1   package org.lcsim.detector.solids;
2   
3   import hep.physics.vec.Hep3Vector;
4   
5   import java.util.ArrayList;
6   import java.util.Collections;
7   import java.util.Comparator;
8   import java.util.List;
9   
10  /**
11   * A port of Polycone that only maintains data members.
12   * No solid functionality for now.
13   * 
14   * @author Cosmin Deaconu <cozzyd@stanford.edu>
15   * @author Jeremy McCormick <jeremym@slac.stanford.edu>
16   */
17  public class Polycone 
18  extends AbstractSolid
19  {
20      List<ZPlane> zplanes = new ArrayList<ZPlane>();
21      private double zHalfLength = 0; 
22      private double zMax; 
23      private double zMin; 
24      
25      public Polycone(String name, List<ZPlane> zplanes)
26      {
27      	super(name);
28      	for (ZPlane zplane : zplanes)
29      	{
30      		this.zplanes.add(zplane);
31      	}
32          
33          //keep ZPlanes sorted in Z... otherwise things will get messed up
34          Collections.sort(this.zplanes, new Comparator<ZPlane>(){
35              
36              public int compare(ZPlane a, ZPlane b){
37                  if (a.z<b.z) return -1;
38                  if (a.z>b.z) return 1; 
39                  return 0; 
40              }
41          });
42          
43          //calculate zmax,min,halflength
44          if(zplanes.size()>0){
45              zMax = zplanes.get(zplanes.size()-1).z;
46              zMin = zplanes.get(0).z;
47              zHalfLength = (zMax - zMin)/2.0;
48              
49          }
50      }    
51          
52      public List<ZPlane> getZPlanes()
53      {
54          return zplanes;
55      }
56          
57      public int getNumberOfZPlanes()
58      {
59          return zplanes.size();
60      }
61      
62      public ZPlane getZPlane(int idx)
63      {
64          return zplanes.get(idx);
65      }
66      
67   
68      public double getZHalfLength(){
69          return zHalfLength;
70      }
71      
72      public static class ZPlane
73      {
74          double rmin, rmax, z;
75          
76          public ZPlane(double rmin, double rmax, double z)
77          {
78              this.rmin = rmin;
79              this.rmax = rmax;
80              this.z = z;
81          }
82          
83          public double getRMin()
84          {
85              return rmin;
86          }
87          
88          public double getRMax()
89          {
90              return rmax;
91          }
92          
93          public double getZ()
94          {
95              return z;
96          }
97          
98          @Override
99          public String toString(){
100             return "ZPlane w/ rmin = "+rmin+", rmax = "+rmax+", z = "+z;
101         }
102     }
103 
104     public double getCubicVolume() 
105     {   
106         if (zplanes.size()<2) throw new RuntimeException("Too few ZPlanes in PolyCone"); 
107         double vol = 0.0; 
108         for (int i = 1; i<zplanes.size(); i++) {
109             vol+=getSegmentVolume(zplanes.get(i-1), zplanes.get(i)); 
110         }
111         return vol;
112     }
113 
114     public Inside inside(Hep3Vector position) 
115     {
116         if (zplanes.size()<2) throw new RuntimeException("Too few ZPlanes in PolyCone"); 
117 
118         double r = Math.sqrt(position.x()*position.x() + position.y()*position.y());
119         double z = position.z();
120 
121         for (int i = 1; i<zplanes.size(); i++) {
122 
123             ZPlane p1 = zplanes.get(i-1);
124             ZPlane p2 = zplanes.get(i);
125 
126             //see if it's at the left or right edge
127             if ((i==1 && z == p1.z && r<=p1.rmax && r>=p1.rmin) ||
128                 (i==zplanes.size()-1 && z == p2.z && r<=p2.rmax && r>=p2.rmin)) 
129                 return Inside.SURFACE;
130 
131             //this means we're in the right section...
132             if ((z <= p2.z && z >= p1.z)) {
133 
134                 double b = f(position.z(),OUTER,p1,p2);
135                 double a = f(position.z(),INNER,p1,p2);
136 
137                 if (r==b || r==a) return Inside.SURFACE;
138                 if (r<b && r>a) return Inside.INSIDE;
139             }
140         }
141 
142         return Inside.OUTSIDE; 
143     }           
144 
145     /**
146     * Returns the inner radius of the polycone at the given z. If
147     * no portion of the polycone exists for the given z, 0. is returned. 
148     * @param z a z-coordinate in mm
149     * @return the inner radius in mm at z
150     */
151     public double getInnerRadiusAtZ(double z) {
152        return getRadiusAtZ(z,INNER);
153     }
154 
155     /**
156     * Returns the outer radius of the polycone at the given z. If
157     * no portion of the polycone exists for the given z, 0. is returned. 
158     * @param z a z-coordinate in mm
159     * @return the outer radius in mm at z
160     */
161     public double getOuterRadiusAtZ(double z) {
162        return getRadiusAtZ(z,OUTER);
163     }
164 
165     /**
166     * Returns the volume of the segment at the given value of z. 
167     * 
168     * <ul>
169     *   <li>If there is no segment at that z, 0 is returned.
170     *   <li>If z lies at the junction of the two segments, the earlier segment
171     *       in the ZPlanes list will be used (should be the one at smaller z)
172     * </ul>
173     * @param z a z-coordinate in mm 
174     * @return the volume of the segment at z in mm^3
175     */
176     public double getVolumeOfSegmentAtZ(double z){
177        if (z<zMin || z>zMax) return 0; 
178        for (int i = 1; i < zplanes.size(); i++) {
179             if (z<zplanes.get(i).z){
180                 ZPlane p1 = zplanes.get(i-1); 
181                 ZPlane p2 = zplanes.get(i); 
182                 return getSegmentVolume(p1,p2); 
183             }
184        }
185        return 0; 
186     }
187 
188    /**
189     * Returns the volume of a polycone segment defined by the zplanes p1 and p2
190     * @param p1 A bounding ZPlane
191     * @param p2 The other bounding ZPlane
192     * @return the volume of the segment
193     */
194    public static double getSegmentVolume(ZPlane p1, ZPlane p2) {    
195         return Math.PI/(3.0)*(p2.z-p1.z)*(p2.rmax*p2.rmax + p1.rmax*p2.rmax + p1.rmax*p1.rmax 
196                         - p2.rmin*p2.rmin - p2.rmin*p1.rmin - p1.rmin*p1.rmin);           
197    }
198 
199    private static final boolean INNER = true; 
200    private static final boolean OUTER = false; 
201    //Calculates the radius at any z of either the outer or inner part of the segment
202    private double f(double z, boolean whichR, ZPlane p1, ZPlane p2){
203 
204         double z1 = p1.z;
205         double z2 = p2.z;
206         double x1 = whichR ? p1.rmin : p1.rmax;
207         double x2 = whichR ? p2.rmin : p2.rmax;
208 
209         double m = (x2-x1)/(z2-z1);
210         return x1 + m*(z-z1);
211    }
212 
213    private double getRadiusAtZ(double z, boolean whichR){
214         if (z<zMin || z>zMax) return 0; 
215         for (int i = 1; i <zplanes.size(); i++){
216             if (z<=zplanes.get(i).z){
217                 return f(z,whichR,zplanes.get(i-1),zplanes.get(i));
218             }
219         }
220         return 0.; 
221    }         
222 }