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
12
13
14
15
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
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
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
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
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
147
148
149
150
151 public double getInnerRadiusAtZ(double z) {
152 return getRadiusAtZ(z,INNER);
153 }
154
155
156
157
158
159
160
161 public double getOuterRadiusAtZ(double z) {
162 return getRadiusAtZ(z,OUTER);
163 }
164
165
166
167
168
169
170
171
172
173
174
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
190
191
192
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
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 }