From d20d31b636ac424a3e69cc9784062ca5d2edc8d8 Mon Sep 17 00:00:00 2001
From: =?utf8?q?Beno=C3=AEt=20Presles?= <benoit.presles@netcourrier.com>
Date: Tue, 23 Oct 2012 19:01:59 +0200
Subject: [PATCH] added labels to landmarks

---
 vv/CMakeLists.txt     |  1 +
 vv/vvClipPolyData.cxx | 80 +++++++++++++++++++++++++++++++++++++++++++
 vv/vvClipPolyData.h   | 25 ++++++++++++++
 vv/vvLandmarks.cxx    | 38 +++++++++++++++++---
 vv/vvLandmarks.h      |  2 ++
 vv/vvMainWindow.cxx   |  4 +--
 vv/vvSlicer.cxx       | 74 +++++++++++++++++++++++++++------------
 vv/vvSlicer.h         |  5 ++-
 8 files changed, 199 insertions(+), 30 deletions(-)
 create mode 100644 vv/vvClipPolyData.cxx
 create mode 100644 vv/vvClipPolyData.h

diff --git a/vv/CMakeLists.txt b/vv/CMakeLists.txt
index 1a21d8c..e280cfc 100644
--- a/vv/CMakeLists.txt
+++ b/vv/CMakeLists.txt
@@ -79,6 +79,7 @@ SET(vv_SRCS
   vvSlicer.cxx
   vvLandmarks.cxx
   vvLandmarksGlyph.cxx
+  vvClipPolyData.cxx
   vvGlyphSource.cxx
   vvGlyph2D.cxx
   vvSlicerManager.cxx
diff --git a/vv/vvClipPolyData.cxx b/vv/vvClipPolyData.cxx
new file mode 100644
index 0000000..91f391b
--- /dev/null
+++ b/vv/vvClipPolyData.cxx
@@ -0,0 +1,80 @@
+#include "vvClipPolyData.h"
+
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformationVector.h"
+#include "vtkInformation.h"
+#include "vtkDataObject.h"
+#include "vtkSmartPointer.h"
+#include "vtkImplicitFunction.h"
+#include "vtkStringArray.h"
+#include "vtkPointData.h"
+
+
+vtkStandardNewMacro(vvClipPolyData);
+
+vvClipPolyData::vvClipPolyData()
+{
+  this->SetNumberOfInputPorts(1);
+  this->SetNumberOfOutputPorts(1);
+}
+
+vvClipPolyData::~vvClipPolyData()
+{
+
+}
+
+int vvClipPolyData::RequestData(vtkInformation *vtkNotUsed(request),
+					     vtkInformationVector **inputVector,
+					     vtkInformationVector *outputVector)
+{
+    // get the info objects
+    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+    vtkInformation *outInfo = outputVector->GetInformationObject(0);
+    // get the input and ouptut
+    vtkPolyData *input = vtkPolyData::SafeDownCast(
+			     inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    vtkStringArray* inputLabels = vtkStringArray::SafeDownCast(input->GetPointData()->GetAbstractArray("labels"));
+    vtkPolyData *output = vtkPolyData::SafeDownCast(
+			    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+    //
+    vtkImplicitFunction* currentImpliciteFunction = this->GetClipFunction();
+    int insideOutValue = this->GetInsideOut();
+    //if insideOutValue=0; we want to retrieve ouside points
+    //if insideOutValue=1; we want to retrieve inside points
+    vtkSmartPointer<vtkPoints> outputPoints = vtkSmartPointer<vtkPoints>::New();
+    vtkSmartPointer<vtkStringArray> outputStrings = vtkSmartPointer<vtkStringArray>::New();
+    outputStrings->SetName("labels");
+    for(vtkIdType i=0;i<input->GetNumberOfPoints();i++) {
+	//
+	double* currentPoint = input->GetPoint(i);
+	double currentIFvalue = currentImpliciteFunction->FunctionValue(currentPoint);
+	//if currentIFvalue>0, current point is outside the clip
+	if (currentIFvalue>0 && insideOutValue==0) {
+	    outputPoints->InsertNextPoint(currentPoint);
+	    vtkStdString label = inputLabels->GetValue(i);
+	    outputStrings->InsertNextValue(label);
+	}
+	//currentIFvalue<=0, current point is inside the clip
+	else if (currentIFvalue<=0 && insideOutValue==1) {
+	    outputPoints->InsertNextPoint(currentPoint);
+	    vtkStdString label = inputLabels->GetValue(i);
+	    outputStrings->InsertNextValue(label);
+	}
+	else {
+	    //vtkErrorMacro("vvClipPolyData - NOT IMPLEMENTED");
+	}
+    }
+    //
+    output->ShallowCopy(input);
+    output->SetPoints(outputPoints);
+    output->GetPointData()->AddArray(outputStrings);
+    return 1;
+}
+
+//----------------------------------------------------------------------------
+
+void vvClipPolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+    this->Superclass::PrintSelf(os,indent);
+}
diff --git a/vv/vvClipPolyData.h b/vv/vvClipPolyData.h
new file mode 100644
index 0000000..5bd3f86
--- /dev/null
+++ b/vv/vvClipPolyData.h
@@ -0,0 +1,25 @@
+#ifndef VVCLIPPOLYDATA_H
+#define VVCLIPPOLYDATA_H
+
+#include "vtkClipPolyData.h"
+
+class vvClipPolyData : public vtkClipPolyData
+{
+public:
+  vtkTypeMacro(vvClipPolyData,vtkClipPolyData);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  static vvClipPolyData *New();
+
+protected:
+  vvClipPolyData();
+  ~vvClipPolyData();
+
+  int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+private:
+  vvClipPolyData(const vvClipPolyData&);  // Not implemented.
+  void operator=(const vvClipPolyData&);  // Not implemented.
+};
+
+#endif // VVCLIPPOLYDATA_H
diff --git a/vv/vvLandmarks.cxx b/vv/vvLandmarks.cxx
index 682398f..0bab2f4 100644
--- a/vv/vvLandmarks.cxx
+++ b/vv/vvLandmarks.cxx
@@ -41,6 +41,8 @@ vvLandmarks::vvLandmarks(int size)
   }
   mPolyData = vtkPolyData::New();
   mIds = vtkFloatArray::New();
+  mLabels = vtkStringArray::New();
+  mLabels->SetName("labels");
 }
 //--------------------------------------------------------------------
 
