1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
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"
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>
33 //--------------------------------------------------------------------
34 vvLandmarks::vvLandmarks(int size)
39 for (int i = 0; i < size; i++) {
40 vtkPoints *points = vtkPoints::New();
41 mPoints.push_back(points);
43 mPolyData = vtkPolyData::New();
44 mIds = vtkFloatArray::New();
45 mLabels = vtkStringArray::New();
46 mLabels->SetName("labels");
48 //--------------------------------------------------------------------
51 //--------------------------------------------------------------------
52 vvLandmarks::~vvLandmarks()
54 for (unsigned int i = 0; i < mPoints.size(); i++) {
57 /*for(unsigned int i = 0; i < mText.size(); i++) {
67 //--------------------------------------------------------------------
70 //--------------------------------------------------------------------
71 void vvLandmarks::AddLandmark(float x,float y,float z,float t,double value)
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);
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());
89 std::stringstream numberVal;
90 numberVal << (mLandmarks.size()-1);
92 vvLandmarksGlyph *number = vvLandmarksGlyph::New();
93 number->SetText(numberVal.str().c_str());
95 DD(numberVal.str().c_str());
96 mText.push_back(number);
99 mIds->InsertNextTuple1(0.55);
100 //mIds->InsertTuple1(mLandmarks.size(),mLandmarks.size());
103 //--------------------------------------------------------------------
106 //--------------------------------------------------------------------
107 void vvLandmarks::RemoveLastLandmark()
109 mPoints[mLandmarks.back().coordinates[3]]->SetNumberOfPoints(
110 mPoints[mLandmarks.back().coordinates[3]]->GetNumberOfPoints()-1);
112 mLandmarks.pop_back();
113 mIds->RemoveLastTuple();
114 mLabels->SetNumberOfValues(mLabels->GetNumberOfValues()-1);
116 mPolyData->Modified();
118 //--------------------------------------------------------------------
121 //--------------------------------------------------------------------
122 void vvLandmarks::RemoveLandmark(int index)
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());
137 mPoints[t]->SetNumberOfPoints(npoints-1);
138 mLabels->SetNumberOfValues(npoints-1);
140 mPolyData->Modified();
142 mLandmarks.erase(mLandmarks.begin() + index);
143 mIds->RemoveLastTuple();
145 //--------------------------------------------------------------------
148 //--------------------------------------------------------------------
149 void vvLandmarks::ChangeComments(int index, std::string comments)
151 mLandmarks[index].comments = comments;
153 //--------------------------------------------------------------------
156 //--------------------------------------------------------------------
157 double vvLandmarks::GetPixelValue(int index)
159 return mLandmarks[index].pixel_value;
161 //--------------------------------------------------------------------
164 //--------------------------------------------------------------------
165 float* vvLandmarks::GetCoordinates(int index)
167 return mLandmarks[index].coordinates;
169 //--------------------------------------------------------------------
172 //--------------------------------------------------------------------
173 std::string vvLandmarks::GetComments(int index)
175 return mLandmarks[index].comments;
177 //--------------------------------------------------------------------
180 //--------------------------------------------------------------------
181 bool vvLandmarks::LoadFile(std::string filename)
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);
192 //--------------------------------------------------------------------
193 bool vvLandmarks::LoadTxtFile(std::string filename)
195 std::ifstream fp(filename.c_str(), std::ios::in|std::ios::binary);
197 std::cerr <<"Unable to open file " << filename << std::endl;
200 mFilename = filename;
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)) {
209 std::string stringline = line;
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
220 if (stringline.size() > 1) {
222 int previousSpace = 0;
224 if (mFormatVersion>0) {
225 space = stringline.find(" ", previousSpace+1);
226 if (space < -1 || space > (int)stringline.size()) {
227 ErrorMsg(mLandmarks.size(),"index");
230 //int index = atoi(stringline.substr(previousSpace,space - previousSpace).c_str());
231 previousSpace = space;
233 space = stringline.find(" ", previousSpace+1);
234 if (space < -1 || space > (int)stringline.size()) {
235 ErrorMsg(mLandmarks.size(),"x position");
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");
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");
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");
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");
269 point.pixel_value = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
270 // DD(point.pixel_value);
272 point.pixel_value=0.; //Not in file
273 point.coordinates[3]=0.;
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();
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());
297 //--------------------------------------------------------------------
299 //--------------------------------------------------------------------
300 bool vvLandmarks::LoadPtsFile(std::string filename)
302 std::ifstream fp(filename.c_str(), std::ios::in|std::ios::binary);
304 std::cerr <<"Unable to open file " << filename << std::endl;
307 mFilename = filename;
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)) {
316 std::string stringline = line;
317 if (stringline.size() > 1) {
319 int previousSpace = 0;
322 if (stringline[0] == '#') // comments
325 space = stringline.find("\t", previousSpace+1);
326 if (space < -1 || space > (int)stringline.size()) {
327 ErrorMsg(mLandmarks.size(),"x position");
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");
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");
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");
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");
361 point.pixel_value = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
362 // DD(point.pixel_value);
364 point.pixel_value=0.; //Not in file
365 point.coordinates[3]=0.;
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();
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());
389 //--------------------------------------------------------------------
391 //--------------------------------------------------------------------
392 bool vvLandmarks::ErrorMsg(int num,const char * text)
394 std::cerr << "error when loading point " << num << " at " << text << std::endl;
397 //--------------------------------------------------------------------
400 //--------------------------------------------------------------------
401 void vvLandmarks::SaveFile(std::string filename)
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
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)
417 fileContent += mLandmarks[i].comments;
420 std::ofstream fp(filename.c_str(), std::ios::trunc);
422 std::cerr << "Unable to open file" << std::endl;
425 fp << fileContent.c_str()<< std::endl;
428 //--------------------------------------------------------------------
431 //--------------------------------------------------------------------
432 void vvLandmarks::SetTime(int time)
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();
442 //--------------------------------------------------------------------
445 //--------------------------------------------------------------------
446 std::string vvLandmarks::replace_dots(std::string input)
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 );
457 //--------------------------------------------------------------------