00001 #include "Iguana/Inventor/interface/IgSoRectColHist.h"
00002 #include <Inventor/nodes/SoIndexedFaceSet.h>
00003 #include <Inventor/nodes/SoShapeHints.h>
00004 #include <Inventor/nodes/SoMaterial.h>
00005 #include <Inventor/nodes/SoIndexedLineSet.h>
00006 #include <Inventor/nodes/SoVertexProperty.h>
00007
00008 #include <Inventor/SbLinear.h>
00009
00010 #include <math.h>
00011 #include <iostream>
00012
00013
00014
00015 const unsigned IgSoRectColHist::IN = 0;
00016 const unsigned IgSoRectColHist::OUT = 1;
00017
00018
00019
00020
00021
00022 SO_KIT_SOURCE (IgSoRectColHist);
00023
00024
00025
00026
00027
00028 void
00029 IgSoRectColHist::initClass (void)
00030 { SO_KIT_INIT_CLASS (IgSoRectColHist, IgSoShapeKit, "IgSoShapeKit"); }
00031
00032
00033 IgSoRectColHist::IgSoRectColHist ()
00034 : m_barrelDeltaEta (0.f),
00035 m_barrelMaxEta (0.f),
00036 m_endcapDeltaTheta (0.f),
00037 m_endcapMaxTheta (0.f),
00038 m_deltasSet (false)
00039 {
00040 SO_KIT_CONSTRUCTOR (IgSoRectColHist);
00041
00042
00043 SO_KIT_ADD_FIELD (radiusZ, (10.f));
00044 SO_KIT_ADD_FIELD (radiusR, (5.f));
00045 SO_KIT_ADD_FIELD (offsetR, (0.f));
00046 SO_KIT_ADD_FIELD (offsetZ, (0.f));
00047 SO_KIT_ADD_FIELD (numR, (10));
00048 SO_KIT_ADD_FIELD (numZ, (10));
00049 SO_KIT_ADD_FIELD (energies, (0.f));
00050 SO_KIT_ADD_FIELD (layer, (0.f));
00051 SO_KIT_ADD_FIELD (center, (SbVec3f (layer.getValue (), 0.f, 0.f)));
00052 SO_KIT_ADD_FIELD (faceColors, (SbColor (0.f, 0.f, 0.f)));
00053 SO_KIT_ADD_FIELD (lineColor, (SbColor (0.f, 0.f, 0.f)));
00054 SO_KIT_ADD_FIELD (barrelMaxEta, (0.f));
00055 SO_KIT_ADD_FIELD (beamPipeTheta, (0.f));
00056 SO_KIT_ADD_FIELD (endcapMaxTheta, (0.f));
00057
00058 SO_KIT_ADD_FIELD (logScale, (FALSE));
00059 SO_KIT_ADD_FIELD (scaleFactor, (1.f));
00060 SO_KIT_ADD_FIELD (maxDist, (0.f));
00061
00062
00063
00064 SO_KIT_ADD_CATALOG_ENTRY (shapeHints, SoShapeHints, FALSE, separator,\x0, TRUE);
00065 SO_KIT_ADD_CATALOG_ENTRY (faceSet, SoIndexedFaceSet, FALSE, separator,\x0, TRUE);
00066
00067
00068
00069
00070 SO_KIT_ADD_CATALOG_ENTRY (lineSet, SoIndexedLineSet, FALSE, separator,\x0, TRUE);
00071
00072
00073
00074
00075 SO_KIT_INIT_INSTANCE ();
00076 setUpConnections (true, true);
00077
00078 faceColors.set1Value (0, SbVec3f (1.f, 0.f, 0.f));
00079 faceColors.set1Value (1, SbVec3f (0.f, 1.f, 0.f));
00080 faceColors.set1Value (2, SbVec3f (0.f, 0.f, 1.f));
00081 faceColors.set1Value (3, SbVec3f (1.f, 1.f, 0.f));
00082 }
00083
00084 std::vector<int>
00085 IgSoRectColHist::assignIndices (std::vector<std::vector<float> >& localEnergies, std::vector<int>& colorIndices)
00086 {
00087
00088
00089
00090 std::vector<int> faceIndices;
00091 unsigned count = 0;
00092 for (unsigned i = 0; i < localEnergies[IN].size (); i++)
00093 {
00094 if (localEnergies[IN][i] != 0.f)
00095 {
00096 faceIndices.push_back (count);
00097 faceIndices.push_back (count + 1);
00098 faceIndices.push_back (count + 2);
00099 faceIndices.push_back (count + 3);
00100 faceIndices.push_back (count);
00101 faceIndices.push_back (SO_END_FACE_INDEX);
00102 count += 4;
00103 colorIndices.push_back ((localEnergies[IN][i] > 0.f) ? (0) : (1));
00104 }
00105 if (localEnergies[OUT][i] != 0.f)
00106 {
00107 faceIndices.push_back (count);
00108 faceIndices.push_back (count + 1);
00109 faceIndices.push_back (count + 2);
00110 faceIndices.push_back (count + 3);
00111 faceIndices.push_back (count);
00112 faceIndices.push_back (SO_END_FACE_INDEX);
00113 count += 4;
00114 colorIndices.push_back ( (localEnergies[OUT][i] >= 0.f) ? (2) : (3));
00115 }
00116 }
00117 return faceIndices;
00118 }
00119
00120 IgSoRectColHist::n_placement
00121 IgSoRectColHist::findBinPlacement (const unsigned binIndex)
00122 {
00123
00124
00125
00126
00127 unsigned _numZ = numZ.getValue ();
00128 unsigned _numR = numR.getValue ();
00129
00130 if (binIndex < _numR/2) return RIGHT;
00131 else if (binIndex < _numR/2 + _numZ) return TOP;
00132 else if (binIndex < 3*_numR/2 + _numZ ) return LEFT;
00133 else if (binIndex < 3*_numR/2 + 2*_numZ ) return BOTTOM;
00134 else return RIGHT;
00135 }
00136
00137 SbVec3f
00138 IgSoRectColHist::projectPoint (const float energy, const SbVec3f& point, const SbVec3f& center)
00139 {
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 const float y = point[1] - center[1];
00150 const float z = point[2] - center[2];
00151 const float radius = calcLocalRadius (point, center);
00152 const float angle = atan2 (y, z);
00153
00154 return convertCoordinates (radius + energy, convertAngle (angle), center);
00155 }
00156
00157
00158
00159 SbVec3f
00160 IgSoRectColHist::convertCoordinates (const float radius, const float phi, const SbVec3f& center)
00161 {
00162 SbVec3f cartesianCoords;
00163 cartesianCoords[0] = layer.getValue ();
00164 cartesianCoords[1] = radius * sin (phi) + center[2];;
00165 cartesianCoords[2] = radius * cos (phi) + center[1];
00166 return cartesianCoords;
00167 }
00168
00169 int
00170 IgSoRectColHist::findMaxEnergyBin (std::vector<std::vector<float> >& energies)
00171 {
00172
00173 m_maxEnergy = 0.0f;
00174 int maxEnergyBin = -1;
00175 float totalE = 0.0f;
00176 const float numBins = energies[IN].size ();
00177
00178 for (unsigned i = 0; i < numBins; i++)
00179 {
00180 totalE = energies[IN][i] + energies[OUT][i];
00181 if (totalE > m_maxEnergy)
00182 {
00183 m_maxEnergy = totalE;
00184 maxEnergyBin = i;
00185 }
00186 }
00187 return maxEnergyBin;
00188 }
00189
00190 void
00191 IgSoRectColHist::calcLogEnergies (std::vector<std::vector<float> >& logEnergies)
00192 {
00193 for (unsigned i = 0; i < logEnergies[IN].size (); i++)
00194 {
00195 logEnergies[IN][i] = log ((logEnergies[IN][i] <= 0.0f) ? (1.0f) : (logEnergies[IN][i]));
00196 logEnergies[OUT][i] = log ((logEnergies[OUT][i] <= 0.0f) ? (1.0f) : (logEnergies[OUT][i]));
00197 }
00198 }
00199
00200 void
00201 IgSoRectColHist::scaleEnergies (std::vector<std::vector<float> >& energies)
00202 {
00203 const float _maxDist = maxDist.getValue ();
00204 float localScaleFactor = 1.0f;
00205
00206
00207 if (_maxDist > 0.f)
00208 {
00209 if (m_maxEnergy != 0.f)
00210 {
00211 localScaleFactor = _maxDist / m_maxEnergy;
00212 }
00213 else
00214 {
00215 std::cerr << "Maximum energy equals zero, no maxDist scaling is done!" << std::endl;
00216 }
00217 }
00218
00219 const float _scaleFactor = scaleFactor.getValue ();
00220
00221 if (_scaleFactor != 1.0f)
00222 {
00223 localScaleFactor = localScaleFactor * _scaleFactor;
00224 }
00225
00226 for (unsigned i = 0; i < energies[0].size (); i++)
00227 {
00228 energies[IN][i] = localScaleFactor * energies[IN][i];
00229 energies[OUT][i] = localScaleFactor * energies[OUT][i];
00230 }
00231 }
00232
00233 void
00234 IgSoRectColHist::setLogEnergies (std::vector<std::vector<float> >& energies)
00235 {
00236 int maxEnergyBin = -1;
00237 maxEnergyBin = findMaxEnergyBin (energies);
00238
00239
00240 if (logScale.getValue () && maxEnergyBin != -1)
00241 {
00242
00243 calcLogEnergies (energies);
00244 m_maxEnergy = energies[IN][maxEnergyBin] + energies[OUT][maxEnergyBin];
00245 }
00246 }
00247
00248 float
00249 IgSoRectColHist::calcLocalRadius (const SbVec3f& point, const SbVec3f& center) const
00250 {
00251
00252 const float y = point[1] - center[1];
00253 const float z = point[2] - center[2];
00254 return sqrt (y * y + z * z);
00255 }
00256
00257 SbVec3f
00258 IgSoRectColHist::calcAnglePoint (float angle, float y, float z)
00259 {
00260
00261
00262
00263
00264
00265
00266
00267
00268 const float _layer = layer.getValue ();
00269 SbLine fixedLine;
00270 SbVec3f point1 (_layer, y, z);
00271
00272 if (y == 0.f)
00273 {
00274 fixedLine.setValue (point1, SbVec3f (_layer, z, z));
00275 }
00276 else if (z == 0.f)
00277 {
00278 fixedLine.setValue (point1, SbVec3f (_layer, y, y));
00279 }
00280 else
00281 {
00282 return SbVec3f (_layer, y, z);
00283 }
00284
00285 SbVec3f test = convertCoordinates (1.f, angleToLeftHanded (angle), SbVec3f (_layer, 0.f, 0.f));
00286 SbLine movingLine (test, SbVec3f (_layer, 0.f, 0.f));
00287
00288 SbVec3f result;
00289 SbVec3f result2;
00290
00291 movingLine.getClosestPoints (fixedLine, result, result2);
00292 return result;
00293 }
00294
00295 float
00296 IgSoRectColHist::angleToLeftHanded (float rightHandedAngle)
00297 {
00298 return (2.f * M_PI - rightHandedAngle);
00299 }
00300
00301 void
00302 IgSoRectColHist::determineAngularDelta (void)
00303 {
00304
00305
00306 float _radiusZ = radiusZ.getValue ();
00307 float _radiusR = radiusR.getValue ();
00308 unsigned _numZ = numZ.getValue ();
00309 unsigned _numR = numR.getValue ();
00310 _radiusZ = (_radiusZ <= 0.f) ? (1.f) : (_radiusZ);
00311 _radiusR = (_radiusR <= 0.f) ? (1.f) : (_radiusR);
00312 _numZ = (_numZ == 0) ? (1) : (_numZ);
00313 _numR = (_numR == 0) ? (1) : (_numR);
00314
00315
00316
00317 m_barrelMaxEta = barrelMaxEta.getValue ();
00318 if (m_barrelMaxEta <= 0.f)
00319 {
00320 if (m_endcapMaxTheta <= 0.f)
00321 {
00322 m_barrelMaxEta = thetaToEta (M_PI/2.f - atan (_radiusZ/_radiusR));
00323 }
00324 else
00325 {
00326 m_barrelMaxEta = thetaToEta (m_endcapMaxTheta);
00327 }
00328 }
00329 m_barrelDeltaEta = m_barrelMaxEta / (_numZ / 2);
00330
00331
00332
00333 m_endcapMaxTheta = endcapMaxTheta.getValue ();
00334 if (m_endcapMaxTheta <= 0.f)
00335 {
00336 if (m_barrelMaxEta > 0.f)
00337 {
00338 m_endcapMaxTheta = etaToTheta (m_barrelMaxEta);
00339 }
00340 else
00341 {
00342 m_endcapMaxTheta = atan (_radiusR / _radiusZ);
00343 }
00344 }
00345 m_endcapDeltaTheta = (m_endcapMaxTheta - beamPipeTheta.getValue ()) / (_numR / 2);
00346 m_deltasSet = true;
00347 }
00348
00349 float
00350 IgSoRectColHist::etaToTheta (float eta)
00351 {
00352 return (2.f * atan (exp (- eta)));
00353 }
00354
00355 float
00356 IgSoRectColHist::thetaToEta (float theta)
00357 {
00358 return (-log (tan (theta/2.f)));
00359 }
00360
00361 float
00362 IgSoRectColHist::getBinAngle (unsigned _binNum, bool isLeftPoint)
00363 {
00364
00365 float result = 0.f;
00366
00367 if (!m_deltasSet) determineAngularDelta ();
00368
00369 unsigned _numZ = numZ.getValue ();
00370 unsigned _numR = numR.getValue ();
00371 _numZ = (_numZ == 0) ? (1) : (_numZ);
00372 _numR = (_numR == 0) ? (1) : (_numR);
00373 const unsigned binNum = (isLeftPoint) ? (_binNum + 1) : (_binNum);
00374
00375
00376
00377
00378
00379
00380
00381 if (_binNum < _numR/2)
00382 {
00383 result = binNum * m_endcapDeltaTheta + beamPipeTheta.getValue ();
00384 }
00385 else if (_binNum < (_numZ/2 + _numR/2))
00386 {
00387 const float tempEta = m_barrelMaxEta - (binNum - _numR/2) * m_barrelDeltaEta;
00388 result = ((tempEta < 0.f) ? (M_PI - etaToTheta (fabs (tempEta))) : (etaToTheta (tempEta)));
00389 }
00390 else if (_binNum < (_numZ + _numR/2))
00391 {
00392 const float tempEta = (binNum - (_numZ/2 + _numR/2)) * m_barrelDeltaEta;
00393 result = M_PI - etaToTheta (tempEta);
00394 }
00395 else if (_binNum < (_numZ + _numR))
00396 {
00397 result = (binNum - (_numZ + _numR/2)) * m_endcapDeltaTheta + M_PI - m_endcapMaxTheta;
00398 }
00399 else if (_binNum < (_numZ + 3*_numR/2))
00400 {
00401 result = (binNum - (_numR + _numZ)) * m_endcapDeltaTheta + beamPipeTheta.getValue () + M_PI;
00402 }
00403 else if (_binNum < (3*(_numZ+_numR)/2))
00404 {
00405 const float tempEta = m_barrelMaxEta - (binNum - (_numZ + 3*_numR/2)) * m_barrelDeltaEta;
00406 result = ((tempEta < 0.f) ? (M_PI - etaToTheta (fabs (tempEta))) : (etaToTheta (tempEta))) + M_PI;
00407 }
00408 else if (_binNum < (2*_numZ + 3*_numR/2))
00409 {
00410 const float tempEta = (binNum - (3*(_numZ+_numR)/2)) * m_barrelDeltaEta;
00411 result = 2.f * M_PI - etaToTheta (tempEta);
00412 }
00413 else
00414 {
00415 result = (binNum - (3*_numR/2 + 2*_numZ)) * m_endcapDeltaTheta + 2.f * M_PI - m_endcapMaxTheta;
00416 }
00417 return result;
00418 }
00419
00420 float
00421 IgSoRectColHist::convertAngle (float angle)
00422 {
00423
00424
00425
00426 float result;
00427 if (angle > (2.f * M_PI))
00428 {
00429 result = fmod (angle, 2 * M_PI);
00430 }
00431 else if (angle < 0.f)
00432 {
00433 result = (angle + 2 * M_PI);
00434 }
00435 else
00436 {
00437 result = angle;
00438 }
00439 return result;
00440 }
00441
00442 void
00443 IgSoRectColHist::calcBinCorner (unsigned i, SbVec3f& left, SbVec3f& right)
00444 {
00445
00446 float yCoord, zCoord;
00447 float _radiusR = radiusR.getValue ();
00448 float _radiusZ = radiusZ.getValue ();
00449
00450 switch (findBinPlacement (i))
00451 {
00452 case TOP:
00453 zCoord = 0.f;
00454 yCoord = -_radiusR;
00455 break;
00456
00457 case RIGHT:
00458 zCoord = _radiusZ;
00459 yCoord = 0.f;
00460 break;
00461
00462 case BOTTOM:
00463 zCoord = 0.f;
00464 yCoord = _radiusR;
00465 break;
00466
00467 default:
00468 zCoord = -_radiusZ;
00469 yCoord = 0.f;
00470 break;
00471 }
00472 left = calcAnglePoint (getBinAngle (i, true), yCoord, zCoord);
00473 right = calcAnglePoint (getBinAngle (i, false), yCoord, zCoord);
00474 }
00475
00476 void
00477 IgSoRectColHist::addOffset (SbVec3f& point, unsigned binNum)
00478 {
00479 if (offsetZ.getValue () == 0.f && offsetR.getValue () == 0.f) return;
00480
00481 SbVec3f offset (layer.getValue (), 0.f, 0.f);
00482 switch (findBinPlacement (binNum))
00483 {
00484 case TOP:
00485 offset[1] = - offsetR.getValue ();
00486 break;
00487
00488 case RIGHT:
00489 offset[2] = offsetZ.getValue ();
00490 break;
00491
00492 case BOTTOM:
00493 offset[1] = offsetR.getValue ();
00494 break;
00495
00496 default:
00497 offset[2] = - offsetZ.getValue ();
00498 break;
00499 }
00500 point = point + offset;
00501 }
00502
00503 void
00504 IgSoRectColHist::refresh (void)
00505 {
00506 const unsigned numOfBins = energies.getNum () / 2;
00507 const unsigned _numR = numR.getValue ();
00508 const unsigned _numZ = numZ.getValue ();
00509
00510 if (2*(_numR + _numZ) == numOfBins && (_numR * _numZ > 0))
00511 {
00512 SbVec3f inner[4];
00513 SbVec3f outer[4];
00514
00515
00516
00517 std::vector<std::vector<float> > localEnergies (2, std::vector<float> (numOfBins, 0.f));
00518 for (unsigned i = 0; i < numOfBins; i++)
00519 {
00520 localEnergies[IN][i] = energies[i];
00521 localEnergies[OUT][i] = energies[numOfBins + i];
00522 }
00523
00524 setLogEnergies (localEnergies);
00525 scaleEnergies (localEnergies);
00526
00527
00528
00529 SbVec3f leftPoint;
00530 SbVec3f rightPoint;
00531
00532
00533 SbVec3f zero (layer.getValue (), 0.f, 0.f);
00534 float leftRadius = 0.f;
00535 float rightRadius = 0.f;
00536 SbVec3f _center = center.getValue ();
00537 SbColor _lineColor = lineColor.getValue ();
00538 std::vector<SbVec3f> vertexData;
00539
00540
00541 for (unsigned i = 0; i < numOfBins; i++)
00542 {
00543
00544 if (localEnergies[0][i] == 0.0f && localEnergies[1][i] == 0.0f) continue;
00545
00546 calcBinCorner (i, leftPoint, rightPoint);
00547
00548 leftRadius = calcLocalRadius (leftPoint, zero);
00549 rightRadius = calcLocalRadius (rightPoint, zero);
00550
00551
00552
00553
00554 if (leftRadius < rightRadius)
00555 {
00556 inner[3] = rightPoint + _center;
00557 inner[0] = projectPoint (rightRadius - leftRadius, leftPoint, zero) + _center;
00558 }
00559 else
00560 {
00561 inner[0] = leftPoint + _center;
00562 inner[3] = projectPoint (leftRadius - rightRadius, rightPoint, zero) + _center;
00563 }
00564
00565
00566 inner[1] = projectPoint (localEnergies[0][i], inner[0], _center);
00567 inner[2] = projectPoint (localEnergies[0][i], inner[3], _center);
00568
00569 outer[0] = inner[1];
00570 outer[3] = inner[2];
00571
00572 outer[1] = projectPoint (localEnergies[1][i], outer[0], _center);
00573 outer[2] = projectPoint (localEnergies[1][i], outer[3], _center);
00574
00575
00576 for (unsigned j = 0; j < 4; j++)
00577 {
00578 addOffset (inner[j], i);
00579 addOffset (outer[j], i);
00580 }
00581
00582
00583 for (unsigned j = 0; j < 4; j++)
00584 {
00585
00586 if (localEnergies[0][i] != 0.f)
00587 {
00588 vertexData.push_back (inner[j]);
00589 }
00590 }
00591
00592 for (unsigned j = 0; j < 4; j++)
00593 {
00594 if (localEnergies[1][i] != 0.f)
00595 {
00596 vertexData.push_back (outer[j]);
00597 }
00598 }
00599 }
00600
00601
00602 SoShapeHints* shapeHints = new SoShapeHints;
00603 shapeHints->faceType = SoShapeHints::CONVEX;
00604 shapeHints->vertexOrdering = SoShapeHints::CLOCKWISE;
00605
00606 SoIndexedFaceSet* faceSet = new SoIndexedFaceSet;
00607 SoIndexedLineSet* lineSet = new SoIndexedLineSet;
00608
00609
00610 SoVertexProperty* vtx = new SoVertexProperty;
00611 vtx->materialBinding = SoMaterialBinding::PER_FACE_INDEXED;
00612
00613
00614 vtx->orderedRGBA.set1Value (0, faceColors[0].getPackedValue ());
00615 vtx->orderedRGBA.set1Value (1, faceColors[1].getPackedValue ());
00616 vtx->orderedRGBA.set1Value (2, faceColors[2].getPackedValue ());
00617 vtx->orderedRGBA.set1Value (3, faceColors[3].getPackedValue ());
00618 vtx->orderedRGBA.set1Value (4, _lineColor.getPackedValue ());
00619
00620
00621 vtx->vertex.setValues (0, vertexData.size (), &vertexData[0]);
00622
00623 std::vector<int> colorIndices;
00624 std::vector<int> faceIndices = assignIndices (localEnergies, colorIndices);
00625
00626
00627 faceSet->coordIndex.setValues (0, faceIndices.size (), &faceIndices[0]);
00628 faceSet->materialIndex.setValues (0, colorIndices.size (), &colorIndices[0]);
00629 lineSet->coordIndex.setValues (0, faceIndices.size (), &faceIndices[0]);
00630
00631
00632 if (!(_lineColor[0] == 0.f && _lineColor[1] == 0.f && _lineColor[2] == 0.f))
00633 {
00634 for (unsigned i = 0; i < colorIndices.size (); i++)
00635 {
00636 colorIndices[i] = 4;
00637 }
00638 }
00639 lineSet->materialIndex.setValues (0, colorIndices.size (), &colorIndices[0]);
00640
00641 faceSet->vertexProperty = vtx;
00642 lineSet->vertexProperty = vtx;
00643
00644 setPart ("shapeHints", shapeHints);
00645 setPart ("faceSet", faceSet);
00646 setPart ("lineSet", lineSet);
00647 }
00648 }
00649