ATLAS Offline Software
VP1People.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
7 // //
8 // Implementation of class VP1People //
9 // //
10 // Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch> //
11 // Initial version: November 2021 //
12 // //
14 
16 
17 #include "VP1HEPVis/SbPolyhedron.h"
19 
20 #include <Inventor/nodes/SoMaterial.h>
21 #include <Inventor/nodes/SoMaterialBinding.h>
22 #include <Inventor/nodes/SoCube.h>
23 #include <Inventor/nodes/SoSeparator.h>
24 #include <Inventor/nodes/SoTransform.h>
25 #include <Inventor/nodes/SoTranslation.h>
26 #include <Inventor/nodes/SoRotationXYZ.h>
27 #include <Inventor/nodes/SoScale.h>
28 #include <Inventor/SbViewportRegion.h>
29 #include <Inventor/actions/SoGetBoundingBoxAction.h>
30 #include <Inventor/VRMLnodes/SoVRMLMaterial.h>
31 
32 #include <Inventor/actions/SoSearchAction.h>
33 #include <Inventor/actions/SoWriteAction.h>
34 #include <Inventor/nodes/SoSeparator.h>
35 #include <Inventor/nodes/SoTexture2.h>
36 #include <Inventor/SoDB.h>
37 #include <Inventor/SoInput.h>
38 #include <Inventor/SoOutput.h>
39 
40 #include <QFile>
41 #include <QFileInfo>
42 #include <QTemporaryDir>
43 
44 #include <algorithm>
45 #include <vector>
46 
47 #ifdef BUILDVP1LIGHT
48  #include "CLHEP/Units/SystemOfUnits.h"
49  #define SYSTEM_OF_UNITS CLHEP
50 #else
51  #include "GaudiKernel/SystemOfUnits.h"
52  #define SYSTEM_OF_UNITS Gaudi::Units
53 #endif
54 
55 //____________________________________________________________________
57 public:
58  Imp(VP1People *,
59  SoMaterial * mat,
60  SoSeparator * attachsep);
62  SoMaterial * material;
63  SoSeparator * attachSep;
64 
65  SoSeparator* loadModel(const std::string& fpath);
66  double getScaleFactor(SoNode* node, double desiredHeight);
67 
68  bool shown;
69  SbColor4f colourAndTransp;
70  double zpos;
71  double vertpos;
72 
73  SoSeparator * sep;
74  SoTranslation * trans1;
75  SoTranslation * trans2;
76  SoTranslation * trans3;
77 
78  void updateFields();
79  void ensureInit3DObjects();
80  void updateColour();
81 
82 };
83 
84 //____________________________________________________________________
85 VP1People::VP1People(SoMaterial * mat,SoSeparator * attachsep,
86  IVP1System * sys,QObject * parent)
87  : QObject(parent), VP1HelperClassBase(sys,"VP1People"), m_d(new Imp(this,mat,attachsep))
88 {
89 }
90 
91 //____________________________________________________________________
93 {
94  setShown(false);
95  if (m_d->sep)
96  m_d->sep->unref();
97  if (m_d->trans1)
98  m_d->trans1->unref();
99  if (m_d->trans2)
100  m_d->trans2->unref();
101  m_d->material->unref();
102  m_d->attachSep->unref();
103  delete m_d;
104 }
105 
106 //____________________________________________________________________
107 VP1People::Imp::Imp(VP1People *tc,SoMaterial * mat,SoSeparator * as)
108  : theclass(tc), material(mat), attachSep(as), shown(false),
109  zpos(0),vertpos(0), sep(0), trans1(0), trans2(0), trans3(0)
110 {
111  material->ref();
112  attachSep->ref();
113 }
114 
115 
116 
117 //____________________________________________________________________
118 SoSeparator* VP1People::Imp::loadModel(const std::string& fpath)
119 {
120  SoDB::init();
121  SoInput myInput;
122  if (!myInput.openFile(fpath.c_str()))
123  exit (1);
124  SoSeparator *model = SoDB::readAll(&myInput);
125  if (model == NULL)
126  exit (1);
127 
128  unsigned int nChildren = model->getNumChildren();
129  std::cout << "nChildren: " << nChildren << std::endl;
130  for (unsigned int i=0; i < nChildren; ++i) {
131  const SoNode* node = model->getChild(i);
132  std::cout << "node " << i << ": " << node << std::endl;
133  if (node->getTypeId() == SoVRMLMaterial::getClassTypeId()) {
134  std::cout << "Found a SoVRMLMaterial node!\n";
135  SoNode * matvrmlnode = (SoVRMLMaterial *)node; // safe downward cast, knows the type
136  std::cout << "Material node: " << matvrmlnode << std::endl;
137  }
138  }
139 
140  // WIP
141  /*
142  SoSearchAction sa;
143  sa.setType(SoVRMLMaterial::getClassTypeId());
144  sa.setInterest(SoSearchAction::ALL);
145  sa.setSearchingAll(TRUE);
146  sa.apply(model);
147  SoPathList & pl = sa.getPaths();
148  SbDict namedict;
149  double plLen = pl.getLength();
150  std::cout << "plLength: " << plLen << std::endl;
151 
152  for (int i = 0; i < plLen; i++) {
153 
154  SoFullPath * p = (SoFullPath*) pl[i];
155 
156  if (p->getTail()->isOfType(SoVRMLMaterial::getClassTypeId())) {
157 
158  std::cout << "Found a SoVRMLMaterial node in Search!\n";
159  SoVRMLMaterial* vmat = (SoVRMLMaterial*) p->getTail();
160 
161  if (vmat->filename.getValue().getLength()) {
162  SbName name = tex->filename.getValue().getString();
163  unsigned long key = (unsigned long) ((void*) name.getString());
164  void * tmp;
165  if (!namedict.find(key, tmp)) {
166  // new texture. just insert into list
167  (void) namedict.enter(key, tex);
168  }
169  else if (tmp != (void*) tex) { // replace with node found in dict
170  SoGroup * parent = (SoGroup*) p->getNodeFromTail(1);
171  int idx = p->getIndexFromTail(0);
172  parent->replaceChild(idx, (SoNode*) tmp);
173  }
174  }
175  }
176  }
177 
178  sa.reset();
179 
180  // output fixed scene to stdout
181  SoOutput out;
182  SoWriteAction wa(&out);
183  wa.apply(model);
184  */
185 
186  return model;
187 }
188 
189 
190 
191 
192 //
193 double VP1People::Imp::getScaleFactor(SoNode* node, double desiredHeight)
194 {
195 
196  // Get the global BoundingBox of the imported model.
197  // NOTE:
198  // SoGet-BoundingBoxAction is typically called on a path,
199  // which enables you to obtain a bounding box for a specific object in world coordinates.
200  // This action returns an SbBox3f,
201  // which specifies a 3D box aligned with the x-, y-, and z-axes in world coordinate space.
202  SbViewportRegion dummyViewport; // we need one just for creating the action
203  SoGetBoundingBoxAction bboxAction(dummyViewport);
204  bboxAction.apply(node);
205  SbXfBox3f xfbox = bboxAction.getXfBoundingBox();
206  SbBox3f box = xfbox.project();
207  float minx, miny, minz, maxx, maxy, maxz;
208  box.getBounds(minx, miny, minz, maxx, maxy, maxz);
209  float cx,cy,cz;
210  box.getCenter().getValue(cx,cy,cz);
211 
212  // get the height of the model (it's along Y axis)
213  float heightModel = (maxy - miny);
214  // set the desired final height for the model
215  float heightDesired = desiredHeight;
216  // get the required scale scale factor
217  double scaleFactor = heightDesired / heightModel;
218 
219  /*
220  // DEBUG MSG
221  std::cout << miny << ", " << maxy
222  << ", heightModel: " << heightModel
223  << ", heightDesired: " << heightDesired
224  << ", scaleFactor: " << scaleFactor
225  << std::endl;
226  */
227  return scaleFactor;
228 }
229 
230 
231 //____________________________________________________________________
233 {
234  if (sep)
235  return;
236  theclass->messageVerbose("Building 3D objects");
237  sep = new SoSeparator; sep->ref();
238  sep->addChild(material);
239 
240 
241  // Create people:
242  // at first we need to copy the 3D file in the Qt resources file to the local filesystem
243  // for the SoQt load method to be able to load it
244  // Then, we load the model into the Coin geometry tree
245  QTemporaryDir tempDir;
246  QFile w1 = QFile(":/vp1/data/models/worker1.wrl");
247  QFile w2 = QFile(":/vp1/data/models/worker2.wrl");
248  SoSeparator* worker1 = nullptr;
249  SoSeparator* worker2 = nullptr;
250  if (tempDir.isValid()) {
251  const QString tempFile1 = tempDir.path() + "/worker1.wrl";
252  if ( w1.copy(tempFile1) ) {
253  worker1 = loadModel( tempFile1.toStdString() );
254  } else {
255  std::cout << "ERROR!! QFile copy of Worker1 was NOT successful!\n";
256  }
257  const QString tempFile2 = tempDir.path() + "/worker2.wrl";
258  if ( w2.copy(tempFile2) ) {
259  worker2 = loadModel( tempFile2.toStdString() );
260  } else {
261  std::cout << "ERROR!! QFile copy of Worker2 was NOT successful!\n";
262  }
263  } else {
264  std::cout << "ERROR!! TempDir is NOT valid!\n";
265  }
266  if (worker1 == nullptr) {
267  std::cout << "\n\nERROR! The 3D model Worker1 could not be loaded!\n\n";
268  exit(1);
269  }
270  if (worker2 == nullptr) {
271  std::cout << "\n\nERROR! The 3D model Worker2 could not be loaded!\n\n";
272  exit(1);
273  }
274 
275  // TEST CODE with a test shape
276  //SoCube* box = new SoCube(); // test shape
277  //worker1->materialBinding=SoMaterialBinding::OVERALL;
278  //SoMaterialBinding::OVERALL;
279  //
280  // get the required scale factor for the model
281  double scaleFactor1 = getScaleFactor(worker1, 1.80*SYSTEM_OF_UNITS::m);
282  double scaleFactor2 = getScaleFactor(worker2, 1.80*SYSTEM_OF_UNITS::m);
283 
284  // set a scale transformation to apply the required scale factor:
285  SoScale* myScale1 = new SoScale();
286  myScale1->scaleFactor.setValue(scaleFactor1, scaleFactor1, scaleFactor1);
287  SoScale* myScale2 = new SoScale();
288  myScale2->scaleFactor.setValue(scaleFactor2, scaleFactor2, scaleFactor2);
289 
290  // Translation for people models
291  trans1 = new SoTranslation;
292  trans1->ref();
293  trans2 = new SoTranslation;
294  trans2->ref();
295  trans3 = new SoTranslation;
296  trans3->ref();
297 
298  // rotate the model around the Y axis
299  SoRotationXYZ * rotY = new SoRotationXYZ();
300  rotY->axis=SoRotationXYZ::Y;
301  rotY->angle = 45*SYSTEM_OF_UNITS::deg;
302 
303  SoVRMLMaterial* matVRML = new SoVRMLMaterial();
304  matVRML->diffuseColor.setValue(0., 1., 1.);
305 
306  // create a separator for the scaled/rotated model,
307  // then
308  // create a separator for the translated model
309  SoSeparator* sepScaledWorker1 = new SoSeparator();
310  sepScaledWorker1->addChild(matVRML);
311  sepScaledWorker1->addChild(myScale1);
312  sepScaledWorker1->addChild(rotY);
313  sepScaledWorker1->addChild(worker1);
314  //sepScaledWorker1->addChild(box); // test shape
315  SoSeparator* sepWorker1 = new SoSeparator();
316  sepWorker1->addChild(trans1);
317  sepWorker1->addChild(sepScaledWorker1);
318 
319  SoSeparator* sepScaledWorker2 = new SoSeparator();
320  sepScaledWorker2->addChild(myScale2);
321  sepScaledWorker2->addChild(rotY);
322  sepScaledWorker2->addChild(worker2);
323  SoSeparator* sepWorker2 = new SoSeparator();
324  sepWorker2->addChild(trans2);
325  sepWorker2->addChild(sepScaledWorker2);
326 
327  SoTranslation* xt = new SoTranslation();
328  xt->translation.setValue(2*SYSTEM_OF_UNITS::m, 0., 1*SYSTEM_OF_UNITS::m);
329  SoSeparator* sepWorker3 = new SoSeparator();
330  sepWorker3->addChild(trans3);
331  sepWorker3->addChild(sepScaledWorker1);
332  sepWorker3->addChild(xt);
333  sepWorker3->addChild(sepScaledWorker2);
334 
335  // add the scaled model to the scenegraph
336  sep->addChild(sepWorker1);
337  sep->addChild(sepWorker2);
338  sep->addChild(sepWorker3);
339 }
340 
341 //____________________________________________________________________
343 {
344  ensureInit3DObjects();
345  theclass->messageVerbose("Updating fields");
346  trans1->translation.setValue(0, vertpos, zpos); // x,y,z
347  trans2->translation.setValue(4*SYSTEM_OF_UNITS::m, vertpos, zpos); // x,y,z
348  trans3->translation.setValue(8*SYSTEM_OF_UNITS::m, vertpos, zpos-10*SYSTEM_OF_UNITS::m); // x,y,z
349 }
350 
351 //____________________________________________________________________
353 {
354  theclass->messageVerbose("Updating packed colour");
355  if (!sep||sep->getNumChildren()<1)
356  return;
357  SoNode * n = sep->getChild(0);
358  if (!n||n->getTypeId()!=SoVRMLMaterial::getClassTypeId())
359  return;
360 
361  SoVRMLMaterial* matVRML = static_cast<SoVRMLMaterial*>(n);
362  matVRML->diffuseColor.setValue( colourAndTransp.getValue() );
363 }
364 
365 //____________________________________________________________________
367 {
368  messageVerbose("Signal received: setShown("+str(b)+")");
369  if (m_d->shown==b)
370  return;
371  m_d->shown=b;
372  if (m_d->shown) {
373  m_d->updateFields();
374  if (m_d->attachSep->findChild(m_d->sep)<0)
375  m_d->attachSep->addChild(m_d->sep);
376  } else {
377  if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0)
378  m_d->attachSep->removeChild(m_d->sep);
379  }
380 }
381 
382 //____________________________________________________________________
383 void VP1People::setColourAndTransp(const SbColor4f&ct)
384 {
385  messageVerbose("Signal received in setColourAndTransp slot.");
386  if (m_d->colourAndTransp==ct)
387  return;
389  if (m_d->shown)
390  m_d->updateColour();
391 }
392 
393 //____________________________________________________________________
394 void VP1People::setZPos(const double&p)
395 {
396  messageVerbose("Signal received: setZPos("+str(p)+")");
397  if (m_d->zpos==p)
398  return;
399  m_d->zpos=p;
400  if (m_d->shown)
401  m_d->updateFields();
402 }
403 
404 //____________________________________________________________________
406 {
407  messageVerbose("Signal received: setVerticalPosition("+str(p)+")");
408  if (m_d->vertpos==p)
409  return;
410  m_d->vertpos=p;
411  if (m_d->shown)
412  m_d->updateFields();
413 }
VP1People::Imp
Definition: VP1People.cxx:56
VP1People::VP1People
VP1People(SoMaterial *mat, SoSeparator *attachsep, IVP1System *sys, QObject *parent=0)
Definition: VP1People.cxx:85
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
VP1People::m_d
Imp * m_d
Definition: VP1People.h:45
mat
GeoMaterial * mat
Definition: LArDetectorConstructionTBEC.cxx:53
VP1HelperClassBase::messageVerbose
void messageVerbose(const QString &) const
Definition: VP1HelperClassBase.cxx:78
CSV_InDetExporter.new
new
Definition: CSV_InDetExporter.py:145
deg
#define deg
Definition: SbPolyhedron.cxx:17
VP1People
Definition: VP1People.h:27
VP1People::setVerticalPosition
void setVerticalPosition(const double &)
Definition: VP1People.cxx:405
VP1People::Imp::attachSep
SoSeparator * attachSep
Definition: VP1People.cxx:63
VP1String::str
static QString str(const QString &s)
Definition: VP1String.h:49
VP1People::Imp::material
SoMaterial * material
Definition: VP1People.cxx:62
mapkey::sys
@ sys
Definition: TElectronEfficiencyCorrectionTool.cxx:42
VP1People::Imp::trans3
SoTranslation * trans3
Definition: VP1People.cxx:76
VP1People::setShown
void setShown(bool)
Definition: VP1People.cxx:366
VP1People::Imp::getScaleFactor
double getScaleFactor(SoNode *node, double desiredHeight)
Definition: VP1People.cxx:193
SoPolyhedron.h
PlotCalibFromCool.cx
cx
Definition: PlotCalibFromCool.py:666
IVP1System
Definition: IVP1System.h:36
xt
#define xt
lumiFormat.i
int i
Definition: lumiFormat.py:92
VP1People::Imp::shown
bool shown
Definition: VP1People.cxx:68
VP1People::Imp::loadModel
SoSeparator * loadModel(const std::string &fpath)
Definition: VP1People.cxx:118
beamspotman.n
n
Definition: beamspotman.py:731
VP1People::Imp::zpos
double zpos
Definition: VP1People.cxx:70
VP1People::Imp::sep
SoSeparator * sep
Definition: VP1People.cxx:73
test_pyathena.parent
parent
Definition: test_pyathena.py:15
calibdata.exit
exit
Definition: calibdata.py:236
VP1HelperClassBase
Definition: VP1HelperClassBase.h:28
calibdata.ct
ct
Definition: calibdata.py:418
VP1People::Imp::updateColour
void updateColour()
Definition: VP1People.cxx:352
Monitored::Y
@ Y
Definition: HistogramFillerUtils.h:24
grepfile.sep
sep
Definition: grepfile.py:38
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
VP1People::setZPos
void setZPos(const double &)
Definition: VP1People.cxx:394
python.PyKernel.init
def init(v_theApp, v_rootStream=None)
Definition: PyKernel.py:45
PlotCalibFromCool.cy
cy
Definition: PlotCalibFromCool.py:667
correlationModel::model
model
Definition: AsgElectronEfficiencyCorrectionTool.cxx:46
VP1People::Imp::colourAndTransp
SbColor4f colourAndTransp
Definition: VP1People.cxx:69
VP1People::Imp::vertpos
double vertpos
Definition: VP1People.cxx:71
VP1People::Imp::theclass
VP1People * theclass
Definition: VP1People.cxx:61
VP1People::Imp::Imp
Imp(VP1People *, SoMaterial *mat, SoSeparator *attachsep)
Definition: VP1People.cxx:107
VP1People::Imp::updateFields
void updateFields()
Definition: VP1People.cxx:342
VP1People::Imp::trans2
SoTranslation * trans2
Definition: VP1People.cxx:75
SbPolyhedron.h
VP1People::Imp::ensureInit3DObjects
void ensureInit3DObjects()
Definition: VP1People.cxx:232
VP1People.h
node
Definition: memory_hooks-stdcmalloc.h:74
VP1People::setColourAndTransp
void setColourAndTransp(const SbColor4f &)
Definition: VP1People.cxx:383
VP1People::~VP1People
virtual ~VP1People()
Definition: VP1People.cxx:92
VP1People::Imp::trans1
SoTranslation * trans1
Definition: VP1People.cxx:74