Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

SiDetLadder.cxx

Go to the documentation of this file.
00001 // $Id: SiDetLadder.cxx,v 1.6 2000/11/30 01:42:34 jrb Exp $
00002 // 
00003 //  Original author: Sawyer Gillespie
00004 //                   hgillesp@u.washington.edu
00005 //
00006 //  Clipping code, etc. provided by Marios Nikolaou, SLAC
00007 //                   marios@slac.stanford.edu
00008 //
00009 
00010 #include "instrument/SiDetLadder.h"
00011 #include <cfloat>
00012 #include <cassert>
00013 #include <algorithm>
00014 #include "dom/DOM_Element.hpp"  // or maybe DOM_Document??
00015 #include "xml/Dom.h"
00016 
00017 // local namespace
00018 namespace {
00019 
00020   // utility function declarations
00021 #ifdef _MSC_VER
00022   inline double copysign(double a, double b){return _copysign(a,b);}
00023 #endif
00024 
00025 
00026 #define EPS 1e-8 // 0.1nm. Have to find a better way. This because of 
00027   // floating point errors.
00028 
00029   // ------------- 2D Liang-Barsky clipping algorithm ------------------------
00030   // Subroutine used by clipping algoritm. (2D Liang-Barsky algorithm)
00031   static inline bool clipT(double p, double q, double *tE, double *tL)
00032     {
00033       if (p < 0.0) {
00034         double t = q / p;
00035         if (t > *tL) return false;
00036         else  if (t > *tE)    *tE = t;
00037       }
00038       else  if (p > 0.0) {
00039         double t = q / p;
00040         if (t < *tE) return false;
00041         else  if (t < *tL)    *tL = t;
00042       }
00043       else       /* p == 0 */
00044         if (q < 0.0) return false;
00045             
00046       return true;
00047     }
00048     
00049   // Clip a line to a specified rectangle.
00050   // ..first & second point
00051   static bool clipDie(double *x0, double *y0, double *x1, double *y1, 
00052                        double xmin, double xmax, double ymin, double ymax)
00053     {
00054       double tE = 0.0;
00055       double tL = 1.0;
00056       double dX = *x1 - *x0;
00057       if (clipT(-dX, *x0 - xmin, &tE, &tL) && clipT(dX, xmax - *x0, &tE, &tL))
00058       {
00059         double dY = *y1 - *y0;
00060         if (clipT(-dY, *y0 - ymin, &tE, &tL) && 
00061             clipT(dY, ymax - *y0, &tE, &tL))   
00062         {
00063           if (tL < 1.0)  {
00064             *x1 = *x0 + (tL * dX);
00065             *y1 = *y0 + (tL * dY);
00066           }
00067           if (tE > 0.0)  {
00068             *x0 += tE * dX;
00069             *y0 += tE * dY;
00070           }
00071         }
00072         else return false;
00073       }
00074       else return false;
00075         
00076       // patch for floating point errors
00077       if (fabs(*x0-xmin) < 10*DBL_EPSILON) *x0=xmin;
00078       if (fabs(*x0-xmax) < 10*DBL_EPSILON) *x0=xmax;
00079       if (fabs(*x1-xmin) < 10*DBL_EPSILON) *x1=xmin;
00080       if (fabs(*x1-xmax) < 10*DBL_EPSILON) *x1=xmax;
00081       if (fabs(*y0-ymin) < 10*DBL_EPSILON) *y0=ymin;
00082       if (fabs(*y0-ymax) < 10*DBL_EPSILON) *y0=ymax;
00083       if (fabs(*y1-ymin) < 10*DBL_EPSILON) *y1=ymin;
00084       if (fabs(*y1-ymax) < 10*DBL_EPSILON) *y1=ymax;
00085         
00086       // Should not happen!
00087       assert((*x0>=xmin) && (*x0<=xmax));
00088       assert((*x1>=xmin) && (*x1<=xmax));
00089       assert((*y0>=ymin) && (*y0<=ymax));
00090       assert((*y1>=ymin) && (*y1<=ymax));
00091         
00092       return true;
00093     }
00094 }
00095 
00096 SiDetLadder::SiDetLadder(const DOM_Element& spec)
00097 {
00098   // get all the parameters from the XML spec.
00099   m_diegap = atof(xml::Dom::transToChar(spec.getAttribute("diegap")));
00100   m_dieheight = atof(xml::Dom::transToChar(spec.getAttribute("dieheight")));
00101   m_guardring = atof(xml::Dom::transToChar(spec.getAttribute("guardring")));
00102   m_ndies = atof(xml::Dom::transToChar(spec.getAttribute("ndies")));
00103   m_strippitch = atof(xml::Dom::transToChar(spec.getAttribute("strippitch")));
00104   m_width = atof(xml::Dom::transToChar(spec.getAttribute("diewidth")));
00105   m_stripzero = 0;
00106 }
00107 
00108 SiDetLadder::~SiDetLadder ()
00109 {
00110 }
00111 
00112 void    SiDetLadder::score(const Point& o, const Point& p, float eloss,
00113                            SiStripList& l, int stripoffset) const
00114 {
00115   Vector dir = (p - o);
00116   double xDir = dir.x();
00117     
00118   double in = o.x();                                // entry point -- x
00119   double ex = p.x();                                // exit point -- x
00120  // enter/exit strips (if valid)
00121   unsigned ins = stripId(in), exs = stripId(ex); 
00122     
00123   // if these assertions fire, it probably is because the clipping algorithm
00124   // may return an intersection, which lies just outside the active area.
00125   // This due to floting point errors.
00126   // Has temporarily been fixed by giving a slightly smaller clipping region.
00127   //    assert(ins != SiStrip::undef_strip());
00128   //    assert(exs != SiStrip::undef_strip());
00129     
00130   if (ins == exs) {
00131     if (ins != SiStrip::undef_strip()) l.push_back(SiStrip(ins + stripoffset,
00132                                                             eloss));
00133   }
00134   else {
00135     double sx = localX (ins);
00136     double dx = m_strippitch/2. - (in-sx)*copysign(1.,xDir);
00137     l.push_back(SiStrip(ins + stripoffset, eloss*dx/fabs(xDir)));// entry strip
00138     sx = localX (exs);
00139     dx = m_strippitch/2. + (ex-sx)*copysign(1.,xDir);
00140     l.push_back(SiStrip(exs + stripoffset, eloss*dx/fabs(xDir))); // exit strip
00141         
00142     // add energy to strips between entry and exit
00143     short sinc = (ins < exs) ? 1 : -1;
00144     if (fabs(xDir) > m_strippitch)
00145       for (unsigned sid = ins + sinc; sid != exs; sid += sinc)   
00146         l.push_back(SiStrip(sid + stripoffset, eloss*m_strippitch/fabs(xDir)));
00147     else
00148       for (unsigned sid = ins + sinc; sid != exs; sid += sinc) { 
00149         //THB fprintf(std::cerr,"Should not have printed this!\n");
00150         l.push_back(SiStrip(sid + stripoffset, eloss));
00151       }
00152   }
00153 }
00154 
00155 SiStripList SiDetLadder::score (const Point& entry, const Point& exit
00156                                  , float eloss, int stripoffset) const
00157 {
00158   SiStripList retval; // return value
00159 
00160   // call the other method
00161   score (entry, exit, eloss, retval, stripoffset);
00162 
00163   // this calls SiStripList copy constructor (deep copy)
00164   return retval;
00165 }
00166 double   SiDetLadder::insideActiveArea (double x) const {
00167   double  xin = 0., yin = 0.;
00168     
00169   // compute the distance to the nearest x-edge
00170   xin = x - m_guardring;
00171   xin = std::min (xin, m_width - m_guardring*2 - xin);
00172     
00173   return xin;
00174 }
00175 
00176 
00177 double   SiDetLadder::insideActiveArea (double x, double y) const {
00178   double  xin = 0., yin = 0.;
00179     
00180   // compute the distance to the nearest x-edge
00181   xin = x - m_guardring;
00182   xin = std::min (xin, m_width - m_guardring*2 - xin);
00183   if (xin < 0) return xin;
00184 
00185   // compute the distance to the nearest y edge
00186   double diefull = m_dieheight + m_diegap;
00187   double die = floor (y / diefull);
00188   yin = y - diefull * die - m_guardring;
00189   yin = std::min(yin, diefull - m_diegap - m_guardring*2 - yin);
00190   if (yin < 0) return yin;
00191 
00192   // finally, return the minimum distance to the edge
00193   return std::min(xin, yin);
00194 }

Generated at Wed Nov 21 12:22:39 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000