00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "instrument/SiDetLadder.h"
00011 #include <cfloat>
00012 #include <cassert>
00013 #include <algorithm>
00014 #include "dom/DOM_Element.hpp"
00015 #include "xml/Dom.h"
00016
00017
00018 namespace {
00019
00020
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
00028
00029
00030
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
00044 if (q < 0.0) return false;
00045
00046 return true;
00047 }
00048
00049
00050
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
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
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
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();
00119 double ex = p.x();
00120
00121 unsigned ins = stripId(in), exs = stripId(ex);
00122
00123
00124
00125
00126
00127
00128
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)));
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)));
00141
00142
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
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;
00159
00160
00161 score (entry, exit, eloss, retval, stripoffset);
00162
00163
00164 return retval;
00165 }
00166 double SiDetLadder::insideActiveArea (double x) const {
00167 double xin = 0., yin = 0.;
00168
00169
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
00181 xin = x - m_guardring;
00182 xin = std::min (xin, m_width - m_guardring*2 - xin);
00183 if (xin < 0) return xin;
00184
00185
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
00193 return std::min(xin, yin);
00194 }