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"
32 //--------------------------------------------------------------------
33 vvLandmarks::vvLandmarks(int size)
38 for (int i = 0; i < size; i++) {
39 vtkPoints *points = vtkPoints::New();
40 mPoints.push_back(points);
42 mPolyData = vtkPolyData::New();
43 mIds = vtkFloatArray::New();
44 mLabels = vtkStringArray::New();
45 mLabels->SetName("labels");
47 //--------------------------------------------------------------------
50 //--------------------------------------------------------------------
51 vvLandmarks::~vvLandmarks()
53 for (unsigned int i = 0; i < mPoints.size(); i++) {
56 /*for(unsigned int i = 0; i < mText.size(); i++) {
66 //--------------------------------------------------------------------
69 //--------------------------------------------------------------------
70 void vvLandmarks::AddLandmark(float x,float y,float z,float t,double value)
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);
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());
88 std::stringstream numberVal;
89 numberVal << (mLandmarks.size()-1);
91 vvLandmarksGlyph *number = vvLandmarksGlyph::New();
92 number->SetText(numberVal.str().c_str());
94 DD(numberVal.str().c_str());
95 mText.push_back(number);
98 mIds->InsertNextTuple1(0.55);
99 //mIds->InsertTuple1(mLandmarks.size(),mLandmarks.size());
102 //--------------------------------------------------------------------
105 //--------------------------------------------------------------------
106 void vvLandmarks::RemoveLastLandmark()
108 mPoints[mLandmarks.back().coordinates[3]]->SetNumberOfPoints(
109 mPoints[mLandmarks.back().coordinates[3]]->GetNumberOfPoints()-1);
111 mLandmarks.pop_back();
112 mIds->RemoveLastTuple();
113 mLabels->SetNumberOfValues(mLabels->GetNumberOfValues()-1);
115 mPolyData->Modified();
117 //--------------------------------------------------------------------
120 //--------------------------------------------------------------------
121 void vvLandmarks::RemoveLandmark(int index)
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());
136 mPoints[t]->SetNumberOfPoints(npoints-1);
137 mLabels->SetNumberOfValues(npoints-1);
139 mPolyData->Modified();
141 mLandmarks.erase(mLandmarks.begin() + index);
142 mIds->RemoveLastTuple();
144 //--------------------------------------------------------------------
147 //--------------------------------------------------------------------
148 void vvLandmarks::ChangeComments(int index, std::string comments)
150 mLandmarks[index].comments = comments;
152 //--------------------------------------------------------------------
155 //--------------------------------------------------------------------
156 double vvLandmarks::GetPixelValue(int index)
158 return mLandmarks[index].pixel_value;
160 //--------------------------------------------------------------------
163 //--------------------------------------------------------------------
164 float* vvLandmarks::GetCoordinates(int index)
166 return mLandmarks[index].coordinates;
168 //--------------------------------------------------------------------
171 //--------------------------------------------------------------------
172 std::string vvLandmarks::GetComments(int index)
174 return mLandmarks[index].comments;
176 //--------------------------------------------------------------------
179 //--------------------------------------------------------------------
180 void vvLandmarks::LoadFile(std::string filename)
182 std::ifstream fp(filename.c_str(), std::ios::in|std::ios::binary);
184 std::cerr <<"Unable to open file " << filename << std::endl;
187 mFilename = filename;
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)) {
196 std::string stringline = line;
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
207 if (stringline.size() > 1) {
209 int previousSpace = 0;
211 if (mFormatVersion>0) {
212 space = stringline.find(" ", previousSpace+1);
213 if (space < -1 || space > (int)stringline.size()) {
214 ErrorMsg(mLandmarks.size(),"index");
217 //int index = atoi(stringline.substr(previousSpace,space - previousSpace).c_str());
218 previousSpace = space;
220 space = stringline.find(" ", previousSpace+1);
221 if (space < -1 || space > (int)stringline.size()) {
222 ErrorMsg(mLandmarks.size(),"x position");
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");
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");
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");
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");
256 point.pixel_value = atof(replace_dots(stringline.substr(previousSpace,space - previousSpace)).c_str());
257 // DD(point.pixel_value);
259 point.pixel_value=0.; //Not in file
260 point.coordinates[3]=0.;
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();
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());
282 //--------------------------------------------------------------------
285 //--------------------------------------------------------------------
286 bool vvLandmarks::ErrorMsg(int num,const char * text)
288 std::cerr << "error when loading point " << num << " at " << text << std::endl;
291 //--------------------------------------------------------------------
294 //--------------------------------------------------------------------
295 void vvLandmarks::SaveFile(std::string filename)
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
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)
311 fileContent += mLandmarks[i].comments;
314 std::ofstream fp(filename.c_str(), std::ios::trunc);
316 std::cerr << "Unable to open file" << std::endl;
319 fp << fileContent.c_str()<< std::endl;
322 //--------------------------------------------------------------------
325 //--------------------------------------------------------------------
326 void vvLandmarks::SetTime(int time)
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();
336 //--------------------------------------------------------------------
339 //--------------------------------------------------------------------
340 std::string vvLandmarks::replace_dots(std::string input)
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 );
351 //--------------------------------------------------------------------