OpenDAFF C++ API  v1.7
Directional Audio File Format
DAFFVizBalloonPlot.cpp
Go to the documentation of this file.
2 #include <DAFFUtils.h>
3 
4 // Todo: strip required
5 #include <vtkActor.h>
6 #include <vtkCellArray.h>
7 #include <vtkCellData.h>
8 #include <vtkContourFilter.h>
9 #include <vtkDoubleArray.h>
10 #include <vtkFloatArray.h>
11 #include <vtkFollower.h>
12 #include <vtkHedgeHog.h>
13 #include <vtkPointData.h>
14 #include <vtkPoints.h>
15 #include <vtkPolyData.h>
16 #include <vtkPolyDataMapper.h>
17 #include <vtkPolyDataNormals.h>
18 #include <vtkPolyLine.h>
19 #include <vtkLine.h>
20 #include <vtkPolygon.h>
21 #include <vtkProperty.h>
22 #include <vtkVectorText.h>
23 #include <vtkWarpScalar.h>
24 #include <vtkVectorText.h>
25 #include <vtkScalarBarActor.h>
26 #include <vtkColorTransferFunction.h>
27 #include <vtkTransform.h>
28 #include <vtkSmartPointer.h>
29 #include <vtkWindowedSincPolyDataFilter.h>
30 
31 #include <DAFF.h>
32 
33 #include <algorithm>
34 #include <assert.h>
35 
36 
37 namespace DAFFViz
38 {
39  BalloonPlot::BalloonPlot( SGNode* pParentNode, const DAFFContent* pContent )
40  : SGNode( pParentNode ),
41  m_pContent( pContent ),
42  m_iFrequency( 0 ),
43  m_iNumFrequencies( 0 ),
44  m_iScaling( SCALING_DECIBEL ),
45  m_dMin( 0.0 ), m_dMax( 1.0 ),
46  m_iChannel( 0 ),
47  m_bWarp( true ),
48  m_bNormalize( false ),
49  m_bNormalizeFreqsIndiv( false ),
50  m_bUseCustomRange( false ),
51  m_bUsePhaseAsColor( false )
52  {
53  init();
54  }
55 
57  : SGNode(),
58  m_pContent( pContent ),
59  m_iFrequency( 0 ),
60  m_iNumFrequencies( 0 ),
61  m_iScaling( SCALING_DECIBEL ),
62  m_dMin( 0.0 ), m_dMax( 1.0 ),
63  m_iChannel( 0 ),
64  m_bWarp( true ),
65  m_bNormalize( false ),
66  m_bNormalizeFreqsIndiv( false ),
67  m_bUseCustomRange( false ),
68  m_bUsePhaseAsColor( false )
69  {
70  init();
71  }
72 
74  {
75  RemoveActor( m_pPlotActor );
76  RemoveActor( m_pLabel );
77  RemoveActor( m_pProbe );
78  }
79 
80  void BalloonPlot::init()
81  {
82 
83  const DAFFProperties* pProps = m_pContent->getProperties();
84 
85  switch( pProps->getContentType() )
86  {
87  case DAFF_DFT_SPECTRUM:
88  m_iNumFrequencies = dynamic_cast< const DAFFContentDFT* >( m_pContent )->getNumDFTCoeffs();
89  break;
90 
94  m_iNumFrequencies = dynamic_cast< const DAFFContentMS* >( m_pContent )->getNumFrequencies();
95  break;
96  }
97 
98  bool bSouthPole = pProps->getBetaStart() == 0;
99  bool bNorthPole = pProps->getBetaEnd() == 180;
100  bool bAzimuthWrap = ( pProps->getAlphaStart() == 0 ) && ( pProps->getAlphaEnd() == 360 );
101 
102 
103 
104  // --= Sphere grid =--
105 
106  vtkSmartPointer< vtkPoints > points = vtkSmartPointer< vtkPoints >::New();
107  m_pNormals = vtkSmartPointer< vtkDoubleArray >::New();
108  m_pNormals->SetNumberOfComponents( 3 );
109  for( int i = 0; i < pProps->getNumberOfRecords(); i++ )
110  {
111  // TODO: Topologies: Rings, Patches, etc.
112  float phi, theta;
113  m_pContent->getRecordCoords( i, DAFF_OBJECT_VIEW, phi, theta );
114 
115  // Compute Cartesian points
116  double x, y, z;
117  sph2cart( phi, theta, x, y, z );
118  points->InsertPoint( i, x, y, z );
119  double n[ 3 ] = { -x, -y, -z }; // define flipped normals for warping
120  m_pNormals->InsertNextTuple( n );
121  }
122 
123 
124  // --= Faces =--
125 
126  vtkSmartPointer< vtkCellArray > cells = vtkSmartPointer< vtkCellArray >::New();
127  vtkIdType quadface[ 4 ];
128  vtkIdType triangleface[ 3 ];
129 
130  int iNumPoints = pProps->getNumberOfRecords();
131  int iAziPoints = pProps->getAlphaPoints();
132  int iElePoints = pProps->getBetaPoints();
133 
134  int iBodyEleRings = iElePoints - 1;
135  int iAziCount = ( bAzimuthWrap ? iAziPoints : iAziPoints - 1 );
136  if( bSouthPole ) iBodyEleRings--;
137  if( bNorthPole ) iBodyEleRings--;
138  int iBodyOffset = 0;
139  if( bSouthPole )
140  iBodyOffset = 1;
141 
142  // if there is only one azimuth point there would be no surface to draw, so lets draw a line
143  if( ( iAziPoints == 1 ) || ( iElePoints == 1 ) )
144  {
145  if( ( iAziPoints == 1 ) && ( iElePoints == 1 ) )
146  {
147  // we will not plot a single point
148  }
149  else
150  {
151  // add a point at center
152  points->InsertPoint( iNumPoints, 0, 0, 0 );
153 
154  for( int i = 0; i < iNumPoints; i++ )
155  {
156  triangleface[ 0 ] = i;
157  triangleface[ 1 ] = i + 1;
158  triangleface[ 2 ] = iNumPoints;
159 
160  for( int k = 0; k < 3; k++ )
161  assert( ( triangleface[ k ] >= 0 ) && ( triangleface[ k ] < iNumPoints + 1 ) );
162 
163  cells->InsertNextCell( 3, triangleface );
164  }
165 
166  }
167  }
168  else
169  {
170  // draw surfaces
171  if( bSouthPole )
172  {
173  /*
174  * If there is a south pole, this has index 0.
175  * The next record, one elevation step above has then index 1.
176  */
177 
178  iBodyOffset = 1;
179  for( int j = 0; j < iAziCount; j++ )
180  {
181  triangleface[ 0 ] = 0;
182  triangleface[ 1 ] = iBodyOffset + j;
183  triangleface[ 2 ] = iBodyOffset + ( j + 1 ) % iAziPoints;
184 
185  for( int k = 0; k < 3; k++ )
186  assert( ( triangleface[ k ] >= 0 ) && ( triangleface[ k ] < iNumPoints ) );
187 
188  cells->InsertNextCell( 3, triangleface );
189  }
190  };
191 
192  // Body
193  for( int i = 0; i < iBodyEleRings; i++ )
194  {
195  for( int j = 0; j < iAziCount; j++ )
196  {
197  quadface[ 0 ] = iBodyOffset + i*iAziPoints + j;
198  quadface[ 1 ] = iBodyOffset + i*iAziPoints + ( j + 1 ) % iAziPoints;
199  quadface[ 2 ] = iBodyOffset + ( i + 1 )*iAziPoints + ( j + 1 ) % iAziPoints;
200  quadface[ 3 ] = iBodyOffset + ( i + 1 )*iAziPoints + j;
201 
202  for( int k = 0; k < 4; k++ )
203  assert( ( quadface[ k ] >= 0 ) && ( quadface[ k ] < iNumPoints ) );
204 
205  cells->InsertNextCell( 4, quadface );
206  }
207  }
208 
209  // North pole
210 
211  if( bNorthPole )
212  {
213  /*
214  * If there is a north pole, this has the last index.
215  * The next record, one elevation step above has then index 1.
216  */
217 
218  for( int j = 0; j < iAziCount; j++ )
219  {
220  triangleface[ 0 ] = iNumPoints - 1;
221  triangleface[ 1 ] = iBodyOffset + iBodyEleRings*iAziPoints + j;
222  triangleface[ 2 ] = iBodyOffset + iBodyEleRings*iAziPoints + ( j + 1 ) % iAziPoints;
223 
224  for( int k = 0; k < 3; k++ )
225  assert( ( triangleface[ k ] >= 0 ) && ( triangleface[ k ] < pProps->getNumberOfRecords() ) );
226 
227  cells->InsertNextCell( 3, triangleface );
228  }
229  }
230  }
231 
232 
233  // --= VTK stuff =--
234  m_pPlotPolydata = vtkSmartPointer< vtkPolyData >::New();
235  m_pPlotPolydata->SetPoints( points );
236  m_pPlotPolydata->SetPolys( cells );
237 
238  // Set scalars of polydata
239  SetScalars();
240  m_pPlotPolydata->GetPointData()->SetActiveScalars( "magnitudes" );
241 
242  // Warp sphere
243  m_pWarp = vtkSmartPointer< vtkWarpScalar >::New();
244  m_pWarp->SetInputData( m_pPlotPolydata );
245  m_pWarp->UseNormalOff();
246 
247  m_pMapper = vtkSmartPointer< vtkPolyDataMapper >::New();
248  m_pMapper->SetScalarModeToUsePointFieldData();
249 
250  if( m_bWarp )
251  EnableWarp();
252  else
253  DisableWarp();
254 
255  SetUsePhaseAsColor( m_bUsePhaseAsColor );
256 
257  m_pPlotActor = vtkSmartPointer< vtkActor >::New();
258  m_pPlotActor->SetMapper( m_pMapper );
259 
260  m_pPlotActor->GetProperty()->SetInterpolationToGouraud();
261 
262  AddActor( m_pPlotActor );
263 
264  // Probe
265 
266  vtkSmartPointer< vtkPoints > points2 = vtkSmartPointer< vtkPoints >::New();
267  points2->SetNumberOfPoints( 2 );
268  points2->InsertPoint( 0, 0, 0, 0 );
269  points2->InsertPoint( 1, 0, -1, 0 );
270 
271  vtkSmartPointer< vtkCellArray >cells2 = vtkSmartPointer< vtkCellArray >::New();
272  vtkSmartPointer< vtkLine > line = vtkSmartPointer< vtkLine >::New();
273  line->GetPointIds()->SetId( 0, 0 );
274  line->GetPointIds()->SetId( 1, 1 );
275  cells2->InsertNextCell( line );
276 
277  vtkSmartPointer< vtkPolyData > polydata = vtkSmartPointer< vtkPolyData >::New();
278  polydata->SetPoints( points2 );
279  polydata->SetLines( cells2 );
280 
281  // Create a mapper and actor
282  vtkSmartPointer< vtkPolyDataMapper > mapper = vtkSmartPointer< vtkPolyDataMapper >::New();
283  mapper->SetInputData( polydata );
284 
285  m_pProbe = vtkSmartPointer< vtkActor >::New();
286  m_pProbe->SetMapper( mapper );
287  m_pProbe->VisibilityOff();
288 
289  AddActor( m_pProbe );
290 
291  // label the probe
292  m_pProbeLabel = vtkSmartPointer< vtkVectorText >::New();
293  std::ostringstream s;
294  s << "test";
295  m_pProbeLabel->SetText( s.str().c_str() );
296 
297  vtkSmartPointer< vtkPolyDataMapper >mapper2 = vtkSmartPointer< vtkPolyDataMapper >::New();
298  mapper2->AddInputConnection( m_pProbeLabel->GetOutputPort() );
299 
300  m_pLabel = vtkSmartPointer< vtkFollower >::New();
301  m_pLabel->SetMapper( mapper2 );
302  m_pLabel->SetScale( 0.03 );
303  m_pLabel->SetPosition( 0.02, -1.01, 0 );
304  m_pLabel->SetOrientation( -90, 0, -90 );
305  m_pLabel->GetProperty()->SetOpacity( 0.8 );
306  m_pLabel->VisibilityOff();
307 
308  AddActor( m_pLabel );
309 
310  }
311 
313  {
314  if( !m_pProbe )
315  return;
316 
317  double* pos = m_pProbe->GetPosition();
318  //double r = grad2rad();
319  double p = DAFFUtils::grad2rad( m_dProbeBeta );
320  double y = DAFFUtils::grad2rad( m_dProbeAlpha );
321 
322  // Translation matrix: to origin
323  vtkSmartPointer< vtkMatrix4x4 > mOrigin = vtkSmartPointer< vtkMatrix4x4 >::New();
324  mOrigin->Identity();
325  mOrigin->SetElement( 0, 3, -pos[ 0 ] );
326  mOrigin->SetElement( 1, 3, -pos[ 1 ] );
327  mOrigin->SetElement( 2, 3, -pos[ 2 ] );
328 
329  // Translation matrix: to object position
330  vtkSmartPointer< vtkMatrix4x4 > mPosition = vtkSmartPointer< vtkMatrix4x4 >::New();
331  mPosition->Identity();
332  mPosition->SetElement( 0, 3, pos[ 0 ] );
333  mPosition->SetElement( 1, 3, pos[ 1 ] );
334  mPosition->SetElement( 2, 3, pos[ 2 ] );
335 
336  /*
337  * Roll: homogenous rotation matrix for -Z axis
338  *
339  *
340  * cos(alpha) sin(alpha) 0 0
341  * -sin(alpha) cos(alpha) 0 0
342  * 0 0 1 0
343  * 0 0 0 1
344  */
345  //vtkSmartPointer< vtkMatrix4x4 >* mRoll = vtkSmartPointer< vtkMatrix4x4 >::New();
346  //mRoll->Identity();
347  //mRoll->SetElement(0,0, cos(r));
348  //mRoll->SetElement(0,1, sin(r));
349  //mRoll->SetElement(1,0, -sin(r));
350  //mRoll->SetElement(1,1, cos(r));
351 
352  /*
353  * Pitch: homogenous rotation matrix for +X axis
354  *
355  * 1 0 0 0
356  * 0 cos(alpha) -sin(alpha) 0
357  * 0 sin(alpha) cos(alpha) 0
358  * 0 0 0 1
359  */
360  vtkSmartPointer< vtkMatrix4x4 > mPitch = vtkSmartPointer< vtkMatrix4x4 >::New();
361  mPitch->Identity();
362  mPitch->SetElement( 1, 1, cos( p ) );
363  mPitch->SetElement( 1, 2, -sin( p ) );
364  mPitch->SetElement( 2, 1, sin( p ) );
365  mPitch->SetElement( 2, 2, cos( p ) );
366 
367  /*
368  * Yaw: homogenous rotation matrix for +Y axis
369  *
370  * cos(alpha) 0 sin(alpha) 0
371  * 0 1 0 0
372  * -sin(alpha) 0 cos(alpha) 0
373  * 0 0 0 1
374  */
375  vtkSmartPointer< vtkMatrix4x4 > mYaw = vtkSmartPointer< vtkMatrix4x4 >::New();
376  mYaw->Identity();
377  mYaw->SetElement( 0, 0, cos( y ) );
378  mYaw->SetElement( 0, 2, sin( y ) );
379  mYaw->SetElement( 2, 0, -sin( y ) );
380  mYaw->SetElement( 2, 2, cos( y ) );
381 
382 
383  // Compose transforms
384  // (Order: Origin, Roll, Pitch, Yaw, Position)
385  vtkSmartPointer< vtkTransform > transform = vtkSmartPointer< vtkTransform >::New();
386  transform->Concatenate( mPosition );
387  transform->Concatenate( mYaw );
388  transform->Concatenate( mPitch );
389  //transform->Concatenate(mRoll);
390  transform->Concatenate( mOrigin );
391 
392  // Apply new transformation
393  m_pProbe->SetUserTransform( transform );
394  m_pLabel->SetUserTransform( transform );
395 
396  // update label
397  assert( m_pContent != 0 );
398  double val = 0;
399  int i;
400  m_pContent->getNearestNeighbour( DAFF_DATA_VIEW, m_dProbeAlpha, m_dProbeBeta, i );
401  std::ostringstream s;
402  const DAFFContentDFT* pContentDFT = NULL;
403  const DAFFContentMS* pContentMS = NULL;
404  const DAFFContentMPS* pContentMPS = NULL;
405 
406  float fMag, fPhase, fReal, fImag;
407 
408  switch( m_pContent->getProperties()->getContentType() )
409  {
410  case DAFF_DFT_SPECTRUM:
411  pContentDFT = dynamic_cast< const DAFFContentDFT* >( m_pContent );
412  pContentDFT->getDFTCoeff( i, m_iChannel, m_iFrequency, fReal, fImag );
413  fMag = sqrt( fReal*fReal + fImag*fImag );
414  if( fReal != 0.0 )
415  {
416  fPhase = atan( fImag / fReal );
417  if( fReal < 0.0 )
418  if( fImag < 0.0 )
419  fPhase -= DAFF::PI_F;
420  else
421  fPhase += DAFF::PI_F;
422  }
423  else
424  {
425  if( fImag < 0.0 )
426  fPhase = -DAFF::HALF_PI_F;
427  else
428  fPhase = DAFF::HALF_PI_F;
429  }
430  if( m_iScaling == SCALING_DECIBEL )
431  {
432  fMag = FactorToDecibel( fMag );
433  s << "Real: " << fReal << ", Imag: " << fImag << "\n Mag: " << fMag << "db, Phase:" << fPhase;
434  }
435  else
436  s << "Real: " << fReal << ", Imag: " << fImag << "\n Mag: " << fMag << ", Phase:" << fPhase;
437  break;
438 
440  pContentMS = dynamic_cast< const DAFFContentMS* >( m_pContent );
441  pContentMS->getMagnitude( i, m_iChannel, m_iFrequency, fMag );
442  if( m_iScaling == SCALING_DECIBEL )
443  {
444  fMag = FactorToDecibel( fMag );
445  s << fMag << "db";
446  }
447  else
448  s << fMag;
449  break;
450 
452  pContentMPS = dynamic_cast< const DAFFContentMPS* >( m_pContent );
453  pContentMPS->getMagnitude( i, m_iChannel, m_iFrequency, fMag );
454  pContentMPS->getPhase( i, m_iChannel, m_iFrequency, fPhase );
455  if( m_iScaling == SCALING_DECIBEL )
456  {
457  fMag = FactorToDecibel( fMag );
458  s << "Mag: " << fMag << "db, Phase: " << fPhase;
459  }
460  else
461  s << "Mag: " << fMag << ", Phase: " << fPhase;
462  break;
463  }
464  m_pProbeLabel->SetText( s.str().c_str() );
465 
466  return;
467  }
468 
469  void BalloonPlot::SetProbeAngles( double dAlpha, double dBeta )
470  {
471  m_dProbeAlpha = dAlpha;
472  m_dProbeBeta = dBeta;
473  }
474 
475  void BalloonPlot::SetProbeVisible( bool bVisible )
476  {
477  m_pProbe->SetVisibility( bVisible );
478  m_pLabel->SetVisibility( bVisible );
479  }
480 
482  {
483  m_iFrequency = iFreq;
484  SetScalars();
485 
486  return;
487  }
488 
490  {
491  return m_iFrequency;
492  }
493 
494  void BalloonPlot::SetScaling( int iScaling )
495  {
496  m_iScaling = iScaling;
497  SetScalars();
498 
499  return;
500  }
501 
503  {
504  return m_iScaling;
505  }
506 
507  void BalloonPlot::SetRange( double dMin, double dMax )
508  {
509  assert( m_pContent != NULL );
510  assert( dMin < dMax );
511  if( m_iScaling == SCALING_LINEAR ) {
512  // Convert from linear to decibel
513  m_dMin = dMin;
514  m_dMax = dMax;
515  }
516  else
517  {
518  m_dMin = DecibelToFactor( dMin );
519  m_dMax = DecibelToFactor( dMax );
520  }
521  SetScalars();
522  }
523 
524  void BalloonPlot::SetUseCustomRange( bool bChecked )
525  {
526  m_bUseCustomRange = bChecked;
527  SetScalars();
528  }
529 
531  {
532  if( m_iScaling == SCALING_LINEAR )
533  {
534  return m_dMin;
535  }
536  else
537  {
538  return FactorToDecibel( m_dMin );
539  }
540  }
541 
543  {
544  if( m_iScaling == SCALING_LINEAR ) {
545  return m_dMax;
546  }
547  else
548  return FactorToDecibel( m_dMax );
549  }
550 
552  {
553  m_pPlotPolydata->GetPointData()->SetNormals( m_pNormals );
554  m_pMapper->SetInputConnection( m_pWarp->GetOutputPort() );
555  m_bWarp = true;
556  }
557 
559  {
560  m_pPlotPolydata->GetPointData()->SetNormals( 0 );
561  m_pMapper->SetInputData( m_pPlotPolydata );
562  m_bWarp = false;
563  }
564 
565  void BalloonPlot::SetNormalize( bool bChecked )
566  {
567  m_bNormalize = bChecked;
568  SetScalars();
569  }
570 
572  {
573  m_bNormalizeFreqsIndiv = bChecked;
574  SetScalars();
575  }
576 
577  void BalloonPlot::SetScalars()
578  {
579  assert( m_iFrequency >= 0 && m_iFrequency < m_iNumFrequencies );
580  assert( m_pContent != NULL );
581  assert( m_dMin < m_dMax );
582 
583  const DAFFContentDFT* pContentDFT = NULL;
584  const DAFFContentMS* pContentMS = NULL;
585  const DAFFContentMPS* pContentMPS = NULL;
586 
587  switch( m_pContent->getProperties()->getContentType() )
588  {
589  case DAFF_DFT_SPECTRUM:
590  pContentDFT = dynamic_cast< const DAFFContentDFT* >( m_pContent );
591  break;
592 
594  pContentMS = dynamic_cast< const DAFFContentMS* >( m_pContent );
595  break;
596 
598  pContentMPS = dynamic_cast< const DAFFContentMPS* >( m_pContent );
599  break;
600  }
601 
602  vtkSmartPointer< vtkFloatArray > pMagArray = vtkSmartPointer< vtkFloatArray >::New();
603 
604  pMagArray->SetName( "magnitudes" );
605  vtkSmartPointer< vtkFloatArray > pPhArray = vtkSmartPointer< vtkFloatArray >::New();
606  pPhArray->SetName( "phases" );
607 
608  float fMag = 0.0f;
609  float fPhase = 0.0f;
610  float fAbsoluteMax = 0.0f;
611  double dMax = 1.0f;
612 
613  //get the normalization range
614  if( pContentDFT )
615  {
616  if( m_iScaling == SCALING_DECIBEL )
617  {
618  if( m_bNormalizeFreqsIndiv )
619  fAbsoluteMax = getMagnitudeMaximum();
620  else
621  fAbsoluteMax = pContentDFT->getOverallMagnitudeMaximum();
622  }
623  else
624  {
625  if( m_bNormalizeFreqsIndiv )
626  dMax = getMagnitudeMaximum();
627  else
628  dMax = pContentDFT->getOverallMagnitudeMaximum();
629  }
630 
631  }
632  else if( pContentMS )
633  {
634  if( m_bNormalizeFreqsIndiv )
635  dMax = getMagnitudeMaximum();
636  else
637  dMax = pContentMS->getOverallMagnitudeMaximum();
638  }
639  else if( pContentMPS )
640  {
641  if( m_bNormalizeFreqsIndiv )
642  dMax = getMagnitudeMaximum();
643  else
644  dMax = pContentMPS->getOverallMagnitudeMaximum();
645  }
646 
647  for( int i = 0; i < m_pContent->getProperties()->getNumberOfRecords(); i++ )
648  {
649  // Get the magnitude value
650 
651  if( pContentDFT ) // ----------------
652  {
653  float fReal, fImag;
654  pContentDFT->getDFTCoeff( i, m_iChannel, m_iFrequency, fReal, fImag );
655  fMag = sqrt( fReal*fReal + fImag*fImag );
656  if( fReal != 0.0 ) {
657  fPhase = atan( fImag / fReal );
658  if( fReal < 0.0 )
659  if( fImag < 0.0 )
660  fPhase -= DAFF::PI_F;
661  else
662  fPhase += DAFF::PI_F;
663  }
664  else
665  {
666  if( fImag < 0.0 )
667  fPhase = -DAFF::HALF_PI_F;
668  else
669  fPhase = DAFF::HALF_PI_F;
670  }
671 
672  // Check weather decibel scaling is activated
673  if( m_iScaling == SCALING_DECIBEL )
674  {
675  assert( fAbsoluteMax != NULL );
676  fMag = FactorToDecibel( fMag / fAbsoluteMax );
677 
678  float DECIBEL_LOWER;
679  float DECIBEL_UPPER;
680 
681  // Decibel boundaries
682  //float DECIBEL_DELTA = 30; // FIXME: should not be hard coded -> GUI
683  if( m_bUseCustomRange )
684  {
685  DECIBEL_LOWER = FactorToDecibel( m_dMin );
686  DECIBEL_UPPER = FactorToDecibel( m_dMax );
687  }
688  else
689  {
690  DECIBEL_LOWER = FactorToDecibel( 0.0 );
691  DECIBEL_UPPER = FactorToDecibel( fAbsoluteMax );
692  }
693 
694  // Limit the lower boundary
695  fMag = std::max( fMag, DECIBEL_LOWER );
696  fMag = std::min( fMag, DECIBEL_UPPER );
697 
698  // Normalize the range into the interval [0,1]
699  fMag = 1 / ( DECIBEL_UPPER - DECIBEL_LOWER )*fMag + DECIBEL_LOWER / ( DECIBEL_LOWER - DECIBEL_UPPER );
700  }
701  else
702  {
703  if( m_bNormalize || m_bNormalizeFreqsIndiv )
704  {
705  assert( dMax != NULL && fMag <= dMax );
706  // Normalize the range into the interval [0, 1]
707  fMag = fMag / dMax;
708  }
709  else if( m_bUseCustomRange )
710  {
711  fMag = std::max( fMag, m_dMin );
712  fMag = std::min( fMag, m_dMax );
713  // Normalize the range into the interval [0,1]
714  fMag = ( fMag - m_dMin ) / ( m_dMax - m_dMin );
715  }
716  }
717 
718  }
719  else if( pContentMS ) // ----------------
720  {
721  pContentMS->getMagnitude( i, m_iChannel, m_iFrequency, fMag );
722 
723  if( m_bNormalize || m_bNormalizeFreqsIndiv )
724  {
725  assert( dMax != NULL && fMag <= dMax );
726  // Normalize the range into the interval [0, 1]
727  fMag = fMag / dMax;
728  }
729  else if( m_bUseCustomRange )
730  {
731  fMag = std::max( fMag, m_dMin );
732  fMag = std::min( fMag, m_dMax );
733  // Normalize the range into the interval [0,1]
734  fMag = ( fMag - m_dMin ) / ( m_dMax - m_dMin );
735  }
736  }
737 
738  else if( pContentMPS ) {
739  pContentMPS->getMagnitude( i, m_iChannel, m_iFrequency, fMag );
740  pContentMPS->getPhase( i, m_iChannel, m_iFrequency, fPhase );
741 
742  if( m_bNormalize )
743  {
744  assert( dMax != NULL && fMag <= dMax );
745  // Normalize the range into the interval [0, 1]
746  fMag = fMag / dMax;
747  }
748  else if( m_bUseCustomRange )
749  {
750  fMag = std::max( fMag, m_dMin );
751  fMag = std::min( fMag, m_dMax );
752  // Normalize the range into the interval [0,1]
753  fMag = ( fMag - m_dMin ) / ( m_dMax - m_dMin );
754  }
755  }
756 
757  // Store (inverted) value into scalars array
758  pMagArray->InsertNextTuple1( 1.0 - fMag );
759  pPhArray->InsertNextTuple1( fPhase );
760  }
761 
762  // Assign scalars to points
763  //m_pPlotPolydata->GetPointData()->SetScalars(pMagArray);
764  m_pPlotPolydata->GetPointData()->AddArray( pMagArray );
765  m_pPlotPolydata->GetPointData()->AddArray( pPhArray );
766 
767  UpdateProbe();
768  return;
769  }
770 
771  void BalloonPlot::sph2cart( double phi, double theta, double& x, double& y, double& z )
772  {
773  x = -sin( ( theta + 90 )*DAFF::PI_F / 180.0 ) * sin( phi*DAFF::PI_F / 180.0 );
774  y = -cos( ( theta + 90 )*DAFF::PI_F / 180.0 );
775  z = -sin( ( theta + 90 )*DAFF::PI_F / 180.0 ) * cos( phi*DAFF::PI_F / 180.0 );
776  }
777 
778  float BalloonPlot::FactorToDecibel( float x ) const
779  {
780  assert( x >= 0 );
781 
782  // Lower boundary is -100 dB
783  if( x <= 0.0000000001 )
784  return -100.0f;
785 
786  return 10.0f * log( x ) / log( 10.0f );
787  }
788 
789  float BalloonPlot::DecibelToFactor( float x ) const
790  {
791  return pow( 10.0, .1*x );
792  }
793 
794  float BalloonPlot::getMagnitudeMaximum() const
795  {
796  assert( m_iFrequency >= 0 && m_iFrequency < m_iNumFrequencies );
797  assert( m_pContent != NULL );
798  assert( m_dMin < m_dMax );
799 
800  const DAFFContentDFT* pContentDFT = NULL;
801  const DAFFContentMS* pContentMS = NULL;
802  const DAFFContentMPS* pContentMPS = NULL;
803 
804  switch( m_pContent->getProperties()->getContentType() )
805  {
806  case DAFF_DFT_SPECTRUM:
807  pContentDFT = dynamic_cast< const DAFFContentDFT* >( m_pContent );
808  break;
809 
811  pContentMS = dynamic_cast< const DAFFContentMS* >( m_pContent );
812  break;
813 
815  pContentMPS = dynamic_cast< const DAFFContentMPS* >( m_pContent );
816  break;
817  }
818 
819  float fMax = std::numeric_limits<float>::min();
820  float fMag;
821  if( pContentDFT )
822  {
823  float fReal, fImag;
824  for( int i = 0; i < pContentDFT->getNumDFTCoeffs(); i++ )
825  {
826  pContentDFT->getDFTCoeff( i, m_iChannel, m_iFrequency, fReal, fImag );
827  fMag = std::sqrtf( std::powf( fReal, 2 ) + std::powf( fImag, 2 ) );
828  if( fMag > fMax )
829  fMax = fMag;
830  }
831  }
832  else if( pContentMS )
833  {
834  for( int i = 0; i < pContentMS->getProperties()->getNumberOfRecords(); i++ )
835  {
836  pContentMS->getMagnitude( i, m_iChannel, m_iFrequency, fMag );
837  if( fMag > fMax )
838  fMax = fMag;
839  }
840  }
841  else if( pContentMPS )
842  {
843  for( int i = 0; i < pContentMPS->getProperties()->getNumberOfRecords(); i++ )
844  {
845  pContentMPS->getMagnitude( i, m_iChannel, m_iFrequency, fMag );
846  if( fMag > fMax )
847  fMax = fMag;
848  }
849  }
850 
851  return fMax;
852  }
853 
854  void BalloonPlot::SetScalarVisibility( bool bVisible )
855  {
856  m_pMapper->SetScalarVisibility( bVisible );
857  }
858 
860  {
861  return m_pMapper->GetScalarVisibility();
862  }
863 
864  void BalloonPlot::SetDisplayMode( int iMode )
865  {
866  if( iMode == MODE_SURFACE )
867  m_pPlotActor->GetProperty()->SetRepresentationToSurface();
868  else if( iMode == MODE_WIREFRAME )
869  m_pPlotActor->GetProperty()->SetRepresentationToWireframe();
870  else if( iMode == MODE_POINT )
871  m_pPlotActor->GetProperty()->SetRepresentationToPoints();
872  }
873 
874  void BalloonPlot::SetChannel( int iChannel )
875  {
876  m_iChannel = iChannel;
877  SetScalars();
878  }
879 
881  {
882  return m_iChannel;
883  }
884 
886  {
887  if( bUse )
888  {
889  m_pMapper->SelectColorArray( "phases" );
890  vtkSmartPointer< vtkColorTransferFunction > colors = vtkSmartPointer< vtkColorTransferFunction >::New();
891  colors->AddRGBPoint( -DAFF::PI_F, 0, 0, 1 );
892  colors->AddRGBPoint( 0, 1, 1, 1 );
893  colors->AddRGBPoint( DAFF::PI_F, 1, 0, 0 );
894  m_pMapper->SetLookupTable( colors );
895  }
896  else
897  {
898  m_pMapper->SelectColorArray( "magnitudes" );
899  m_pMapper->SetLookupTable( 0 );
900  }
901  m_bUsePhaseAsColor = bUse;
902  }
903 
904 } // End of namespace "DAFFViz"
void AddActor(vtkSmartPointer< vtkActor > pActor)
Add a VTK actor to the node.
virtual float getOverallMagnitudeMaximum() const =0
Returns the overall greatest magnitude value.
int GetScalarVisibility()
Get whether scalars should be used to color the model.
Discrete Fourier spectrum in the frequency-domain.
Definition: DAFFDefs.h:70
void RemoveActor(vtkSmartPointer< vtkActor > pActor)
Remove a VTK actor from the assembly of the node.
void SetSelectedFrequency(int iFreqIndex)
Sets the currently selected frequency index.
void SetChannel(int iChannel)
Set active channel.
virtual void getNearestNeighbour(int iView, float fAngle1Deg, float fAngle2Deg, int &iRecordIndex) const =0
Determine the nearest neighbour record and return its index.
void EnableWarp()
Enable/Disable warping (WARP_DISABLE | WARP_ENABLE)
Common content interface.
Definition: DAFFContent.h:40
int GetChannel()
get active channel
virtual int getDFTCoeff(int iRecordIndex, int iChannel, int iDFTCoeff, float &fReal, float &fImag) const =0
Retrieve a single magnitude coefficient.
Magnitude spectrum content interface.
Definition: DAFFContentMS.h:31
virtual float getAlphaStart() const =0
Magnitude spectrum defined at discrete frequencies.
Definition: DAFFDefs.h:67
virtual int getMagnitude(int iRecordIndex, int iChannel, int iFreqIndex, float &fMag) const =0
Retrieves a single magnitude coefficient.
#define NULL
Definition: DAFFDefs.h:59
void SetNormalize(bool bChecked)
set wether the magnitudes should be normalized
Magnitude-phase spectrum defined at discrete frequencies.
Definition: DAFFDefs.h:69
virtual float getBetaEnd() const =0
void SetScaling(int iScaling)
Set scaling (SCALING_LINEAR | SCALING_DECIBEL)
int GetScaling() const
Get scaling (SCALING_LINEAR | SCALING_DECIBEL)
void SetUsePhaseAsColor(bool bUse)
set whether the phase should be used for coloring. If not, the magnitude will be used.
int GetSelectedFrequency() const
Returns the currently selected frequency index.
virtual int getRecordCoords(int iRecordIndex, int iView, float &fAngle1Deg, float &fAngle2Deg) const =0
Determines the spherical coordinates of a record (grid point on spherical regular grid) ...
void SetUseCustomRange(bool bChecked)
set wether the magnitudes should be normalized to a custom range
virtual int getNumDFTCoeffs() const =0
Returns the number of DFT coefficients.
virtual float getBetaStart() const =0
virtual float getOverallMagnitudeMaximum() const =0
Returns the overall greatest magnitude value.
Magnitude-phase spectrum content interface.
virtual int getContentType() const =0
Returns the content type.
virtual int getAlphaPoints() const =0
Base class for scene graph nodes.
Definition: DAFFVizSGNode.h:67
virtual int getNumberOfRecords() const =0
Returns the overall number of records.
void SetNormalizeFrequenciesIndividually(bool bChecked)
set wether the magnitudes should be normalized for each individual frequency
void SetProbeAngles(double dAlpha, double dBeta)
Set probe angles.
BalloonPlot(SGNode *pParentNode, const DAFFContent *pContent)
void SetDisplayMode(int iMode)
Set display mode (MODE_SURFACE | MODE_WIREFRAME | MODE_POINT)
virtual const DAFFProperties * getProperties() const =0
Returns the properties.
virtual int getMagnitude(int iRecordIndex, int iChannel, int iFreqIndex, float &fMag) const =0
Retrieves a single magnitude coefficient.
void SetProbeVisible(bool bVisible)
Enables/disables probe.
void SetRange(double dMin, double dMax)
Set data range (in dB or absolute values depending on currently used scaling)
Discrete Fourier spectrum content interface.
virtual float getAlphaEnd() const =0
void UpdateProbe()
Update probe nodes.
double GetRangeMin() const
Set minimum of data range (in dB or absolute values depending on currently used scaling) ...
virtual int getPhase(int iRecordIndex, int iChannel, int iFreqIndex, float &fPhase) const =0
Retrieves a single phase coefficient.
virtual int getBetaPoints() const =0
Properties of a DAFF file that uses regular sphere grids (or parts of a regular grid) ...
Phase spectrum defined at discrete frequencies.
Definition: DAFFDefs.h:68
static double grad2rad(double phi)
Definition: DAFFUtils.h:109
virtual float getOverallMagnitudeMaximum() const =0
Returns the overall greatest magnitude value.
void SetScalarVisibility(bool bVisible)
Set whether scalars should be used to color the model.
Data-related view referring to data spherical coordinates (DSC)
Definition: DAFFDefs.h:86
Object-related view referring to object spherical coordinates (OSC)
Definition: DAFFDefs.h:87
double GetRangeMax() const
Set minimum of data range (in dB or absolute values depending on currently used scaling) ...
OpenDAFF is a project from the Institute of Technical Acoustics, RWTH Aachen University, Germany.