@@ -58,6 +60,8 @@ vvLandmarks::~vvLandmarks()
     mIds->Delete();
   if (mPolyData)
     mPolyData->Delete();
+  if (mLabels)
+    mLabels->Delete();
 }
 //--------------------------------------------------------------------
 
@@ -66,14 +70,21 @@ vvLandmarks::~vvLandmarks()
 void vvLandmarks::AddLandmark(float x,float y,float z,float t,double value)
 {
   vvLandmark point;
+  vtkIdType idPoint;
   point.coordinates[0] = x;
   point.coordinates[1] = y;
   point.coordinates[2] = z;
   point.coordinates[3] = t;
   point.pixel_value=value;
   mLandmarks.push_back(point);
-  mPoints[int(t)]->InsertNextPoint(x,y,z);
-  
+
+  idPoint = mPoints[int(t)]->InsertNextPoint(x,y,z);
+  std::string str_vtkIdType;	    // string which will contain the result
+  std::ostringstream convert;	    // stream used for the conversion
+  convert << idPoint;	    		// insert the textual representation of 'idPoint' in the characters in the stream
+  str_vtkIdType = convert.str();    // set 'str_vtkIdType' to the contents of the stream
+  mLabels->InsertNextValue(str_vtkIdType.c_str());
+
   std::stringstream numberVal;
   numberVal << (mLandmarks.size()-1);
   /*
@@ -96,10 +107,12 @@ void vvLandmarks::RemoveLastLandmark()
 {
   mPoints[mLandmarks.back().coordinates[3]]->SetNumberOfPoints(
                                                                mPoints[mLandmarks.back().coordinates[3]]->GetNumberOfPoints()-1);
-  mPolyData->Modified();
   //  mText.pop_back();
   mLandmarks.pop_back();
   mIds->RemoveLastTuple();
+  mLabels->SetNumberOfValues(mLabels->GetNumberOfValues()-1);
+  mLabels->Modified();
+  mPolyData->Modified();
 }
 //--------------------------------------------------------------------
 
@@ -112,9 +125,17 @@ void vvLandmarks::RemoveLandmark(int index)
   // pologyons linking the points
   int npoints = mPoints[mLandmarks[index].coordinates[3]]->GetNumberOfPoints();
   int t = mLandmarks[index].coordinates[3];
-  for (int i = index; i < npoints - 1; i++)
+  for (int i = index; i < npoints - 1; i++) {
     mPoints[t]->InsertPoint(i, mPoints[t]->GetPoint(i+1));
+	std::string str_i;		     // string which will contain the result
+	std::ostringstream convert;	 // stream used for the conversion
+	convert << i;			     // insert the textual representation of 'i' in the characters in the stream
+	str_i = convert.str();		 // set 'str_i' to the contents of the stream
+	mLabels->SetValue(i,str_i.c_str());
+    }
   mPoints[t]->SetNumberOfPoints(npoints-1);
+  mLabels->SetNumberOfValues(npoints-1);
+  mLabels->Modified();
   mPolyData->Modified();
 
   mLandmarks.erase(mLandmarks.begin() + index);
@@ -165,6 +186,7 @@ void vvLandmarks::LoadFile(std::string filename)
   }
   mFilename = filename;
   mLandmarks.clear();
+  vtkIdType idPoint;
   char line[255];
   for (unsigned int i = 0; i < mPoints.size(); i++)
     mPoints[i]->SetNumberOfPoints(0);
@@ -246,8 +268,13 @@ void vvLandmarks::LoadFile(std::string filename)
       //      DD(point.comments);
       mLandmarks.push_back(point);
       mIds->InsertNextTuple1(0.55);
-      mPoints[int(point.coordinates[3])]->InsertNextPoint(
+     idPoint = mPoints[int(point.coordinates[3])]->InsertNextPoint(
                                                           point.coordinates[0],point.coordinates[1],point.coordinates[2]);
+     std::string str_vtkIdType;	    // string which will contain the result
+     std::ostringstream convert;	// stream used for the conversion
+     convert << idPoint;		    // insert the textual representation of 'idPoint' in the characters in the stream
+     str_vtkIdType = convert.str(); // set 'str_vtkIdType' to the contents of the stream
+     mLabels->InsertNextValue(str_vtkIdType.c_str());
     }
   }
   SetTime(0);
@@ -301,6 +328,7 @@ void vvLandmarks::SetTime(int time)
   if (time >= 0 && time <= ((int)mPoints.size() -1)) {
     mPolyData->SetPoints(mPoints[time]);
     mPolyData->GetPointData()->SetScalars(mIds);
+    mPolyData->GetPointData()->AddArray(mLabels);
     mPolyData->Modified();
     mPolyData->Update();
   }
diff --git a/vv/vvLandmarks.h b/vv/vvLandmarks.h
index 6bfe82e..8f94717 100644
--- a/vv/vvLandmarks.h
+++ b/vv/vvLandmarks.h
@@ -24,6 +24,7 @@
 #include "vtkPolyData.h"
 #include "vtkPoints.h"
 #include "vvLandmarksGlyph.h"
+#include "vtkStringArray.h"
 
 //typedef
 struct vvLandmark {
@@ -67,6 +68,7 @@ private:
     std::vector<vtkPoints*> mPoints;
     vtkFloatArray* mIds;
     //std::vector<vvLandmarksGlyph*> mText;
+    vtkStringArray* mLabels;
     std::string mFilename;
     int mFormatVersion;
 };
diff --git a/vv/vvMainWindow.cxx b/vv/vvMainWindow.cxx
index 8f94ff6..1432b16 100644
--- a/vv/vvMainWindow.cxx
+++ b/vv/vvMainWindow.cxx
@@ -101,9 +101,9 @@
 #define COLUMN_IMAGE_NAME 7
 
 #if CLITK_PRIVATE_FEATURES
-  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.usf)"
+  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.usf)"
 #else
-  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr)"
+  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan)"
 #endif
 
 /*Data Tree values
diff --git a/vv/vvSlicer.cxx b/vv/vvSlicer.cxx
index 17aa41b..548d0f3 100644
--- a/vv/vvSlicer.cxx
+++ b/vv/vvSlicer.cxx
@@ -41,6 +41,7 @@
 #include <vtkDataArray.h>
 #include <vtkFloatArray.h>
 #include <vtkClipPolyData.h>
+#include <vtkActor2DCollection.h>
 #include <vtkGlyph3D.h>
 #include <vtkMath.h>
 #include <vtkCursor3D.h>
@@ -580,36 +581,40 @@ void vvSlicer::SetLandmarks(vvLandmarks* landmarks)
 
     if (!mCross)
       mCross = vtkSmartPointer<vtkCursor3D>::New();
+	if (!mClipBox)
+      mClipBox = vtkSmartPointer<vtkBox>::New();
+    if (!mLandClipper)
+      mLandClipper = vtkSmartPointer<vvClipPolyData>::New();
+    if (!mLandGlyph)
+      mLandGlyph = vtkSmartPointer<vtkGlyph3D>::New();
+    if (!mLandMapper)
+      mLandMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+    if (!mLandActor)
+      mLandActor = vtkSmartPointer<vtkActor>::New();
+
     mCross->SetFocalPoint(0.0,0.0,0.0);
     mCross->SetModelBounds(-10,10,-10,10,-10,10);
     mCross->AllOff();
     mCross->AxesOn();
 
-    if (!mLandGlyph)
-      mLandGlyph = vtkSmartPointer<vtkGlyph3D>::New();
+    mLandClipper->SetClipFunction(mClipBox);
+    mLandClipper->InsideOutOn();
+    mLandClipper->SetInput(mLandmarks->GetOutput());
+
     mLandGlyph->SetSource(mCross->GetOutput());
-    mLandGlyph->SetInput(landmarks->GetOutput());
+    mLandGlyph->SetInput(mLandClipper->GetOutput());
     //mLandGlyph->SetIndexModeToScalar();
-    mLandGlyph->SetRange(0,1);
-    mLandGlyph->ScalingOff();
-
-    mLandGlyph->SetColorModeToColorByScalar();
+    //mLandGlyph->SetRange(0,1);
+    //mLandGlyph->ScalingOff();
 
-    if (!mClipBox)
-      mClipBox = vtkSmartPointer<vtkBox>::New();
-    if (!mLandClipper)
-      mLandClipper = vtkSmartPointer<vtkClipPolyData>::New();
-    mLandClipper->InsideOutOn();
-    mLandClipper->SetInput(mLandGlyph->GetOutput());
-    mLandClipper->SetClipFunction(mClipBox);
+    //mLandGlyph->SetColorModeToColorByScalar();
+    
+    mLandGlyph->SetScaleModeToDataScalingOff();
+    mLandGlyph->SetIndexModeToOff();
 
-    if (!mLandMapper)
-      mLandMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
-    mLandMapper->SetInputConnection(mLandClipper->GetOutputPort());
+    mLandMapper->SetInputConnection(mLandGlyph->GetOutputPort());
     //mLandMapper->ScalarVisibilityOff();
 
-    if (!mLandActor)
-      mLandActor = vtkSmartPointer<vtkActor>::New();
     mLandActor->SetMapper(mLandMapper);
     mLandActor->GetProperty()->SetColor(255,10,212);
     mLandActor->SetPickable(0);
@@ -1441,13 +1446,38 @@ void vvSlicer::UpdateLandmarks()
 {
   vtkPolyData *pd = static_cast<vtkPolyData*>(mLandClipper->GetInput());
   if (pd->GetPoints()) {
-    mLandGlyph->SetRange(0,1);
-    mLandGlyph->Modified();
-    mLandGlyph->Update();
+    //mLandGlyph->SetRange(0,1);
+    //mLandGlyph->Modified();
+    //mLandGlyph->Update();
 
     mClipBox->Modified();
     mLandClipper->Update();
     mLandMapper->Update();
+    //Let's add the captions
+    //First remove all captions:
+    for(unsigned int i=0;i<mLandLabelActors.size();i++) {
+	this->Renderer->RemoveActor2D(mLandLabelActors[i]);
+	//allActors2D->Remove (mLandLabelActors[i]);
+    }
+    mLandLabelActors.clear();
+    //Next add the captions to the displayed points
+    for (vtkIdType id=0; id<mLandClipper->GetOutput()->GetNumberOfPoints(); id++) {
+	  double *position = mLandClipper->GetOutput()->GetPoint(id);
+      vtkStdString label = static_cast<vtkStringArray*>(mLandClipper->GetOutput()->GetPointData()->GetAbstractArray("labels"))->GetValue(id);
+      vtkSmartPointer<vtkCaptionActor2D> label_actor = vtkSmartPointer<vtkCaptionActor2D>::New();
+      label_actor->SetCaption(label);
+      label_actor->SetAttachmentPoint(position);
+      label_actor->GetCaptionTextProperty()->SetColor(1,0,0);
+      label_actor->GetCaptionTextProperty()->SetOrientation(33.333333);
+      label_actor->GetCaptionTextProperty()->SetFontFamilyToTimes();
+      label_actor->GetCaptionTextProperty()->SetBold(0);
+      label_actor->GetCaptionTextProperty()->SetFontSize(6);
+      label_actor->BorderOff();
+      label_actor->LeaderOff();
+      label_actor->ThreeDimensionalLeaderOff();
+      mLandLabelActors.push_back(label_actor);
+      this->Renderer->AddActor2D(mLandLabelActors[id]);
+     }
   }
 
 }
diff --git a/vv/vvSlicer.h b/vv/vvSlicer.h
index 9a750e1..a738a78 100644
--- a/vv/vvSlicer.h
+++ b/vv/vvSlicer.h
@@ -24,11 +24,13 @@
 #include "vvImage.h"
 #include "vvMesh.h"
 #include "vvMeshActor.h"
+#include "vvClipPolyData.h"
 
 #include <vtkSmartPointer.h>
 #include <vtkImageViewer2.h>
 #include <vtkImageReslice.h>
 #include <vtkImageMapToColors.h>
+#include <vtkCaptionActor2D.h>
 
 class vtkActor;
 class vtkActor2D;
@@ -244,9 +246,10 @@ protected:
   vtkSmartPointer<vtkActor> mVFActor;
   vtkSmartPointer<vtkGlyph3D> mLandGlyph;
   vtkSmartPointer<vtkCursor3D> mCross;
-  vtkSmartPointer<vtkClipPolyData> mLandClipper;
+  vtkSmartPointer<vvClipPolyData> mLandClipper;
   vtkSmartPointer<vtkPolyDataMapper> mLandMapper;
   vtkSmartPointer<vtkActor> mLandActor;
+  std::vector<vtkSmartPointer<vtkCaptionActor2D> > mLandLabelActors;
   vtkSmartPointer<vtkBox> mClipBox;
   vtkSmartPointer<vtkScalarBarActor> legend;
   std::vector<vvMeshActor*> mSurfaceCutActors;
-- 
2.49.0