ATLAS Offline Software
Loading...
Searching...
No Matches
PRDHandleBase.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
11
14#include "VP1Base/VP1Msg.h"
15
17
18#include <Inventor/C/errors/debugerror.h>
19#include <Inventor/nodes/SoSeparator.h>
20#include <Inventor/nodes/SoTransform.h>
21#include <Inventor/nodes/SoMaterial.h>
22
23#include "TrkSurfaces/Surface.h"
25
28
29#include <vector>
30#include <algorithm>
31#include <sstream>
32
33//____________________________________________________________________
35public:
39 void detach3DObjects();
40
42
43 //Child 0 is the transform, then follows the node representing the shapes.
44 SoSeparator * sepDetailed;
45 SoSeparator * sepSimple;
46 SoMaterial * currentmaterial;
49
50 SoMaterial * determineMaterial(PRDHandleBase*);
51};
52
53//____________________________________________________________________
54SoSeparator* PRDHandleBase::sepSimple() const
55{
56 return m_d->sepSimple;
57}
58
59//____________________________________________________________________
60SoSeparator* PRDHandleBase::sepDetailed() const
61{
62 return m_d->sepDetailed;
63}
64
65//____________________________________________________________________
67 : m_d(new Imp), m_common(colhandle->common()),m_visible(false)
68{
69 m_d->colhandle = colhandle;
70 m_d->sepDetailed = 0;
71 m_d->sepSimple = 0;
72 m_d->currentmaterial = 0;
73 m_d->sephelper_lod_detail = 0;
74 m_d->sephelper_lod_simple = 0;
75}
76
77
78//____________________________________________________________________
80{
81 if (m_d->sepDetailed)
82 m_d->sepDetailed->unref();
83 if (m_d->sepSimple)
84 m_d->sepSimple->unref();
85 if (m_d->currentmaterial)
86 m_d->currentmaterial->unref();
87
88 delete m_d;
89}
90
91//____________________________________________________________________
93{
94 //Fixme:
95 SoTransform * transform(0);
96 //If visible and already build: Detach separators (and ensure we got the sephelpers):
97 if (theclass->m_visible) {
99 int idx = theclass->regionIndex();
101 }
103 }
104
105 //Ensure separators are built and with no children:
106 if (sepDetailed) {
107 //We might get transform from this one:
108 if (sepDetailed->getNumChildren()>0) {
109 transform = static_cast<SoTransform*>(sepDetailed->getChild(0));
110 transform->ref();
111 }
112 sepDetailed->removeAllChildren();
113 } else {
114 sepDetailed = new SoSeparator;
115 sepDetailed->ref();
116 // sepDetailed->renderCaching.setValue(SoSeparator::ON);
117 // sepDetailed->boundingBoxCaching.setValue(SoSeparator::ON);
118 }
119 if (sepSimple) {
120 sepSimple->removeAllChildren();
121 } else {
122 sepSimple = new SoSeparator;
123 // sepSimple->renderCaching.setValue(SoSeparator::ON);
124 // sepSimple->boundingBoxCaching.setValue(SoSeparator::ON);
125 sepSimple->ref();
126 }
127 //Attach transforms:
128 if (!transform) {
129 transform = theclass->createTransform();
130 transform->ref();
131 theclass->common()->registerTransform2Handle(transform,theclass);
132 }
133 sepDetailed->addChild(transform);//For efficiency it is important that this happens BEFORE buildShapes(..) is called.
134 sepSimple->addChild(transform);
135 transform->unref();
136
137 SoNode* shape_simple(0), * shape_detailed(0);
138 theclass->buildShapes(shape_simple, shape_detailed);
139 if (!shape_simple)
140 shape_simple = theclass->common()->nodeManager()->getShapeNode_Point();//Add single point as a stop-gap measure.
141 if (!shape_detailed)
142 shape_detailed = shape_simple;//Could not create detailed shape for some reason. Use simple shape instead.
143
144 sepSimple->addChild(shape_simple);
145 sepDetailed->addChild(shape_detailed);
146
147 //Attach if visible:
148 if (theclass->m_visible)
149 attach3DObjects(theclass);
150}
151
152// //____________________________________________________________________
153// inline void PRDHandleBase::registerTransform(SoTransform*transform)//FIXME: Pass-through not needed
154// {
155// //Use this pass-through method to get around a friend-problem
156// //FIXME common()->system()->registerTransform2Handle(transform,this);
157// }
158
159//____________________________________________________________________
161{
162 //We need to change the current material. This means we need to
163 //clear the cache. Only if we are visible do we need to do a
164 //detach->clear material->attach cycle to trigger attachment under new material.
165
166 if (!m_d->currentmaterial)
167 return;//We have no material cached and is thus not attached either.
168 if (m_visible) {
169 //See if the material changed. If it did, detach, update the material, attach again.
170 SoMaterial * newmat = m_d->determineMaterial(this);
171 newmat->ref();
172 if (newmat!=m_d->currentmaterial) {
173 m_d->detach3DObjects();
174 m_d->currentmaterial->unref();
175 m_d->currentmaterial = newmat;
176 m_d->attach3DObjects(this);
177 } else {
178 newmat->unref();
179 }
180 } else {
181 //Just clear material.
182 m_d->currentmaterial->unref();
183 m_d->currentmaterial = 0;
184 }
185}
186
187//____________________________________________________________________
189{
190 if (!currentmaterial) {
192 currentmaterial->ref();
193 }
194 if (sepDetailed) {
195 if (colhandle->sephelperDetailedNodes())
196 colhandle->sephelperDetailedNodes()->addNodeUnderMaterial(sepDetailed,currentmaterial);
198 sephelper_lod_detail->addNodeUnderMaterial(sepDetailed,currentmaterial);
199 }
200 if (sepSimple) {
201 if (colhandle->sephelperSimpleNodes())
202 colhandle->sephelperSimpleNodes()->addNodeUnderMaterial(sepSimple,currentmaterial);
204 sephelper_lod_simple->addNodeUnderMaterial(sepSimple,currentmaterial);
205 }
206}
207
208//____________________________________________________________________
210{
211 if (!currentmaterial)
212 return;//Can never have been attached!
213 if (sepDetailed) {
214 if (colhandle->sephelperDetailedNodes())
215 colhandle->sephelperDetailedNodes()->removeNodeUnderMaterial(sepDetailed,currentmaterial);
217 sephelper_lod_detail->removeNodeUnderMaterial(sepDetailed,currentmaterial);
218 }
219 if (sepSimple) {
220 if (colhandle->sephelperSimpleNodes())
221 colhandle->sephelperSimpleNodes()->removeNodeUnderMaterial(sepSimple,currentmaterial);
223 sephelper_lod_simple->removeNodeUnderMaterial(sepSimple,currentmaterial);
224 }
225}
226
227//____________________________________________________________________
229{
230 return m_d->colhandle;
231}
232
233//____________________________________________________________________
235{
236 if (vis==m_visible)
237 return;
238 //std::cout<<"Changing visible status from "<<m_visible<<" to "<<vis<<" for: "<<*getPRD()<<std::endl;
239 m_visible=vis;
240 if (vis) {
241 m_d->colhandle->incrementNShownHandles();
242 if (inMuonChamber())
244 if (!m_d->sepSimple||!m_d->sepDetailed)
245 m_d->rebuild3DObjects(this);//The call to rebuild also fixes attached state.
246 else
247 m_d->attach3DObjects(this);
248 } else {
249 m_d->colhandle->decrementNShownHandles();
250 if (inMuonChamber())
252 m_d->detach3DObjects();
253 }
254}
255
256//____________________________________________________________________
258 //Fixme: If selected we really need to redo selection updates!!!
259 if (m_visible) {
260 m_d->rebuild3DObjects(this);
261 } else {
262 //Simply clear the present 3D objects. They will only be recreated if/when the prd becomes visible again.
263 if (m_d->sepDetailed) {
264 m_d->sepDetailed->unref();
265 m_d->sepDetailed = 0;
266 }
267 if (m_d->sepSimple) {
268 m_d->sepSimple->unref();
269 m_d->sepSimple = 0;
270 }
271 }
272
273}
274
275//____________________________________________________________________
276QStringList PRDHandleBase::clicked() const
277{
278 const Trk::PrepRawData * prd = getPRD();
279 if (!prd)
280 return QStringList("Null PRD");
281 std::ostringstream os;
282 os << *(prd);
283 return QString(os.str().c_str()).split("\n");
284}
285
286
287//____________________________________________________________________
289{
290 if (!prd)
291 return Amg::Vector3D(0,0,0);
292 if (!prd->detectorElement())
293 return Amg::Vector3D(0.0,0.0,0.0);
294 const Trk::Surface& theSurface = prd->detectorElement()->surface(prd->identify());
295
296 const Amg::Vector3D hitpos = theSurface.localToGlobal(prd->localPosition());
297
298 const Amg::Vector3D& pos(hitpos);
299 return pos;
300}
301
302//____________________________________________________________________
307
308//____________________________________________________________________
313
314
315//____________________________________________________________________
317{
318 return positionPRD();
319}
320
321//____________________________________________________________________
323{
324 if (m_d->sepDetailed&&m_d->sepDetailed->getNumChildren()>0) {
325 //For efficiency/consistency we simply copy the transform from the
326 //inventor transformation (only loose slight precision in the
327 //double->float->double conversions):
328 SoTransform * transform = static_cast<SoTransform*>(m_d->sepDetailed->getChild(0));
329 float tx, ty, tz;
330 transform->translation.getValue().getValue(tx,ty,tz);
331 SbVec3f so_rotaxis;
332 float so_rotangle;
333 transform->rotation.getValue().getValue(so_rotaxis, so_rotangle);
334 float rx, ry, rz;
335 so_rotaxis.getValue(rx,ry,rz);
336 Amg::Vector3D axis(rx,ry,rz);
337// Amg::AngleAxis3D angleAxis = Amg::getRotation3DfromAngleAxis( so_rotangle, axis );
338// Amg::Rotation3D rot;
339// rot = angleAxis;
340 Amg::Rotation3D rot = Amg::getRotation3DfromAngleAxis( so_rotangle, axis );
341 return Amg::Translation3D(tx,ty,tz) * rot;
342 }
343 std::cout<<"VP1 PRDHandleBase Warning: getTransform_CLHEP called at inopportune moment!!"<<std::endl;
344
345 //NB: Some code duplicated here and in the createTransform() method.
346
347 const Trk::PrepRawData * prd = getPRD();
348 if (!prd) {
349 return Amg::Transform3D::Identity();
350 }
351 const Trk::Surface& theSurface = prd->detectorElement()->surface(prd->identify());
352 Amg::Vector3D theHitGPos;
354 // for tubes, should use position of center of tube (if drawing full tube)
355 theHitGPos= Amg::Vector3D(theSurface.center());
356 } else {
357 // for clusters or short tubes, use position of hit.
358 theHitGPos = theSurface.localToGlobal(prd->localPosition()); //theSurface 'new s' a Vector3D and returns pointer
359 }
360
361// CLHEP::Hep3Vector t(theSurface.transform().getTranslation());
362// return HepGeom::Transform3D( HepGeom::Translate3D(theHitGPos->x()-t.x(),theHitGPos->y()-t.y(),theHitGPos->z()-t.z()) * (theSurface.transform()) );
365 Amg::Translation3D transl = Amg::Translation3D(theHitGPos.x()-t.x(), theHitGPos.y()-t.y(), theHitGPos.z()-t.z());
366 Amg::Transform3D transf = transl * (theSurface.transform());
367 return transf;
368}
369
370//____________________________________________________________________
372{
373 //NB: Some code duplicated here and in the getTransform_CLHEP() method.
374 const Trk::PrepRawData * prd = getPRD();
375 if (!prd) {
376 std::cerr<<"PRDHandleBase::createTransform() No prd!"<<std::endl;
377 return new SoTransform;
378 }
379 const Trk::Surface& theSurface = prd->detectorElement()->surface(prd->identify());
380 SoTransform * theHitTransform = VP1LinAlgUtils::toSoTransform(theSurface.transform());
381
382 Amg::Vector3D theHitGPos;
384 // for tubes, should use position of center of tube (if drawing full tube)
385 theHitGPos= Amg::Vector3D (theSurface.center());
386 } else {
387 // for strips, clusters or short tubes, use position of hit.
388 theHitGPos = theSurface.localToGlobal(prd->localPosition());
389 }
390 if ((theHitGPos)[0]!=(theHitGPos)[0] || (theHitGPos)[1]!=(theHitGPos)[1] || (theHitGPos)[2]!=(theHitGPos)[2]){
391 std::cerr<<"PRDHandleBase::createTransform() NaN in globalposition"<<std::endl;
392 }
393 theHitTransform->translation.setValue((theHitGPos)[0], (theHitGPos)[1], (theHitGPos)[2]);
394 return theHitTransform;
395}
396
397//____________________________________________________________________
399{
400 double hlw = colhandle->highLightWeight();
401 //Get most frequent special case (i.e. no highlighting ) out of the
402 //way first for efficiency:
403 if (colhandle->colourMethod()!=PRDCollHandleBase::ByTechOnly) {
404 std::map<SoMaterial*,double> materials;
405 //-> Retrieve tracks/segments.
407 if (ts) {
408 //-> Add all materials from tracks as appropriate
409 if (colhandle->colourByTracks()) {
410 for (unsigned i = 0; i < ts->tracks.size(); ++i) {
411 SoMaterial * mat = theclass->common()->trackAndSegmentHelper()->trackMaterial(ts->tracks[i]);
412 if (mat)
413 materials[mat]=1.0;
414 else
415 std::cout<< "PRDHandleBase ERROR: Did not find track material!"<<std::endl;
416 }
417 }
418 //-> Add all materials from segments as appropriate
419 if (colhandle->colourBySegments()) {
420 for (unsigned i = 0; i < ts->segments.size(); ++i) {
421 SoMaterial * mat = theclass->common()->trackAndSegmentHelper()->segmentMaterial(ts->segments[i]);
422 if (mat)
423 materials[mat]=1.0;
424 else
425 std::cout<< "PRDHandleBase ERROR: Did not find segment material (2)!"<<std::endl;
426 }
427 }
428 if (hlw>0.0&&colhandle->highLightOutliers()) {
429 //Add outliers (if colourbytracks) + a highlightmaterial, all with appropriate weights.
430 if (colhandle->colourByTracks()&&!ts->tracks_outliers.empty()) {
431 if (hlw>999.0) {
432 materials[colhandle->highLightMaterial()] = ts->tracks_outliers.size();
433 } else {
434 for (unsigned i = 0; i < ts->tracks_outliers.size(); ++i) {
435 SoMaterial * mat = theclass->common()->trackAndSegmentHelper()->trackMaterial(ts->tracks_outliers[i]);
436 if (mat)
437 materials[mat]=1.0/(hlw+1.0);
438 else
439 std::cout<< "PRDHandleBase ERROR: Did not find track material (3)!"<<std::endl;
440 }
441 materials[colhandle->highLightMaterial()] = ts->tracks_outliers.size()*hlw/(hlw+1.0);
442 }
443 }
444 } else {
445 //Just add materials from outliers - and see if we need highlighting also.
446 if (colhandle->colourByTracks()) {
447 for (unsigned i = 0; i < ts->tracks_outliers.size(); ++i) {
448 SoMaterial * mat = theclass->common()->trackAndSegmentHelper()->trackMaterial(ts->tracks_outliers[i]);
449 if (mat)
450 materials[mat]=1.0;
451 else
452 std::cout<< "PRDHandleBase ERROR: Did not find track material (4)!"<<std::endl;
453 }
454 }
455 if (hlw>0.0&&!colhandle->highLightOutliers()&&theclass->highLight()) {
456 unsigned ntrackssegments= (colhandle->colourByTracks()?ts->tracks.size()+ts->tracks_outliers.size():0)
457 +(colhandle->colourBySegments()?ts->segments.size():0);
458 if (ntrackssegments)
459 materials[colhandle->highLightMaterial()] = hlw*ntrackssegments;
460 }
461 }
462 if (!materials.empty())
463 return theclass->common()->materialMixer()->getMixedMaterial(materials);
464 }
465 }
466
467
468 //OK, just use the tech colour - and possibly some non-outlier-highlighting.
469 if (hlw>0.0&&!colhandle->highLightOutliers()&&theclass->highLight()) {
470 if (hlw>999.0)
471 return colhandle->highLightMaterial();
472 return theclass->common()->materialMixer()->getMixedMaterial(colhandle->highLightMaterial(),hlw,colhandle->material(),1.0);
473 } else {
474 return colhandle->material();
475 }
476}
static Double_t rz
SoMaterial * currentmaterial
SoMaterial * determineMaterial(PRDHandleBase *)
void attach3DObjects(PRDHandleBase *)
VP1ExtraSepLayerHelper * sephelper_lod_simple
static Amg::Vector3D positionPRD(const Trk::PrepRawData *prd)
SoSeparator * sepSimple
void rebuild3DObjects(PRDHandleBase *)
PRDCollHandleBase * colhandle
SoSeparator * sepDetailed
VP1ExtraSepLayerHelper * sephelper_lod_detail
virtual const Trk::PrepRawData * getSecondPRD() const
virtual const Trk::PrepRawData * getPRD() const =0
virtual ~PRDHandleBase()
PRDSysCommonData * m_common
virtual bool transformUsesSurfacePositionOnly() const
virtual void buildShapes(SoNode *&shape_simple, SoNode *&shape_detailed)=0
void setVisible(bool)
virtual int regionIndex()
SoSeparator * sepDetailed() const
virtual SoTransform * createTransform() const
Amg::Transform3D getTransform_CLHEP() const
Amg::Vector3D positionPRD() const
virtual QStringList clicked() const
PRDHandleBase(PRDCollHandleBase *)
PRDSysCommonData * common() const
virtual bool inMuonChamber() const
virtual bool highLight() const
PRDCollHandleBase * collHandle() const
virtual Amg::Vector3D center() const
virtual GeoPVConstLink parentMuonChamberPV() const
Amg::Vector3D positionSecondPRD() const
SoSeparator * sepSimple() const
TouchedMuonChamberHelper * touchedMuonChamberHelper() const
HitsSoNodeManager * nodeManager() const
PRDTrackSegmentHelper * trackAndSegmentHelper() const
VP1SoMaterialMixer * materialMixer() const
void registerTransform2Handle(SoTransform *transform, PRDHandleBase *handle)
SoMaterial * trackMaterial(const Trk::Track *) const
const TracksAndSegments * tracksAndSegments(const Trk::PrepRawData *)
SoMaterial * segmentMaterial(const Trk::Segment *) const
void decrementNumberOfObjectsForPV(const GeoPVConstLink &chamberPV)
void incrementNumberOfObjectsForPV(const GeoPVConstLink &chamberPV)
virtual const TrkDetElementBase * detectorElement() const =0
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
Abstract Base Class for tracking surfaces.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const =0
Specified by each surface type: LocalToGlobal method without dynamic memory allocation.
virtual const Surface & surface() const =0
Return surface associated with this detector element.
static SoTransform * toSoTransform(const HepGeom::Transform3D &, SoTransform *t=0)
SoMaterial * getMixedMaterial(const std::set< SoMaterial * > &)
int ts
Definition globals.cxx:24
Amg::Vector3D getTranslationVectorFromTransform(const Amg::Transform3D &tr)
Get the Translation vector out of a Transformation.
Eigen::Quaternion< double > Rotation3D
Eigen::Affine3d Transform3D
Amg::Rotation3D getRotation3DfromAngleAxis(double angle, Amg::Vector3D &axis)
get a AngleAxis from an angle and an axis.
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D