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> 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> 41 m_pContent( pContent ),
43 m_iNumFrequencies( 0 ),
44 m_iScaling( SCALING_DECIBEL ),
45 m_dMin( 0.0 ), m_dMax( 1.0 ),
48 m_bNormalize( false ),
49 m_bNormalizeFreqsIndiv( false ),
50 m_bUseCustomRange( false ),
51 m_bUsePhaseAsColor( false )
58 m_pContent( pContent ),
60 m_iNumFrequencies( 0 ),
62 m_dMin( 0.0 ), m_dMax( 1.0 ),
65 m_bNormalize( false ),
66 m_bNormalizeFreqsIndiv( false ),
67 m_bUseCustomRange( false ),
68 m_bUsePhaseAsColor( false )
80 void BalloonPlot::init()
88 m_iNumFrequencies =
dynamic_cast< const DAFFContentDFT*
>( m_pContent )->getNumDFTCoeffs();
94 m_iNumFrequencies =
dynamic_cast< const DAFFContentMS*
>( m_pContent )->getNumFrequencies();
106 vtkSmartPointer< vtkPoints > points = vtkSmartPointer< vtkPoints >::New();
107 m_pNormals = vtkSmartPointer< vtkDoubleArray >::New();
108 m_pNormals->SetNumberOfComponents( 3 );
117 sph2cart( phi, theta, x, y, z );
118 points->InsertPoint( i, x, y, z );
119 double n[ 3 ] = { -x, -y, -z };
120 m_pNormals->InsertNextTuple( n );
126 vtkSmartPointer< vtkCellArray > cells = vtkSmartPointer< vtkCellArray >::New();
127 vtkIdType quadface[ 4 ];
128 vtkIdType triangleface[ 3 ];
134 int iBodyEleRings = iElePoints - 1;
135 int iAziCount = ( bAzimuthWrap ? iAziPoints : iAziPoints - 1 );
136 if( bSouthPole ) iBodyEleRings--;
137 if( bNorthPole ) iBodyEleRings--;
143 if( ( iAziPoints == 1 ) || ( iElePoints == 1 ) )
145 if( ( iAziPoints == 1 ) && ( iElePoints == 1 ) )
152 points->InsertPoint( iNumPoints, 0, 0, 0 );
154 for(
int i = 0; i < iNumPoints; i++ )
156 triangleface[ 0 ] = i;
157 triangleface[ 1 ] = i + 1;
158 triangleface[ 2 ] = iNumPoints;
160 for(
int k = 0; k < 3; k++ )
161 assert( ( triangleface[ k ] >= 0 ) && ( triangleface[ k ] < iNumPoints + 1 ) );
163 cells->InsertNextCell( 3, triangleface );
179 for(
int j = 0; j < iAziCount; j++ )
181 triangleface[ 0 ] = 0;
182 triangleface[ 1 ] = iBodyOffset + j;
183 triangleface[ 2 ] = iBodyOffset + ( j + 1 ) % iAziPoints;
185 for(
int k = 0; k < 3; k++ )
186 assert( ( triangleface[ k ] >= 0 ) && ( triangleface[ k ] < iNumPoints ) );
188 cells->InsertNextCell( 3, triangleface );
193 for(
int i = 0; i < iBodyEleRings; i++ )
195 for(
int j = 0; j < iAziCount; j++ )
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;
202 for(
int k = 0; k < 4; k++ )
203 assert( ( quadface[ k ] >= 0 ) && ( quadface[ k ] < iNumPoints ) );
205 cells->InsertNextCell( 4, quadface );
218 for(
int j = 0; j < iAziCount; j++ )
220 triangleface[ 0 ] = iNumPoints - 1;
221 triangleface[ 1 ] = iBodyOffset + iBodyEleRings*iAziPoints + j;
222 triangleface[ 2 ] = iBodyOffset + iBodyEleRings*iAziPoints + ( j + 1 ) % iAziPoints;
224 for(
int k = 0; k < 3; k++ )
225 assert( ( triangleface[ k ] >= 0 ) && ( triangleface[ k ] < pProps->
getNumberOfRecords() ) );
227 cells->InsertNextCell( 3, triangleface );
234 m_pPlotPolydata = vtkSmartPointer< vtkPolyData >::New();
235 m_pPlotPolydata->SetPoints( points );
236 m_pPlotPolydata->SetPolys( cells );
240 m_pPlotPolydata->GetPointData()->SetActiveScalars(
"magnitudes" );
243 m_pWarp = vtkSmartPointer< vtkWarpScalar >::New();
244 m_pWarp->SetInputData( m_pPlotPolydata );
245 m_pWarp->UseNormalOff();
247 m_pMapper = vtkSmartPointer< vtkPolyDataMapper >::New();
248 m_pMapper->SetScalarModeToUsePointFieldData();
257 m_pPlotActor = vtkSmartPointer< vtkActor >::New();
258 m_pPlotActor->SetMapper( m_pMapper );
260 m_pPlotActor->GetProperty()->SetInterpolationToGouraud();
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 );
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 );
277 vtkSmartPointer< vtkPolyData > polydata = vtkSmartPointer< vtkPolyData >::New();
278 polydata->SetPoints( points2 );
279 polydata->SetLines( cells2 );
282 vtkSmartPointer< vtkPolyDataMapper > mapper = vtkSmartPointer< vtkPolyDataMapper >::New();
283 mapper->SetInputData( polydata );
285 m_pProbe = vtkSmartPointer< vtkActor >::New();
286 m_pProbe->SetMapper( mapper );
287 m_pProbe->VisibilityOff();
292 m_pProbeLabel = vtkSmartPointer< vtkVectorText >::New();
293 std::ostringstream s;
295 m_pProbeLabel->SetText( s.str().c_str() );
297 vtkSmartPointer< vtkPolyDataMapper >mapper2 = vtkSmartPointer< vtkPolyDataMapper >::New();
298 mapper2->AddInputConnection( m_pProbeLabel->GetOutputPort() );
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();
317 double* pos = m_pProbe->GetPosition();
323 vtkSmartPointer< vtkMatrix4x4 > mOrigin = vtkSmartPointer< vtkMatrix4x4 >::New();
325 mOrigin->SetElement( 0, 3, -pos[ 0 ] );
326 mOrigin->SetElement( 1, 3, -pos[ 1 ] );
327 mOrigin->SetElement( 2, 3, -pos[ 2 ] );
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 ] );
360 vtkSmartPointer< vtkMatrix4x4 > mPitch = vtkSmartPointer< vtkMatrix4x4 >::New();
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 ) );
375 vtkSmartPointer< vtkMatrix4x4 > mYaw = vtkSmartPointer< vtkMatrix4x4 >::New();
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 ) );
385 vtkSmartPointer< vtkTransform > transform = vtkSmartPointer< vtkTransform >::New();
386 transform->Concatenate( mPosition );
387 transform->Concatenate( mYaw );
388 transform->Concatenate( mPitch );
390 transform->Concatenate( mOrigin );
393 m_pProbe->SetUserTransform( transform );
394 m_pLabel->SetUserTransform( transform );
397 assert( m_pContent != 0 );
401 std::ostringstream s;
406 float fMag, fPhase, fReal, fImag;
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 );
416 fPhase = atan( fImag / fReal );
419 fPhase -= DAFF::PI_F;
421 fPhase += DAFF::PI_F;
426 fPhase = -DAFF::HALF_PI_F;
428 fPhase = DAFF::HALF_PI_F;
432 fMag = FactorToDecibel( fMag );
433 s <<
"Real: " << fReal <<
", Imag: " << fImag <<
"\n Mag: " << fMag <<
"db, Phase:" << fPhase;
436 s <<
"Real: " << fReal <<
", Imag: " << fImag <<
"\n Mag: " << fMag <<
", Phase:" << fPhase;
440 pContentMS =
dynamic_cast< const DAFFContentMS*
>( m_pContent );
441 pContentMS->
getMagnitude( i, m_iChannel, m_iFrequency, fMag );
444 fMag = FactorToDecibel( fMag );
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 );
457 fMag = FactorToDecibel( fMag );
458 s <<
"Mag: " << fMag <<
"db, Phase: " << fPhase;
461 s <<
"Mag: " << fMag <<
", Phase: " << fPhase;
464 m_pProbeLabel->SetText( s.str().c_str() );
471 m_dProbeAlpha = dAlpha;
472 m_dProbeBeta = dBeta;
477 m_pProbe->SetVisibility( bVisible );
478 m_pLabel->SetVisibility( bVisible );
483 m_iFrequency = iFreq;
496 m_iScaling = iScaling;
509 assert( m_pContent !=
NULL );
510 assert( dMin < dMax );
518 m_dMin = DecibelToFactor( dMin );
519 m_dMax = DecibelToFactor( dMax );
526 m_bUseCustomRange = bChecked;
538 return FactorToDecibel( m_dMin );
548 return FactorToDecibel( m_dMax );
553 m_pPlotPolydata->GetPointData()->SetNormals( m_pNormals );
554 m_pMapper->SetInputConnection( m_pWarp->GetOutputPort() );
560 m_pPlotPolydata->GetPointData()->SetNormals( 0 );
561 m_pMapper->SetInputData( m_pPlotPolydata );
567 m_bNormalize = bChecked;
573 m_bNormalizeFreqsIndiv = bChecked;
577 void BalloonPlot::SetScalars()
579 assert( m_iFrequency >= 0 && m_iFrequency < m_iNumFrequencies );
580 assert( m_pContent !=
NULL );
581 assert( m_dMin < m_dMax );
590 pContentDFT =
dynamic_cast< const DAFFContentDFT*
>( m_pContent );
594 pContentMS =
dynamic_cast< const DAFFContentMS*
>( m_pContent );
598 pContentMPS =
dynamic_cast< const DAFFContentMPS*
>( m_pContent );
602 vtkSmartPointer< vtkFloatArray > pMagArray = vtkSmartPointer< vtkFloatArray >::New();
604 pMagArray->SetName(
"magnitudes" );
605 vtkSmartPointer< vtkFloatArray > pPhArray = vtkSmartPointer< vtkFloatArray >::New();
606 pPhArray->SetName(
"phases" );
610 float fAbsoluteMax = 0.0f;
618 if( m_bNormalizeFreqsIndiv )
619 fAbsoluteMax = getMagnitudeMaximum();
625 if( m_bNormalizeFreqsIndiv )
626 dMax = getMagnitudeMaximum();
632 else if( pContentMS )
634 if( m_bNormalizeFreqsIndiv )
635 dMax = getMagnitudeMaximum();
639 else if( pContentMPS )
641 if( m_bNormalizeFreqsIndiv )
642 dMax = getMagnitudeMaximum();
654 pContentDFT->
getDFTCoeff( i, m_iChannel, m_iFrequency, fReal, fImag );
655 fMag = sqrt( fReal*fReal + fImag*fImag );
657 fPhase = atan( fImag / fReal );
660 fPhase -= DAFF::PI_F;
662 fPhase += DAFF::PI_F;
667 fPhase = -DAFF::HALF_PI_F;
669 fPhase = DAFF::HALF_PI_F;
675 assert( fAbsoluteMax !=
NULL );
676 fMag = FactorToDecibel( fMag / fAbsoluteMax );
683 if( m_bUseCustomRange )
685 DECIBEL_LOWER = FactorToDecibel( m_dMin );
686 DECIBEL_UPPER = FactorToDecibel( m_dMax );
690 DECIBEL_LOWER = FactorToDecibel( 0.0 );
691 DECIBEL_UPPER = FactorToDecibel( fAbsoluteMax );
695 fMag = std::max( fMag, DECIBEL_LOWER );
696 fMag = std::min( fMag, DECIBEL_UPPER );
699 fMag = 1 / ( DECIBEL_UPPER - DECIBEL_LOWER )*fMag + DECIBEL_LOWER / ( DECIBEL_LOWER - DECIBEL_UPPER );
703 if( m_bNormalize || m_bNormalizeFreqsIndiv )
705 assert( dMax !=
NULL && fMag <= dMax );
709 else if( m_bUseCustomRange )
711 fMag = std::max( fMag, m_dMin );
712 fMag = std::min( fMag, m_dMax );
714 fMag = ( fMag - m_dMin ) / ( m_dMax - m_dMin );
719 else if( pContentMS )
721 pContentMS->
getMagnitude( i, m_iChannel, m_iFrequency, fMag );
723 if( m_bNormalize || m_bNormalizeFreqsIndiv )
725 assert( dMax !=
NULL && fMag <= dMax );
729 else if( m_bUseCustomRange )
731 fMag = std::max( fMag, m_dMin );
732 fMag = std::min( fMag, m_dMax );
734 fMag = ( fMag - m_dMin ) / ( m_dMax - m_dMin );
738 else if( pContentMPS ) {
739 pContentMPS->
getMagnitude( i, m_iChannel, m_iFrequency, fMag );
740 pContentMPS->
getPhase( i, m_iChannel, m_iFrequency, fPhase );
744 assert( dMax !=
NULL && fMag <= dMax );
748 else if( m_bUseCustomRange )
750 fMag = std::max( fMag, m_dMin );
751 fMag = std::min( fMag, m_dMax );
753 fMag = ( fMag - m_dMin ) / ( m_dMax - m_dMin );
758 pMagArray->InsertNextTuple1( 1.0 - fMag );
759 pPhArray->InsertNextTuple1( fPhase );
764 m_pPlotPolydata->GetPointData()->AddArray( pMagArray );
765 m_pPlotPolydata->GetPointData()->AddArray( pPhArray );
771 void BalloonPlot::sph2cart(
double phi,
double theta,
double& x,
double& y,
double& z )
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 );
778 float BalloonPlot::FactorToDecibel(
float x )
const 783 if( x <= 0.0000000001 )
786 return 10.0f * log( x ) / log( 10.0f );
789 float BalloonPlot::DecibelToFactor(
float x )
const 791 return pow( 10.0, .1*x );
794 float BalloonPlot::getMagnitudeMaximum()
const 796 assert( m_iFrequency >= 0 && m_iFrequency < m_iNumFrequencies );
797 assert( m_pContent !=
NULL );
798 assert( m_dMin < m_dMax );
807 pContentDFT =
dynamic_cast< const DAFFContentDFT*
>( m_pContent );
811 pContentMS =
dynamic_cast< const DAFFContentMS*
>( m_pContent );
815 pContentMPS =
dynamic_cast< const DAFFContentMPS*
>( m_pContent );
819 float fMax = std::numeric_limits<float>::min();
826 pContentDFT->
getDFTCoeff( i, m_iChannel, m_iFrequency, fReal, fImag );
827 fMag = std::sqrtf( std::powf( fReal, 2 ) + std::powf( fImag, 2 ) );
832 else if( pContentMS )
836 pContentMS->
getMagnitude( i, m_iChannel, m_iFrequency, fMag );
841 else if( pContentMPS )
845 pContentMPS->
getMagnitude( i, m_iChannel, m_iFrequency, fMag );
856 m_pMapper->SetScalarVisibility( bVisible );
861 return m_pMapper->GetScalarVisibility();
867 m_pPlotActor->GetProperty()->SetRepresentationToSurface();
869 m_pPlotActor->GetProperty()->SetRepresentationToWireframe();
871 m_pPlotActor->GetProperty()->SetRepresentationToPoints();
876 m_iChannel = iChannel;
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 );
898 m_pMapper->SelectColorArray(
"magnitudes" );
899 m_pMapper->SetLookupTable( 0 );
901 m_bUsePhaseAsColor = bUse;
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.
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.
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.
virtual float getAlphaStart() const =0
Magnitude spectrum defined at discrete frequencies.
virtual int getMagnitude(int iRecordIndex, int iChannel, int iFreqIndex, float &fMag) const =0
Retrieves a single magnitude coefficient.
void SetNormalize(bool bChecked)
set wether the magnitudes should be normalized
Magnitude-phase spectrum defined at discrete frequencies.
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.
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.
static double grad2rad(double phi)
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)
Object-related view referring to object spherical coordinates (OSC)
double GetRangeMax() const
Set minimum of data range (in dB or absolute values depending on currently used scaling) ...