Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

LCD_DocGeoUtil.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // $Id: LCD_DocGeoUtil.cc,v 1.9 2004/02/02 22:12:48 uid561 Exp $
00003 // ----------------------------------------------------------------------------
00004 //
00005 // LCD_DocGeoUtil.cxx
00006 //
00007 // Utilities for sorting out elements peculiar to LCD detector
00008 // geometry description
00009 #include "LCD_DocGeoUtil.hh"
00010 #include "LCD_DocumentUtil.hh"
00011 #include "LCD_DocManager.hh"
00012 #include "LCD_Document.hh"  // not strictly nec. since in included in above
00013 
00014 XERCES_CPP_NAMESPACE_USE
00015 
00016 // Forward declaration of local routine used in public xxxDim routines
00017 static double getTotalThickness(DOM_Element shape);
00018 
00019 // Given an element of tag type "layering" or with a child of this
00020 // return total width of layers or width of a single layer
00021 
00022 /*
00023  * Comment
00024  */
00025 double LCD_DocGeoUtil::getLayerWidth(DOM_Element elt, bool all) {
00026   DOM_Element layering;
00027   if ((elt.getTagName()).equals("layering")) {
00028     layering = elt;
00029   }
00030   else {
00031     layering = LCD_DocumentUtil::firstDesc(elt, "layering");
00032     if (layering == 0) return -1.0;       // throw exception??
00033   }
00034   DOM_NodeList list = layering.getElementsByTagName(DOMString("slice"));
00035   int          nSlice = list.getLength();
00036   int          iSlice;
00037   DOM_Element  tmpElt;
00038   double       tmpValue;
00039   double       width = 0.0;
00040   bool         ok;
00041 
00042   // Compute width of a single layer by adding up width of slices
00043   for (iSlice = 0; iSlice < nSlice; iSlice++) {
00044     DOM_Node node = list.item(iSlice);
00045     tmpElt = (DOM_Element &) node;
00046     ok =
00047       LCD_DocumentUtil::convertValue(tmpElt.getAttribute(DOMString("width")),
00048                                      &tmpValue);
00049     width += tmpValue;
00050   }
00051   if (!all) return width;
00052 
00053   // multiply by number of layers
00054   int nLayer;
00055 
00056   ok = LCD_DocumentUtil::convertValue(layering.getAttribute("n"), &nLayer);
00057   width *= nLayer;
00058 
00059   return width;
00060 }
00061 
00062 /*
00063  * Comment
00064  */
00065 bool LCD_DocGeoUtil::reflected(const DOM_Element& vol)
00066 {
00067   bool refl;
00068 
00069   // Complex volumes cannot be reflected
00070   if (!(vol.getTagName().equals("volume"))) return false;
00071 
00072   // Get first child.  Should be tube, disk or cone, all of which
00073   // have a "reflected" attribute
00074   DOM_Element shape = LCD_DocumentUtil::firstDesc(vol, "*");
00075 
00076   //  if (vol.getAttributeNode("reflected") == 0) return false;
00077   DOMString reflValue = shape.getAttribute("reflected");
00078 
00079   if (reflValue.equals("")) return false;
00080 
00081   bool ok = LCD_DocumentUtil::convertValue(reflValue, &refl);
00082   if (ok) return refl;
00083   else return false;
00084 
00085   /*  if (LCD_DocumentUtil::convertValue(vol.getAttribute("reflected"), &refl)) {
00086       return refl;
00087       }
00088       else return false; */
00089 }
00090 
00091 
00092 // Given a barrel (centered tube), return  inner_r, outer_z and
00093 // (optionally) outer_r
00094 
00095 /*
00096  * Comment
00097  */
00098 bool LCD_DocGeoUtil::barrelDim(const DOM_Element& tube, double *  pInnerR,
00099                                double * pOuterZ, double * pOuterR) {
00100   bool   ok;
00101 
00102   if (!(tube.getTagName().equals("tube"))) return false;
00103 
00104   DOM_Element dim;
00105 
00106   // In content model for tube, first child element is either
00107   // tube_dimensions, barrel_dimensions or neighbor.  This routine
00108   // can't handle tube_dimensions.  barrel_dimensions case is
00109   // straigthtforward except for outer r.  In neighbor case
00110   // we have to do extra work to get dimensions.
00111   DOM_Element elt = LCD_DocumentUtil::firstDesc(tube, "*");
00112 
00113   if ((elt.getTagName().equals("neighbor"))) {  // implies barrel
00114     DOMString neighborId = elt.getAttribute("adjoins");
00115     double    gap;
00116     double    neighInnerR, neighOuterR;
00117 
00118     ok = LCD_DocumentUtil::convertValue(elt.getAttribute("gap"), &gap);
00119 
00120     // get neighboring element.
00121     // First need to get our enclosing LCD_Document
00122     DOM_Document domDoc = elt.getOwnerDocument();
00123 
00124     // This may not be right -- could be complex volume
00125     elt = (LCD_DocManager::getLCDDoc(domDoc))->getElement(neighborId,
00126                                                           DOMString("volume"));
00127 
00128     // it better be a tube
00129     elt = LCD_DocumentUtil::firstDesc(elt, "tube");
00130 
00131     // Call ourselves to get its dimensions, in particular outer r
00132     // and outer z
00133     tubeDim(elt, &neighInnerR, pOuterZ, &neighOuterR);
00134 
00135     *pInnerR = neighOuterR + gap;
00136   }
00137 
00138   else if ((elt.getTagName().equals("barrel_dimensions"))) {
00139     dim = elt;
00140     ok =
00141       LCD_DocumentUtil::convertValue(dim.getAttribute(DOMString("inner_r")),
00142                                      pInnerR);
00143 
00144     if (ok)
00145       ok =
00146         LCD_DocumentUtil::convertValue(dim.getAttribute(DOMString("outer_z")),
00147                                        pOuterZ);
00148   }
00149   else return false;
00150 
00151   if (pOuterR) *pOuterR = *pInnerR + getTotalThickness(tube);
00152   return ok;
00153 }
00154 
00155 // Return parameters of a not-necessarily-centered tube.  offset
00156 // returned is distance from center of tube to origin.
00157 
00158 /*
00159  * Comment
00160  */
00161 bool LCD_DocGeoUtil::tubeDim(const DOM_Element& tube, double *pInnerR,
00162                              double *pOffsetZ, double *pLength,
00163                              double *pOuterR) {
00164 
00165   bool ok;
00166   if (!(tube.getTagName().equals("tube"))) return false;
00167 
00168   DOM_Element dim = LCD_DocumentUtil::firstDesc(tube, "*");
00169 
00170   if (((dim.getTagName().equals("barrel_dimensions") )  ) ||
00171       ((dim.getTagName().equals("neighbor") )  )            ) {
00172     double outerZ;
00173 
00174     ok = barrelDim(tube, pInnerR, &outerZ, pOuterR);
00175 
00176     if (ok) {
00177       *pOffsetZ = 0.0;
00178       *pLength = 2 * outerZ;
00179     }
00180     return ok;
00181   }
00182   else if (dim.getTagName().equals("tube_dimensions")) {
00183     ok =
00184       LCD_DocumentUtil::convertValue(dim.getAttribute(DOMString("inner_r")),
00185                                      pInnerR);
00186     if (ok)
00187       ok =
00188         LCD_DocumentUtil::convertValue(dim.getAttribute(DOMString("offset_z")),
00189                                        pOffsetZ);
00190     if (ok)
00191       ok =
00192         LCD_DocumentUtil::convertValue(dim.getAttribute(DOMString("length")),
00193                                        pLength);
00194     if (!pOuterR) return ok;
00195     if (!ok) return false;
00196     else *pOuterR = *pInnerR + getTotalThickness(tube);
00197 
00198     return true;
00199   }
00200   return false;  // improper first child
00201 }
00202 
00203 
00204 // Given a disk, return inner r, inner z, outer r and (optionally)
00205 // outer z.
00206 
00207 /*
00208  * Comment
00209  */
00210 bool LCD_DocGeoUtil::diskDim(const DOM_Element& disk, double *pInnerR,
00211                              double *pInnerZ, double *pOuterR,
00212                              double *pOuterZ) {
00213   bool   ok;
00214 
00215   if (!(disk.getTagName().equals("disk"))) return false;
00216 
00217   DOM_Element dim;
00218 
00219   // In content model for disk, first child element is either disk_dimensions
00220   // or neighbor.  In latter case we have to do extra work to get
00221   // dimensions.
00222   DOM_Element elt = LCD_DocumentUtil::firstDesc(disk, "*");
00223 
00224   if ((elt.getTagName().equals("neighbor"))) {
00225     DOMString neighborId = elt.getAttribute("adjoins");
00226     double    gap;
00227     double    neighOuterZ;
00228 
00229     ok = LCD_DocumentUtil::convertValue(elt.getAttribute("gap"), &gap);
00230 
00231     // get neighboring element. Our inner R, outer R will be the
00232     // same as the neighbor's. To get our inner Z, take neighbor's
00233     // outer Z and add gap
00234     // First need to get our enclosing LCD_Document
00235     DOM_Document domDoc = elt.getOwnerDocument();
00236 
00237     // Not quite right since it also could be a complex volume
00238     elt = (LCD_DocManager::getLCDDoc(domDoc))->getElement(neighborId,
00239                                                           DOMString("volume"));
00240 
00241     // could be tube or another disk.  If a tube, had better be barrel type
00242     elt = LCD_DocumentUtil::firstDesc(elt, "*");
00243 
00244     if ((elt.getTagName()).equals("tube")) {
00245       barrelDim(elt, pInnerR, &neighOuterZ, pOuterR);
00246     }
00247     else if ((elt.getTagName()).equals("disk")) {
00248       double tmp;     // for neighbor inner Z, which we don't need
00249       diskDim(elt, pInnerR, &tmp, pOuterR, &neighOuterZ);
00250     }
00251 
00252     *pInnerZ = neighOuterZ + gap;
00253   }
00254 
00255   else { // it's a disk_dimension element
00256     ok =
00257       LCD_DocumentUtil::convertValue(elt.getAttribute(DOMString("inner_r")),
00258                                      pInnerR);
00259 
00260     if (ok)
00261       ok =
00262         LCD_DocumentUtil::convertValue(elt.getAttribute(DOMString("inner_z")),
00263                                        pInnerZ);
00264 
00265     if (ok)
00266       ok =
00267         LCD_DocumentUtil::convertValue(elt.getAttribute(DOMString("outer_r")),
00268                                        pOuterR);
00269   }
00270 
00271   if (pOuterZ)  *pOuterZ = *pInnerZ + getTotalThickness(disk);
00272 
00273   return ok;
00274 }
00275 
00276 // This is just a private utility.  We can assume shape is
00277 // a DOM_Element of the proper type
00278 static double getTotalThickness(DOM_Element shape) {
00279   double      tmpValue;
00280   DOM_NodeList list = shape.getElementsByTagName(DOMString("slice"));
00281   DOM_Element  tmpElt;
00282   double       width;
00283   bool         ok;
00284 
00285   // Get width due to layers
00286   tmpElt = LCD_DocumentUtil::firstDesc(shape, "layering");
00287   width = LCD_DocGeoUtil::getLayerWidth(tmpElt, true);
00288 
00289   // add on width of inner wall, if any
00290   tmpElt = LCD_DocumentUtil::firstDesc(shape, DOMString("iwall"));
00291   if (tmpElt != DOM_Element()) {
00292     ok = LCD_DocumentUtil::convertValue(tmpElt.getAttribute("width"),
00293                                         &tmpValue);
00294     width += tmpValue;
00295   }
00296 
00297   // add on width of outer wall, if any
00298   tmpElt = LCD_DocumentUtil::firstDesc(shape, "owall");
00299   if (tmpElt != DOM_Element()) {
00300     ok = LCD_DocumentUtil::convertValue(tmpElt.getAttribute("width"),
00301                                         &tmpValue);
00302     width += tmpValue;
00303   }
00304   return width;
00305 }
00306 
00307 /*
00308  * Comment
00309  */
00310 bool LCD_DocGeoUtil::coneDim(const DOM_Element& cone,
00311                              double *pMinInnerR, double *pMinOuterR,
00312                              double *pMaxInnerR, double *pMaxOuterR,
00313                              double *pInnerZ, double *pOuterZ) {
00314 
00315   double innerWidth, outerWidth;
00316 
00317   if (!(cone.getTagName().equals("cone"))) return false;
00318 
00319   DOM_Element child = LCD_DocumentUtil::firstDesc(cone, "cone_dimensions");
00320 
00321   if (!LCD_DocumentUtil::convertValue(child.getAttribute("min_inner_r"),
00322                                       pMinInnerR)) return false;
00323   if (!LCD_DocumentUtil::convertValue(child.getAttribute("max_inner_r"),
00324                                       pMaxInnerR)) return false;
00325   if (!LCD_DocumentUtil::convertValue(child.getAttribute("inner_z"),
00326                                       pInnerZ)) return false;
00327   if (!LCD_DocumentUtil::convertValue(child.getAttribute("outer_z"),
00328                                       pOuterZ)) return false;
00329 
00330   child = LCD_DocumentUtil::firstDesc(cone, "cone_slice");
00331   if (!LCD_DocumentUtil::convertValue(child.getAttribute("inner_width"),
00332                                       &innerWidth)) return false;
00333   if (child.getAttributeNode("outer_width") == 0) {
00334     outerWidth = innerWidth;
00335   }
00336   else {
00337     if (!LCD_DocumentUtil::convertValue(child.getAttribute("outer_width"),
00338                                         &outerWidth)) return false;
00339   }
00340 
00341   *pMinOuterR = *pMinInnerR + innerWidth;
00342   *pMaxOuterR = *pMaxInnerR + outerWidth;
00343   return true;
00344 }
00345 
00346 // The element "layered" should be a tube or disk (or just have one
00347 // as descendant?)
00348 
00349 /*
00350  * Comment
00351  */
00352 double LCD_DocGeoUtil::getLayer0Dist(const DOM_Element& layered) {
00353   bool    ok;
00354   double  innerBound;
00355 
00356   if  ((layered.getTagName()).equals("tube")) {
00357     double offsetZ, length;  // will throw these away
00358     ok = tubeDim(layered, &innerBound, &offsetZ, &length);
00359   }
00360   else if  ((layered.getTagName()).equals("disk")) {
00361     double innerR, outerR; // will throw these away
00362     ok = diskDim(layered, &innerR, &innerBound, &outerR);
00363   }
00364   else return 0.0;  // throw exception??
00365   if (!ok) return 0.0; // throw exception??
00366 
00367   DOM_Element child = LCD_DocumentUtil::firstDesc(layered, "iwall");
00368   if (child == 0) return innerBound;
00369 
00370   double width;
00371 
00372   ok =
00373     LCD_DocumentUtil::convertValue(child.getAttribute(DOMString("width")),
00374                                    &width);
00375   if (ok) innerBound += width;
00376   return innerBound;
00377 }
00378 
00379 
00380 /*
00381  * Comment
00382  */
00383 bool LCD_DocGeoUtil::getSegmentation(const DOM_Element& elt, double *nTheta,
00384                                      double *nPhi)
00385 {
00386   bool ok;
00387 
00388   DOM_Element seg;
00389   if ((elt.getTagName()).equals("segmentation")) {
00390     seg = elt;
00391   }
00392   else {
00393     seg = LCD_DocumentUtil::firstDesc(elt, "segmentation");
00394     if (seg == 0) return false;       // throw exception??
00395   }
00396 
00397   // New files will say theta. Old files may say cos_theta
00398   ok =
00399     LCD_DocumentUtil::convertValue(seg.getAttribute(DOMString("theta")),
00400                                    nTheta);
00401   if (!ok) ok =
00402              LCD_DocumentUtil::convertValue(seg.getAttribute(DOMString("cos_theta")),
00403                                             nTheta);
00404 
00405   ok = ok &&
00406     LCD_DocumentUtil::convertValue(seg.getAttribute(DOMString("phi")),
00407                                    nPhi);
00408   return ok;
00409 }

Generated on Thu Oct 7 18:44:46 2004 for LCDG4 by doxygen 1.3.4