]> Creatis software - clitk.git/blob - vv/vvLandmarks.cxx
Merge branch 'master' of git://git.creatis.insa-lyon.fr/clitk
[clitk.git] / vv / vvLandmarks.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ===========================================================================**/
18 #include "vvLandmarks.h"
19
20 #include <ios>
21 #include <fstream>
22 #include <sstream>
23 #include <string>
24 #include <locale.h>
25
26 #include "vtkPolyData.h"
27 #include "vtkPoints.h"
28 #include "vtkFloatArray.h"
29 #include "vtkPointData.h"
30 #include "clitkCommon.h"
31
32 //--------------------------------------------------------------------
33 vvLandmarks::vvLandmarks(int size)
34 {
35   mLandmarks.resize(0);
36   mFilename = "";
37
38   for (int i = 0; i < size; i++) {
39     vtkPoints *points = vtkPoints::New();
40     mPoints.push_back(points);
41   }
42   mPolyData = vtkPolyData::New();
43   mIds = vtkFloatArray::New();
44   mLabels = vtkStringArray::New();
45   mLabels->SetName("labels");
46 }
47 //--------------------------------------------------------------------
48
49
50 //--------------------------------------------------------------------
51 vvLandmarks::~vvLandmarks()
52 {
53   for (unsigned int i = 0; i < mPoints.size(); i++) {
54     mPoints[i]->Delete();
55   }
56   /*for(unsigned int i = 0; i < mText.size(); i++) {
57     mText[i]->Delete();
58     }*/
59   if (mIds)
60     mIds->Delete();
61   if (mPolyData)
62     mPolyData->Delete();
63   if (mLabels)
64     mLabels->Delete();
65 }
66 //--------------------------------------------------------------------
67
68
69 //--------------------------------------------------------------------
70 void vvLandmarks::AddLandmark(float x,float y,float z,float t,double value)
71 {
72   vvLandmark point;
73   vtkIdType idPoint;
74   point.coordinates[0] = x;
75   point.coordinates[1] = y;
76   point.coordinates[2] = z;
77   point.coordinates[3] = t;
78   point.pixel_value=value;
79   mLandmarks.push_back(point);
80
81   idPoint = mPoints[int(t)]->InsertNextPoint(x,y,z);
82   std::string str_vtkIdType;        // string which will contain the result
83   std::ostringstream convert;       // stream used for the conversion
84   convert << idPoint;                   // insert the textual representation of 'idPoint' in the characters in the stream
85   str_vtkIdType = convert.str();    // set 'str_vtkIdType' to the contents of the stream
86   mLabels->InsertNextValue(str_vtkIdType.c_str());
87
88   std::stringstream numberVal;
89   numberVal << (mLandmarks.size()-1);
90   /*
91   vvLandmarksGlyph *number = vvLandmarksGlyph::New();
92   number->SetText(numberVal.str().c_str());
93   number->BackingOff();
94   DD(numberVal.str().c_str());
95   mText.push_back(number);
96   */
97
98   mIds->InsertNextTuple1(0.55);
99   //mIds->InsertTuple1(mLandmarks.size(),mLandmarks.size());
100   SetTime(int(t));
101 }
102 //--------------------------------------------------------------------
103
104
105 //--------------------------------------------------------------------
106 void vvLandmarks::RemoveLastLandmark()
107 {
108   mPoints[mLandmarks.back().coordinates[3]]->SetNumberOfPoints(
109                                                                mPoints[mLandmarks.back().coordinates[3]]->GetNumberOfPoints()-1);
110   //  mText.pop_back();
111   mLandmarks.pop_back();
112   mIds->RemoveLastTuple();
113   mLabels->SetNumberOfValues(mLabels->GetNumberOfValues()-1);
114   mLabels->Modified();
115   mPolyData->Modified();
116 }
117 //--------------------------------------------------------------------
118
119
120 //--------------------------------------------------------------------
121 void vvLandmarks::RemoveLandmark(int index)
122 {
123   // erase a vtkPoint by shifiting the array .
124   // not a problem here because there are no 
125   // pologyons linking the points
126   int npoints = mPoints[mLandmarks[index].coordinates[3]]->GetNumberOfPoints();
127   int t = mLandmarks[index].coordinates[3];
128   for (int i = index; i < npoints - 1; i++) {
129     mPoints[t]->InsertPoint(i, mPoints[t]->GetPoint(i+1));
130         std::string str_i;                   // string which will contain the result
131         std::ostringstream convert;      // stream used for the conversion
132         convert << i;                        // insert the textual representation of 'i' in the characters in the stream
133         str_i = convert.str();           // set 'str_i' to the contents of the stream
134         mLabels->SetValue(i,str_i.c_str());
135     }
136   mPoints[t]->SetNumberOfPoints(npoints-1);
137   mLabels->SetNumberOfValues(npoints-1);
138   mLabels->Modified();
139   mPolyData->Modified();
140
141   mLandmarks.erase(mLandmarks.begin() + index);
142   mIds->RemoveLastTuple();
143 }
144 //--------------------------------------------------------------------
145
146
147 //--------------------------------------------------------------------
148 void vvLandmarks::ChangeComments(int index, std::string comments)
149 {
150   mLandmarks[index].comments = comments;
151 }
152 //--------------------------------------------------------------------
153
154
155 //--------------------------------------------------------------------
156 double vvLandmarks::GetPixelValue(int index)
157 {
158   return mLandmarks[index].pixel_value;
159 }
160 //--------------------------------------------------------------------
161
162
163 //--------------------------------------------------------------------
164 float* vvLandmarks::GetCoordinates(int index)
165 {
166   return mLandmarks[index].coordinates;
167 }
168 //--------------------------------------------------------------------
169
170
171 //--------------------------------------------------------------------
172 std::string vvLandmarks::GetComments(int index)
173 {
174   return mLandmarks[index].comments;
175 }
176 //--------------------------------------------------------------------
177
178
179 //--------------------------------------------------------------------
180 void vvLandmarks::LoadFile(std::string filename)
181 {
182   std::ifstream fp(filename.c_str(), std::ios::in|std::ios::binary);
183   if (!fp.is_open()) {
184     std::cerr <<"Unable to open file " << filename << std::endl;
185     return;
186   }
187   mFilename = filename;
188   mLandmarks.clear();
189   vtkIdType idPoint;
190   char line[255];
191   for (unsigned int i = 0; i < mPoints.size(); i++)
192     mPoints[i]->SetNumberOfPoints(0);
193   bool first_line=true;
194   while (fp.getline(line,255)) {
195     //    DD(line);
196     std::string stringline = line;
197     if (first_line) {
198       first_line=false;
199       ///New landmark format: first line is "LANDMARKSXX", where XX is the version number
200       if (stringline.size() >= 10 && stringline.compare(0,9,"LANDMARKS")==0) {
201         std::istringstream ss(stringline.c_str()+9);
202         ss >> mFormatVersion;
203         continue; //skip first line
204       } else
205         mFormatVersion=0;
206     }
207     if (stringline.size() > 1) {
208       vvLandmark point;
209       int previousSpace = 0;
210       int space=0;
211       if (mFormatVersion>0) {
212         space = stringline.find(" ", previousSpace+1);
213         if (space < -1 || space > (int)stringline.size()) {
214           ErrorMsg(mLandmarks.size(),"index");
215           continue;
216         }
217         //int index = atoi(stringline.substr(previousSpace,space - previousSpace).c_str());
218         previousSpace = space;
219       }
220       space = stringline.find(" ", previousSpace+1);
221       if (space < -1 || space > (int)stringline.size()) {
222         ErrorMsg(mLandmarks.size(),"x position");
223         continue;
224       }
225       point.coordinates[0] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
226       //      DD(point.coordinates[0]);
227       previousSpace = space;
228       space = stringline.find(" ", previousSpace+1);
229       if (space < -1 || space > (int)stringline.size()) {
230         ErrorMsg(mLandmarks.size(),"y position");
231         continue;
232       }
233       point.coordinates[1] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
234       //      DD(point.coordinates[1]);
235       previousSpace = space;
236       space = stringline.find(" ", previousSpace+1);
237       if (space < -1 || space > (int)stringline.size()) {
238         ErrorMsg(mLandmarks.size(),"z position");
239         continue;
240       }
241       point.coordinates[2] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
242       previousSpace = space;
243       if (mFormatVersion>0) {
244         space = stringline.find(" ", previousSpace+1);
245         if (space < -1 || space > (int)stringline.size()) {
246           ErrorMsg(mLandmarks.size(),"t position");
247           continue;
248         }
249         point.coordinates[3] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
250         previousSpace = space;
251         space = stringline.find(" ", previousSpace+1);
252         if (space < -1 || space > (int)stringline.size()) {
253           ErrorMsg(mLandmarks.size(),"pixel value");
254           continue;
255         }
256         point.pixel_value = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
257         //        DD(point.pixel_value);
258       } else {
259         point.pixel_value=0.; //Not in file
260         point.coordinates[3]=0.;
261       }
262       previousSpace = space;
263       //this is the maximum size of comments
264       space = (stringline.find("\n", previousSpace+1) < 254 ? stringline.find("\n", previousSpace+1) : 254);
265       if (previousSpace != -1) {
266         point.comments = stringline.substr(previousSpace,space - (previousSpace)).c_str();
267       }
268       //      DD(point.comments);
269       mLandmarks.push_back(point);
270       mIds->InsertNextTuple1(0.55);
271      idPoint = mPoints[int(point.coordinates[3])]->InsertNextPoint(
272                                                           point.coordinates[0],point.coordinates[1],point.coordinates[2]);
273      std::string str_vtkIdType;     // string which will contain the result
274      std::ostringstream convert;        // stream used for the conversion
275      convert << idPoint;                    // insert the textual representation of 'idPoint' in the characters in the stream
276      str_vtkIdType = convert.str(); // set 'str_vtkIdType' to the contents of the stream
277      mLabels->InsertNextValue(str_vtkIdType.c_str());
278     }
279   }
280   SetTime(0);
281 }
282 //--------------------------------------------------------------------
283
284
285 //--------------------------------------------------------------------
286 bool vvLandmarks::ErrorMsg(int num,const char * text)
287 {
288   std::cerr << "error when loading point " << num << " at " << text << std::endl;
289   return false;
290 }
291 //--------------------------------------------------------------------
292
293
294 //--------------------------------------------------------------------
295 void vvLandmarks::SaveFile(std::string filename)
296 {
297   std::string fileContent = "LANDMARKS1\n"; //File format version identification
298   for (unsigned int i = 0; i < mLandmarks.size(); i++) {
299     std::stringstream out;
300     out.imbue(std::locale("C")); //This is to specify that the dot is to be used as the decimal separator
301     out << i << " "
302         << mLandmarks[i].coordinates[0] << " "
303         << mLandmarks[i].coordinates[1] << " "
304         << mLandmarks[i].coordinates[2] << " "
305         << mLandmarks[i].coordinates[3] << " "
306         << mLandmarks[i].pixel_value << " ";
307     fileContent += out.str();
308     if (mLandmarks[i].comments.size() == 0)
309       fileContent += " ";
310     else
311       fileContent += mLandmarks[i].comments;
312     fileContent += "\n";
313   }
314   std::ofstream fp(filename.c_str(), std::ios::trunc);
315   if ( !fp ) {
316     std::cerr << "Unable to open file" << std::endl;
317     return;
318   }
319   fp << fileContent.c_str()<< std::endl;
320   fp.close();
321 }
322 //--------------------------------------------------------------------
323
324
325 //--------------------------------------------------------------------
326 void vvLandmarks::SetTime(int time)
327 {
328   if (time >= 0 && time <= ((int)mPoints.size() -1)) {
329     mPolyData->SetPoints(mPoints[time]);
330     mPolyData->GetPointData()->SetScalars(mIds);
331     mPolyData->GetPointData()->AddArray(mLabels);
332     mPolyData->Modified();
333     mPolyData->Update();
334   }
335 }
336 //--------------------------------------------------------------------
337
338
339 //--------------------------------------------------------------------
340 std::string vvLandmarks::replace_dots(std::string input)
341 {
342   ///Replaces the dots used in the file with the decimal separator in use on the platform
343   lconv * conv=localeconv();
344   unsigned int position = input.find( "." );
345   while ( position < input.size() ) {
346     input.replace(position, 1, conv->decimal_point);
347     position = input.find( ".", position + 1 );
348   }
349   return input;
350 }
351 //--------------------------------------------------------------------