]> Creatis software - clitk.git/blob - vv/vvLandmarks.cxx
Merge branch 'master' of 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 #include <itksys/SystemTools.hxx>
32
33 //--------------------------------------------------------------------
34 vvLandmarks::vvLandmarks(int size)
35 {
36   mLandmarks.resize(0);
37   mFilename = "";
38
39   for (int i = 0; i < size; i++) {
40     vtkPoints *points = vtkPoints::New();
41     mPoints.push_back(points);
42   }
43   mPolyData = vtkPolyData::New();
44   mIds = vtkFloatArray::New();
45   mLabels = vtkStringArray::New();
46   mLabels->SetName("labels");
47 }
48 //--------------------------------------------------------------------
49
50
51 //--------------------------------------------------------------------
52 vvLandmarks::~vvLandmarks()
53 {
54   for (unsigned int i = 0; i < mPoints.size(); i++) {
55     mPoints[i]->Delete();
56   }
57   /*for(unsigned int i = 0; i < mText.size(); i++) {
58     mText[i]->Delete();
59     }*/
60   if (mIds)
61     mIds->Delete();
62   if (mPolyData)
63     mPolyData->Delete();
64   if (mLabels)
65     mLabels->Delete();
66 }
67 //--------------------------------------------------------------------
68
69
70 //--------------------------------------------------------------------
71 void vvLandmarks::AddLandmark(float x,float y,float z,float t,double value)
72 {
73   vvLandmark point;
74   vtkIdType idPoint;
75   point.coordinates[0] = x;
76   point.coordinates[1] = y;
77   point.coordinates[2] = z;
78   point.coordinates[3] = t;
79   point.pixel_value=value;
80   mLandmarks.push_back(point);
81
82   idPoint = mPoints[int(t)]->InsertNextPoint(x,y,z);
83   std::string str_vtkIdType;        // string which will contain the result
84   std::ostringstream convert;       // stream used for the conversion
85   convert << idPoint;                   // insert the textual representation of 'idPoint' in the characters in the stream
86   str_vtkIdType = convert.str();    // set 'str_vtkIdType' to the contents of the stream
87   mLabels->InsertNextValue(str_vtkIdType.c_str());
88
89   std::stringstream numberVal;
90   numberVal << (mLandmarks.size()-1);
91   /*
92   vvLandmarksGlyph *number = vvLandmarksGlyph::New();
93   number->SetText(numberVal.str().c_str());
94   number->BackingOff();
95   DD(numberVal.str().c_str());
96   mText.push_back(number);
97   */
98
99   mIds->InsertNextTuple1(0.55);
100   //mIds->InsertTuple1(mLandmarks.size(),mLandmarks.size());
101   SetTime(int(t));
102 }
103 //--------------------------------------------------------------------
104
105
106 //--------------------------------------------------------------------
107 void vvLandmarks::RemoveLastLandmark()
108 {
109   mPoints[mLandmarks.back().coordinates[3]]->SetNumberOfPoints(
110                                                                mPoints[mLandmarks.back().coordinates[3]]->GetNumberOfPoints()-1);
111   //  mText.pop_back();
112   mLandmarks.pop_back();
113   mIds->RemoveLastTuple();
114   mLabels->SetNumberOfValues(mLabels->GetNumberOfValues()-1);
115   mLabels->Modified();
116   mPolyData->Modified();
117 }
118 //--------------------------------------------------------------------
119
120
121 //--------------------------------------------------------------------
122 void vvLandmarks::RemoveLandmark(int index)
123 {
124   // erase a vtkPoint by shifiting the array .
125   // not a problem here because there are no 
126   // pologyons linking the points
127   int npoints = mPoints[mLandmarks[index].coordinates[3]]->GetNumberOfPoints();
128   int t = mLandmarks[index].coordinates[3];
129   for (int i = index; i < npoints - 1; i++) {
130     mPoints[t]->InsertPoint(i, mPoints[t]->GetPoint(i+1));
131         std::string str_i;                   // string which will contain the result
132         std::ostringstream convert;      // stream used for the conversion
133         convert << i;                        // insert the textual representation of 'i' in the characters in the stream
134         str_i = convert.str();           // set 'str_i' to the contents of the stream
135         mLabels->SetValue(i,str_i.c_str());
136     }
137   mPoints[t]->SetNumberOfPoints(npoints-1);
138   mLabels->SetNumberOfValues(npoints-1);
139   mLabels->Modified();
140   mPolyData->Modified();
141
142   mLandmarks.erase(mLandmarks.begin() + index);
143   mIds->RemoveLastTuple();
144 }
145 //--------------------------------------------------------------------
146
147
148 //--------------------------------------------------------------------
149 void vvLandmarks::ChangeComments(int index, std::string comments)
150 {
151   mLandmarks[index].comments = comments;
152 }
153 //--------------------------------------------------------------------
154
155
156 //--------------------------------------------------------------------
157 double vvLandmarks::GetPixelValue(int index)
158 {
159   return mLandmarks[index].pixel_value;
160 }
161 //--------------------------------------------------------------------
162
163
164 //--------------------------------------------------------------------
165 float* vvLandmarks::GetCoordinates(int index)
166 {
167   return mLandmarks[index].coordinates;
168 }
169 //--------------------------------------------------------------------
170
171
172 //--------------------------------------------------------------------
173 std::string vvLandmarks::GetComments(int index)
174 {
175   return mLandmarks[index].comments;
176 }
177 //--------------------------------------------------------------------
178
179
180 //--------------------------------------------------------------------
181 bool vvLandmarks::LoadFile(std::string filename)
182 {
183   std::string extension = itksys::SystemTools::GetFilenameExtension(filename);
184   if (extension == ".txt")
185     return LoadTxtFile(filename);
186   else if (extension == ".pts")
187     return LoadPtsFile(filename);
188
189   return false;
190 }
191
192 //--------------------------------------------------------------------
193 bool vvLandmarks::LoadTxtFile(std::string filename)
194 {
195   std::ifstream fp(filename.c_str(), std::ios::in|std::ios::binary);
196   if (!fp.is_open()) {
197     std::cerr <<"Unable to open file " << filename << std::endl;
198     return false;
199   }
200   mFilename = filename;
201   mLandmarks.clear();
202   vtkIdType idPoint;
203   char line[255];
204   for (unsigned int i = 0; i < mPoints.size(); i++)
205     mPoints[i]->SetNumberOfPoints(0);
206   bool first_line=true;
207   while (fp.getline(line,255)) {
208     //    DD(line);
209     std::string stringline = line;
210     if (first_line) {
211       first_line=false;
212       ///New landmark format: first line is "LANDMARKSXX", where XX is the version number
213       if (stringline.size() >= 10 && stringline.compare(0,9,"LANDMARKS")==0) {
214         std::istringstream ss(stringline.c_str()+9);
215         ss >> mFormatVersion;
216         continue; //skip first line
217       } else
218         mFormatVersion=0;
219     }
220     if (stringline.size() > 1) {
221       vvLandmark point;
222       int previousSpace = 0;
223       int space=0;
224       if (mFormatVersion>0) {
225         space = stringline.find(" ", previousSpace+1);
226         if (space < -1 || space > (int)stringline.size()) {
227           ErrorMsg(mLandmarks.size(),"index");
228           continue;
229         }
230         //int index = atoi(stringline.substr(previousSpace,space - previousSpace).c_str());
231         previousSpace = space;
232       }
233       space = stringline.find(" ", previousSpace+1);
234       if (space < -1 || space > (int)stringline.size()) {
235         ErrorMsg(mLandmarks.size(),"x position");
236         continue;
237       }
238       point.coordinates[0] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
239       //      DD(point.coordinates[0]);
240       previousSpace = space;
241       space = stringline.find(" ", previousSpace+1);
242       if (space < -1 || space > (int)stringline.size()) {
243         ErrorMsg(mLandmarks.size(),"y position");
244         continue;
245       }
246       point.coordinates[1] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
247       //      DD(point.coordinates[1]);
248       previousSpace = space;
249       space = stringline.find(" ", previousSpace+1);
250       if (space < -1 || space > (int)stringline.size()) {
251         ErrorMsg(mLandmarks.size(),"z position");
252         continue;
253       }
254       point.coordinates[2] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
255       previousSpace = space;
256       if (mFormatVersion>0) {
257         space = stringline.find(" ", previousSpace+1);
258         if (space < -1 || space > (int)stringline.size()) {
259           ErrorMsg(mLandmarks.size(),"t position");
260           continue;
261         }
262         point.coordinates[3] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
263         previousSpace = space;
264         space = stringline.find(" ", previousSpace+1);
265         if (space < -1 || space > (int)stringline.size()) {
266           ErrorMsg(mLandmarks.size(),"pixel value");
267           continue;
268         }
269         point.pixel_value = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
270         //        DD(point.pixel_value);
271       } else {
272         point.pixel_value=0.; //Not in file
273         point.coordinates[3]=0.;
274       }
275       previousSpace = space;
276       //this is the maximum size of comments
277       space = (stringline.find("\n", previousSpace+1) < 254 ? stringline.find("\n", previousSpace+1) : 254);
278       if (previousSpace != -1) {
279         point.comments = stringline.substr(previousSpace,space - (previousSpace)).c_str();
280       }
281       //      DD(point.comments);
282       mLandmarks.push_back(point);
283       mIds->InsertNextTuple1(0.55);
284      idPoint = mPoints[int(point.coordinates[3])]->InsertNextPoint(
285                                                           point.coordinates[0],point.coordinates[1],point.coordinates[2]);
286      std::string str_vtkIdType;     // string which will contain the result
287      std::ostringstream convert;        // stream used for the conversion
288      convert << idPoint;                    // insert the textual representation of 'idPoint' in the characters in the stream
289      str_vtkIdType = convert.str(); // set 'str_vtkIdType' to the contents of the stream
290      mLabels->InsertNextValue(str_vtkIdType.c_str());
291     }
292   }
293   SetTime(0);
294   
295   return true;
296 }
297 //--------------------------------------------------------------------
298
299 //--------------------------------------------------------------------
300 bool vvLandmarks::LoadPtsFile(std::string filename)
301 {
302   std::ifstream fp(filename.c_str(), std::ios::in|std::ios::binary);
303   if (!fp.is_open()) {
304     std::cerr <<"Unable to open file " << filename << std::endl;
305     return false;
306   }
307   mFilename = filename;
308   mLandmarks.clear();
309   vtkIdType idPoint;
310   char line[255];
311   for (unsigned int i = 0; i < mPoints.size(); i++)
312     mPoints[i]->SetNumberOfPoints(0);
313   bool first_line=true;
314   while (fp.getline(line,255)) {
315     //    DD(line);
316     std::string stringline = line;
317     if (stringline.size() > 1) {
318       vvLandmark point;
319       int previousSpace = 0;
320       int space=0;
321       
322       if (stringline[0] == '#') // comments
323         continue;
324       
325       space = stringline.find("\t", previousSpace+1);
326       if (space < -1 || space > (int)stringline.size()) {
327         ErrorMsg(mLandmarks.size(),"x position");
328         continue;
329       }
330       point.coordinates[0] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
331       //      DD(point.coordinates[0]);
332       previousSpace = space;
333       space = stringline.find("\t", previousSpace+1);
334       if (space < -1 || space > (int)stringline.size()) {
335         ErrorMsg(mLandmarks.size(),"y position");
336         continue;
337       }
338       point.coordinates[1] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
339       //      DD(point.coordinates[1]);
340       previousSpace = space;
341       space = stringline.find("\t", previousSpace+1);
342       if (space < -1 || space > (int)stringline.size()) {
343         ErrorMsg(mLandmarks.size(),"z position");
344         continue;
345       }
346       point.coordinates[2] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
347       previousSpace = space;
348       if (mFormatVersion>0) {
349         space = stringline.find("\t", previousSpace+1);
350         if (space < -1 || space > (int)stringline.size()) {
351           ErrorMsg(mLandmarks.size(),"t position");
352           continue;
353         }
354         point.coordinates[3] = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
355         previousSpace = space;
356         space = stringline.find("\t", previousSpace+1);
357         if (space < -1 || space > (int)stringline.size()) {
358           ErrorMsg(mLandmarks.size(),"pixel value");
359           continue;
360         }
361         point.pixel_value = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
362         //        DD(point.pixel_value);
363       } else {
364         point.pixel_value=0.; //Not in file
365         point.coordinates[3]=0.;
366       }
367       previousSpace = space;
368       //this is the maximum size of comments
369       space = (stringline.find("\n", previousSpace+1) < 254 ? stringline.find("\n", previousSpace+1) : 254);
370       if (previousSpace != -1) {
371         point.comments = stringline.substr(previousSpace,space - (previousSpace)).c_str();
372       }
373       //      DD(point.comments);
374       mLandmarks.push_back(point);
375       mIds->InsertNextTuple1(0.55);
376      idPoint = mPoints[int(point.coordinates[3])]->InsertNextPoint(
377                                                           point.coordinates[0],point.coordinates[1],point.coordinates[2]);
378      std::string str_vtkIdType;     // string which will contain the result
379      std::ostringstream convert;  // stream used for the conversion
380      convert << idPoint;        // insert the textual representation of 'idPoint' in the characters in the stream
381      str_vtkIdType = convert.str(); // set 'str_vtkIdType' to the contents of the stream
382      mLabels->InsertNextValue(str_vtkIdType.c_str());
383     }
384   }
385   SetTime(0);
386   
387   return true;
388 }
389 //--------------------------------------------------------------------
390
391 //--------------------------------------------------------------------
392 bool vvLandmarks::ErrorMsg(int num,const char * text)
393 {
394   std::cerr << "error when loading point " << num << " at " << text << std::endl;
395   return false;
396 }
397 //--------------------------------------------------------------------
398
399
400 //--------------------------------------------------------------------
401 void vvLandmarks::SaveFile(std::string filename)
402 {
403   std::string fileContent = "LANDMARKS1\n"; //File format version identification
404   for (unsigned int i = 0; i < mLandmarks.size(); i++) {
405     std::stringstream out;
406     out.imbue(std::locale("C")); //This is to specify that the dot is to be used as the decimal separator
407     out << i << " "
408         << mLandmarks[i].coordinates[0] << " "
409         << mLandmarks[i].coordinates[1] << " "
410         << mLandmarks[i].coordinates[2] << " "
411         << mLandmarks[i].coordinates[3] << " "
412         << mLandmarks[i].pixel_value << " ";
413     fileContent += out.str();
414     if (mLandmarks[i].comments.size() == 0)
415       fileContent += " ";
416     else
417       fileContent += mLandmarks[i].comments;
418     fileContent += "\n";
419   }
420   std::ofstream fp(filename.c_str(), std::ios::trunc);
421   if ( !fp ) {
422     std::cerr << "Unable to open file" << std::endl;
423     return;
424   }
425   fp << fileContent.c_str()<< std::endl;
426   fp.close();
427 }
428 //--------------------------------------------------------------------
429
430
431 //--------------------------------------------------------------------
432 void vvLandmarks::SetTime(int time)
433 {
434   if (time >= 0 && time <= ((int)mPoints.size() -1)) {
435     mPolyData->SetPoints(mPoints[time]);
436     mPolyData->GetPointData()->SetScalars(mIds);
437     mPolyData->GetPointData()->AddArray(mLabels);
438     mPolyData->Modified();
439     mPolyData->Update();
440   }
441 }
442 //--------------------------------------------------------------------
443
444
445 //--------------------------------------------------------------------
446 std::string vvLandmarks::replace_dots(std::string input)
447 {
448   ///Replaces the dots used in the file with the decimal separator in use on the platform
449   lconv * conv=localeconv();
450   unsigned int position = input.find( "." );
451   while ( position < input.size() ) {
452     input.replace(position, 1, conv->decimal_point);
453     position = input.find( ".", position + 1 );
454   }
455   return input;
456 }
457 //--------------------------------------------------------------------