QT_ACTION_CONN( Open );
QT_ACTION_CONN( Config );
QT_ACTION_CONN( Process );
+ QT_ACTION_CONN( MarkReference );
+ QT_ACTION_CONN( MarkStenosis );
+ QT_ACTION_CONN( SaveResults );
+ QT_ACTION_CONN( UpdateContour );
// Load log
if( argc == 3 )
for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt )
points.push_back( mesh->GetPoint( *eIt ) );
- } // fi
+ TFourier f( points.begin( ), points.end( ), 6 );
+ f.SetOrderingToCounterClockWise( );
+ this->m_Fourier.push_back( f );
+ }
+ else
+ {
+ TFourier f( 6 );
+ f[ 1 ] = 0.1;
+ this->m_Fourier.push_back( f );
- TFourier f( points.begin( ), points.end( ), 6 );
- f.SetOrderingToCounterClockWise( );
- this->m_Fourier.push_back( f );
+ } // fi
vtkSmartPointer< ivq::VTK::PolyDataActor > actor =
vtkSmartPointer< ivq::VTK::PolyDataActor >::New( );
this->m_UI->Plot->rescaleAxes( );
this->m_UI->Plot->replot( );
+ this->m_StenosisText = new QCPItemText( this->m_UI->Plot );
+ this->m_StenosisText->setText( "Stenosis: NaN" );
+ this->m_UI->Plot->replot( );
}
// -------------------------------------------------------------------------
slice_view->Render( );
this->_prepareQuantification( );
+ this->m_StenosisSlice = -1;
+ this->m_ReferenceSlice = -1;
+ this->m_StenosisLine = NULL;
+ this->m_ReferenceLine = NULL;
+}
+
+// -------------------------------------------------------------------------
+void CTArteries::
+_showStenosis( )
+{
+ if( this->m_StenosisSlice >= 0 )
+ {
+ if( this->m_StenosisLine == NULL )
+ this->m_StenosisLine = new QCPItemLine( this->m_UI->Plot );
+ this->m_StenosisLine->start->setCoords( this->m_StenosisSlice, 0 );
+ this->m_StenosisLine->end->setCoords(
+ this->m_StenosisSlice,
+ this->m_UI->Plot->yAxis->range( ).size( )
+ );
+ this->m_UI->Plot->replot( );
+
+ } // fi
+ if( this->m_ReferenceSlice >= 0 )
+ {
+ if( this->m_ReferenceLine == NULL )
+ this->m_ReferenceLine = new QCPItemLine( this->m_UI->Plot );
+ this->m_ReferenceLine->start->setCoords( this->m_ReferenceSlice, 0 );
+ this->m_ReferenceLine->end->setCoords(
+ this->m_ReferenceSlice,
+ this->m_UI->Plot->yAxis->range( ).size( )
+ );
+ this->m_UI->Plot->replot( );
+
+ } // fi
+ if( this->m_StenosisSlice < 0 || this->m_ReferenceSlice < 0 )
+ return;
+
+ double sa, sb, st, sp;
+ this->m_Fourier[ this->m_StenosisSlice ].GetEllipse( 1, sa, sb, st, sp );
+ double sarea = this->m_Fourier[ this->m_StenosisSlice ].GetArea( );
+ double ra, rb, rt, rp;
+ this->m_Fourier[ this->m_ReferenceSlice ].GetEllipse( 1, ra, rb, rt, rp );
+ double rarea = this->m_Fourier[ this->m_ReferenceSlice ].GetArea( );
+ double qmin = 100.0 * ( 1.0 - ( sb / rb ) );
+ double qmax = 100.0 * ( 1.0 - ( sa / ra ) );
+ double qarea = 100.0 * ( 1.0 - ( sarea / rarea ) );
+
+ std::stringstream s;
+ s << "Stenosis: " << std::endl
+ << qmin << "% (min diameter)" << std::endl
+ << qmax << "% (max diameter)" << std::endl
+ << qarea << "% (area)";
+ this->m_StenosisText->setText( s.str( ).c_str( ) );
+ this->m_StenosisText->position->setCoords(
+ ( this->m_ReferenceSlice + this->m_StenosisSlice ) * 0.5,
+ this->m_UI->Plot->yAxis->range( ).center( )
+ );
+ this->m_UI->Plot->replot( );
}
// -------------------------------------------------------------------------
this->_showProcessResults( );
}
+// -------------------------------------------------------------------------
+void CTArteries::
+_sMarkReference( )
+{
+ if( this->m_Fourier.size( ) == 0 )
+ return;
+ ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( );
+ this->m_ReferenceSlice = slice_view->GetImageActor( )->GetSliceNumber( );
+ this->_showStenosis( );
+}
+
+// -------------------------------------------------------------------------
+void CTArteries::
+_sMarkStenosis( )
+{
+ if( this->m_Fourier.size( ) == 0 )
+ return;
+ ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( );
+ this->m_StenosisSlice = slice_view->GetImageActor( )->GetSliceNumber( );
+ this->_showStenosis( );
+}
+
+// -------------------------------------------------------------------------
+void CTArteries::
+_sSaveResults( )
+{
+ std::string fname =
+ QFileDialog::getSaveFileName(
+ this,
+ "Select one or more files to open",
+ ".",
+ "CSV files (*.csv);;All files (*)"
+ ).toStdString( );
+ if( fname == "" )
+ return;
+
+ std::ofstream out( fname.c_str( ) );
+ out << "slice;min_diameter;max_diameter;area" << std::endl;
+ for( unsigned int i = 0; i < this->m_Fourier.size( ); ++i )
+ {
+ double a, b, t, p;
+ this->m_Fourier[ i ].GetEllipse( 1, a, b, t, p );
+ double area = this->m_Fourier[ i ].GetArea( );
+ out << i << ";" << b << ";" << a << ";" << area << std::endl;
+
+ } // rof
+ out << "############################" << std::endl;
+ typedef ivq::VTK::SeedWidgetOverImageActor::TSeeds _TSeeds;
+ const _TSeeds& seeds = this->m_Seeds->GetSeeds( );
+ for( _TSeeds::value_type seed: seeds )
+ {
+ for( unsigned int i = 0; i < seed.second.size( ); i += 3 )
+ {
+ out
+ << seed.second[ i + 0 ] << " "
+ << seed.second[ i + 1 ] << " "
+ << seed.second[ i + 2 ] << std::endl;
+
+ } // rof
+
+ } // rof
+ out << "############################" << std::endl;
+ out.close( );
+}
+
+// -------------------------------------------------------------------------
+void CTArteries::
+_sUpdateContour( )
+{
+ if( this->m_ContourActor == NULL )
+ return;
+ vtkSmartPointer< vtkPolyData > new_pd =
+ vtkSmartPointer< vtkPolyData >::New( );
+ this->m_Spline->GetPolyData( new_pd );
+
+ ivq::VTK::ImageViewer* slice_view = this->m_UI->Slice->GetViewer( );
+ ivq::VTK::ImageActor* slice_actor = slice_view->GetImageActor( );
+ this->m_ContoursActors[ slice_actor->GetSliceNumber( ) ]->
+ SetInputData( new_pd );
+ slice_view->Render( );
+
+
+ typedef itk::QuadEdgeMesh< double, 2 > _TQEMesh;
+ typedef _TQEMesh::PointType _T2DPoint;
+ typedef std::vector< _T2DPoint > _T2DPoints;
+ _T2DPoints points;
+ _TQEMesh::Pointer mesh = _TQEMesh::New( );
+ for( unsigned int i = 0; i < new_pd->GetNumberOfPoints( ); ++i )
+ {
+ _T2DPoint pnt;
+ double p[ 3 ];
+ new_pd->GetPoint( i, p );
+ pnt[ 0 ] = p[ 0 ];
+ pnt[ 1 ] = p[ 1 ];
+ mesh->AddPoint( pnt );
+
+ } // rof
+ vtkCellArray* lines = new_pd->GetLines( );
+ lines->InitTraversal( );
+ vtkIdType* ids = new vtkIdType[ 2 ];
+ vtkIdType npts;
+ while( lines->GetNextCell( npts, ids ) != 0 )
+ mesh->AddEdge( ids[ 0 ], ids[ 1 ] );
+ delete ids;
+ _TQEMesh::QEPrimal* edge = mesh->GetEdge( );
+ if( edge != NULL )
+ {
+ mesh->AddFace( edge );
+ edge = mesh->GetEdge( );
+ for( auto eIt = edge->BeginGeomLnext( ); eIt != edge->EndGeomLnext( ); ++eIt )
+ points.push_back( mesh->GetPoint( *eIt ) );
+
+ TFourier f( points.begin( ), points.end( ), 6 );
+ f.SetOrderingToCounterClockWise( );
+ this->m_Fourier[ slice_actor->GetSliceNumber( ) ] = f;
+
+ } // fi
+}
+
// -------------------------------------------------------------------------
template< class _TImagePtr, class _TVTKImagePtr, class _TCurvePtr >
void CTArteries::