]> Creatis software - FrontAlgorithms.git/blobdiff - appli/CTArteries/CTArteries.cxx
...
[FrontAlgorithms.git] / appli / CTArteries / CTArteries.cxx
index 54b8aeb8908f73f6cb2e223aa2abf02a9b6e145a..282f66f604521007519297d82e640ace3a739a00 100644 (file)
@@ -122,6 +122,10 @@ CTArteries( int argc, char* argv[], QWidget* parent )
   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 )
@@ -378,11 +382,17 @@ _prepareQuantification( )
       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( );
@@ -468,6 +478,9 @@ _prepareQuantification( )
 
   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( );
 }
 
 // -------------------------------------------------------------------------
@@ -534,6 +547,64 @@ _showProcessResults( )
   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( );
 }
 
 // -------------------------------------------------------------------------
@@ -628,6 +699,125 @@ _sProcess( )
   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::