Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:25

0001 #include "DetectorDescription/Core/interface/DDExpandedView.h"
0002 
0003 #include <memory>
0004 #include <ostream>
0005 
0006 #include "DetectorDescription/Core/interface/DDComparator.h"
0007 #include "DetectorDescription/Core/interface/DDLogicalPart.h"
0008 #include "DetectorDescription/Core/interface/DDPosData.h"
0009 #include "DataFormats/Math/interface/Graph.h"
0010 #include "DataFormats/Math/interface/GraphWalker.h"
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 #include "Math/GenVector/Cartesian3D.h"
0013 #include "Math/GenVector/DisplacementVector3D.h"
0014 #include "Math/GenVector/Rotation3D.h"
0015 
0016 class DDPartSelection;
0017 
0018 /** 
0019    After construction the instance corresponds to the root of the geometrical tree.
0020 */
0021 DDExpandedView::DDExpandedView(const DDCompactView& cpv)
0022     : walker_(nullptr),
0023       w2_(cpv.graph(), cpv.root()),
0024       trans_(DDTranslation()),
0025       rot_(DDRotationMatrix()),
0026       depth_(0),
0027       worldpos_(cpv.worldPosition()),
0028       cpv_(&cpv) {
0029   walker_ = &w2_;
0030 
0031   const DDPosData* pd((*walker_).current().second);
0032   if (!pd)
0033     pd = worldpos_;
0034   DDExpandedNode expn((*walker_).current().first, pd, trans_, rot_, 0);
0035 
0036   // starting point for position calculations, == root of expanded view
0037   history_.emplace_back(expn);
0038 }
0039 
0040 DDExpandedView::~DDExpandedView() {}
0041 
0042 const DDLogicalPart& DDExpandedView::logicalPart() const { return history_.back().logp_; }
0043 
0044 const std::string& DDExpandedView::name() const { return history_.back().logp_.ddname().name(); }
0045 
0046 const DDTranslation& DDExpandedView::translation() const { return history_.back().trans_; }
0047 
0048 const DDRotationMatrix& DDExpandedView::rotation() const { return history_.back().rot_; }
0049 
0050 const DDGeoHistory& DDExpandedView::geoHistory() const { return history_; }
0051 
0052 int DDExpandedView::depth() const { return depth_; }
0053 
0054 int DDExpandedView::copyno() const { return history_.back().copyno(); }
0055 
0056 /** 
0057    returns true, if a next sibling exists and updates \c this
0058    otherwise returns false.
0059    If a scope was set, the nextSibling of the root of the scope is not selected.
0060 */
0061 bool DDExpandedView::nextSibling() {
0062   bool result(false);
0063   if (!scope_.empty() && history_.back() == scope_.back()) {
0064     ;  // no-next-sibling, if current node is the root of the scope!
0065   } else {
0066     if ((*walker_).nextSibling()) {
0067       DDExpandedNode& expn(history_.back());  // back of history_ is always current node
0068       WalkerType::value_type curr = (*walker_).current();
0069       DDPosData const* posdOld = expn.posd_;
0070       expn.logp_ = curr.first;
0071       expn.posd_ = curr.second;
0072 
0073       DDGeoHistory::size_type hsize = history_.size();
0074 
0075       if (hsize > 1) {
0076         const DDExpandedNode& expnBefore(history_[hsize - 2]);
0077 
0078         // T = T1 + INV[R1] * T2
0079         expn.trans_ = expnBefore.trans_ + (expnBefore.rot_ * expn.posd_->trans());
0080 
0081         // R = R1*INV[R2]
0082         // VI in principle we can do this
0083         if (!(expn.posd_->rot() == posdOld->rot())) {
0084           expn.rot_ = expnBefore.rot_ * expn.posd_->rot();  //.inverse();
0085         }
0086       } else {
0087         expn.trans_ = expn.posd_->trans();
0088         expn.rot_ = expn.posd_->rot();  //.inverse();
0089       }
0090       ++expn.siblingno_;
0091       result = true;
0092     }
0093   }
0094   return result;
0095 }
0096 
0097 /** 
0098    returns true, if a child of the current node exists and updates \c this
0099    otherwise returns false
0100 */
0101 bool DDExpandedView::firstChild() {
0102   bool result(false);
0103   bool depthNotReached(true);
0104 
0105   // Check for the depth within the scope ...
0106   if (depth_) {
0107     if ((history_.size() - scope_.size()) == depth_) {
0108       depthNotReached = false;
0109     }
0110   }
0111   if (depthNotReached) {
0112     if ((*walker_).firstChild()) {
0113       DDExpandedNode& expnBefore(history_.back());
0114       WalkerType::value_type curr = (*walker_).current();
0115 
0116       DDPosData* newPosd = curr.second;
0117 
0118       // T = ... (see nextSiblinig())
0119       DDTranslation newTrans = expnBefore.trans_ + expnBefore.rot_ * newPosd->trans();
0120 
0121       // R = ... (see nextSibling())
0122       DDRotationMatrix newRot = expnBefore.rot_ * newPosd->rot();  //.inverse();
0123 
0124       // create a new Expanded node and push it to the history ...
0125       DDExpandedNode expn(curr.first, curr.second, newTrans, newRot, 0);
0126 
0127       history_.emplace_back(expn);
0128       result = true;
0129     }  // if firstChild
0130   }    // if depthNotReached
0131   return result;
0132 }
0133 
0134 /** 
0135    returns ture, if a parent exists and updates \c this otherwise returns
0136    false. When false is returned, the root node of the scope is reached.
0137 */
0138 bool DDExpandedView::parent() {
0139   bool result(false);
0140   bool scopeRoot(false);
0141 
0142   // check for a scope
0143   if (!scope_.empty()) {
0144     if (scope_.back() == history_.back()) {
0145       // the current node is the root of the scope
0146       scopeRoot = true;
0147     }
0148   }
0149 
0150   if (!scopeRoot) {
0151     if ((*walker_).parent()) {
0152       history_.pop_back();
0153       result = true;
0154     }
0155   }
0156 
0157   return result;
0158 }
0159 
0160 // same implementation as in GraphWalker !
0161 /** 
0162    Tree transversal:
0163     
0164    - try to go to the first child
0165       
0166    - else try to go to the next sibling
0167       
0168    - else try to go to the next sibling of the parent
0169       
0170    Currently the whole remaining subtree is transversed when next() is
0171    subsequently called.
0172       
0173    \todo stop, when subtree down a specified node has been transversed    
0174 */
0175 bool DDExpandedView::next() {
0176   bool res(false);
0177   if (firstChild())
0178     res = true;
0179   else if (nextSibling())
0180     res = true;
0181   else {
0182     while (parent()) {
0183       if (nextSibling()) {
0184         res = true;
0185         break;
0186       }
0187     }
0188   }
0189   return res;
0190 }
0191 
0192 /** broad first */
0193 bool DDExpandedView::nextB() {
0194   bool res(false);
0195   return res;
0196 }
0197 
0198 void dump(const DDGeoHistory& history) {
0199   edm::LogInfo("DDExpandedView") << "--GeoHistory-Dump--[" << std::endl;
0200   int i = 0;
0201   for (const auto& it : history) {
0202     edm::LogInfo("DDExpandedView") << " " << i << it.logicalPart() << std::endl;
0203     ++i;
0204   }
0205   edm::LogInfo("DDExpandedView") << "]---------" << std::endl;
0206 }
0207 
0208 /** 
0209    User specific data can be attached to single nodes or a selection of
0210    nodes in the expanded view through the DDSpecifics interface.
0211       
0212    The resulting std::vector is of size 0 if no specific data was attached.
0213    
0214 */
0215 std::vector<const DDsvalues_type*> DDExpandedView::specifics() const {
0216   // backward compatible
0217   std::vector<const DDsvalues_type*> result;
0218   specificsV(result);
0219   return result;
0220 }
0221 
0222 void DDExpandedView::specificsV(std::vector<const DDsvalues_type*>& result) const {
0223   const auto& specs = logicalPart().attachedSpecifics();
0224   if (!specs.empty()) {
0225     result.reserve(specs.size());
0226     for (const auto& it : specs) {
0227       // a part selection
0228       const DDPartSelection& psel = *(it.first);
0229       const DDGeoHistory& hist = geoHistory();
0230 
0231       if (DDCompareEqual(hist, psel)())
0232         result.emplace_back(it.second);
0233     }
0234   }
0235 }
0236 
0237 DDsvalues_type DDExpandedView::mergedSpecifics() const {
0238   DDsvalues_type merged;
0239   mergedSpecificsV(merged);
0240   return merged;
0241 }
0242 
0243 void DDExpandedView::mergedSpecificsV(DDsvalues_type& merged) const {
0244   merged.clear();
0245   const auto& specs = logicalPart().attachedSpecifics();
0246   if (specs.empty())
0247     return;
0248   const DDGeoHistory& hist = geoHistory();
0249   for (const auto& it : specs) {
0250     if (DDCompareEqual(hist, *it.first)())
0251       merge(merged, *it.second);
0252   }
0253 }
0254 
0255 /**
0256    All navigational commands only operate in the subtree rooted by the
0257    node marked by the node of the DDGeoHistory returned by this method.
0258    If the size() of the scope equals 0, the full scope covering the 
0259    whole expanded-view is set (default).
0260 */
0261 const DDGeoHistory& DDExpandedView::scope() const { return scope_; }
0262 
0263 void DDExpandedView::clearScope() {
0264   scope_.clear();
0265   depth_ = 0;
0266 }
0267 
0268 void DDExpandedView::reset() {
0269   clearScope();
0270   while (parent())
0271     ;
0272 }
0273 
0274 /**
0275    The scope of the expanded-view is set to the subtree rooted by the node 
0276    marked by the DDGeohistory hist.
0277    The current not of the expanded view is set to the root of the subtree.
0278    All navigational methods apply only on the subtree.
0279     
0280    In case of hist not marking a valid node in the expanded-view, the
0281    state of the expanded-view is unchanged and false is returned by setScope().
0282    Otherwise true is returned.
0283 */
0284 bool DDExpandedView::setScope(const DDGeoHistory& sc, int depth) {
0285   bool result(false);
0286 
0287   DDGeoHistory buf = scope_;  // save current scope
0288   scope_.clear();             // sets scope to global (full) scope
0289 
0290   while (parent())
0291     ;  // move up to the root of the expanded-view
0292 
0293   if (descend(sc)) {  // try to move down the given scope-history ...
0294     scope_ = sc;
0295     depth_ = depth;
0296     result = true;
0297   } else {
0298     scope_ = buf;
0299   }
0300 
0301   return result;
0302 }
0303 
0304 /**
0305   goTo will reset the ExpandedView if pos is not a valid position.
0306   Currently no checks are implemented to verify that pos is within the
0307   current scope of the ExpandedView.
0308   \todo check whether pos is in the current scope 
0309 */
0310 bool DDExpandedView::goToHistory(const DDGeoHistory& pos) {
0311   bool result = true;
0312   int tempD = depth_;
0313   DDGeoHistory tempScope = scope_;
0314   reset();
0315   DDGeoHistory::size_type s = pos.size();
0316   for (DDGeoHistory::size_type j = 1; j < s; ++j) {
0317     if (!firstChild()) {
0318       result = false;
0319       break;
0320     }
0321     int i = 0;
0322     for (; i < pos[j].siblingno(); ++i) {
0323       if (!nextSibling()) {
0324         result = false;
0325       }
0326     }
0327   }
0328 
0329   if (!result) {
0330     reset();
0331     setScope(tempScope, tempD);
0332   } else {
0333     scope_ = tempScope;
0334     depth_ = tempD;
0335   }
0336 
0337   return result;
0338 }
0339 
0340 //! \todo implement it simpler using DDExpandedNode::siblingno()
0341 bool DDExpandedView::descend(const DDGeoHistory& sc) {
0342   DDGeoHistory::size_type mxx = sc.size();
0343   DDGeoHistory::size_type cur = 0;
0344   bool result(false);
0345 
0346   /* algo: compare currerent node in expanded-view with current-node in sc
0347            if matching:
0348          (A)go to first child in expanded-view, go one level deeper in sc
0349          iterate over all children in expanded-view until one of them
0350          matches the current node in sc. 
0351          if no one matches, return false
0352          else continue at (A)
0353        else return false
0354   */
0355   const DDExpandedNode& curNode = history_.back();
0356 
0357   if (!sc.empty()) {
0358     if (curNode == sc[cur]) {
0359       bool res(false);
0360       while (cur + 1 < mxx && firstChild()) {
0361         ++cur;
0362         if (!(history_.back() == sc[cur])) {
0363           while (nextSibling()) {
0364             if (history_.back() == sc[cur]) {
0365               res = true;
0366               break;
0367             }
0368           }
0369         } else {
0370           res = true;
0371         }
0372         if (res == false)
0373           break;
0374       }
0375       result = res;
0376     }
0377   }
0378   return result;
0379 }
0380 
0381 bool DDExpandedView::goTo(const nav_type& newpos) { return goTo(&newpos.front(), newpos.size()); }
0382 
0383 bool DDExpandedView::goTo(NavRange newpos) { return goTo(newpos.first, newpos.second); }
0384 
0385 bool DDExpandedView::goTo(int const* newpos, size_t sz) {
0386   bool result(false);
0387 
0388   // save the current position
0389   DDGeoHistory savedPos = history_;
0390 
0391   // reset to root node
0392   //FIXME: reset to root of scope!!
0393   reset();
0394 
0395   // try to navigate down to the newpos
0396   for (size_t i = 1; i < sz; ++i) {
0397     result = firstChild();
0398     if (result) {
0399       int pos = newpos[i];
0400       for (int k = 0; k < pos; ++k) {
0401         result = nextSibling();
0402       }
0403     } else {
0404       break;
0405     }
0406   }
0407 
0408   if (!result) {
0409     goToHistory(savedPos);
0410   }
0411   return result;
0412 }
0413 
0414 DDExpandedView::nav_type DDExpandedView::navPos() const {
0415   DDGeoHistory::size_type i = 0;
0416   DDGeoHistory::size_type j = history_.size();
0417   nav_type pos(j);
0418 
0419   for (; i < j; ++i)
0420     pos[i] = history_[i].siblingno();
0421 
0422   return pos;
0423 }
0424 
0425 DDExpandedView::nav_type DDExpandedView::copyNumbers() const {
0426   DDGeoHistory::size_type it = 0;
0427   DDGeoHistory::size_type sz = history_.size();
0428   nav_type result(sz);
0429 
0430   for (; it < sz; ++it) {
0431     result[it] = history_[it].copyno();
0432   }
0433   return result;
0434 }
0435 
0436 std::string printNavType(int const* n, size_t sz) {
0437   std::ostringstream oss;
0438   oss << '(';
0439   for (int const* it = n; it != n + sz; ++it) {
0440     oss << *it << ',';
0441   }
0442   oss << ')';
0443   return oss.str();
0444 }