IO.cpp
Go to the documentation of this file.
00001 // kate: replace-tabs off; indent-width 4; indent-mode normal
00002 // vim: ts=4:sw=4:noexpandtab
00003 /*
00004 
00005 Copyright (c) 2010--2012,
00006 François Pomerleau and Stephane Magnenat, ASL, ETHZ, Switzerland
00007 You can contact the authors at <f dot pomerleau at gmail dot com> and
00008 <stephane at magnenat dot net>
00009 
00010 All rights reserved.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014     * Redistributions of source code must retain the above copyright
00015       notice, this list of conditions and the following disclaimer.
00016     * Redistributions in binary form must reproduce the above copyright
00017       notice, this list of conditions and the following disclaimer in the
00018       documentation and/or other materials provided with the distribution.
00019     * Neither the name of the <organization> nor the
00020       names of its contributors may be used to endorse or promote products
00021       derived from this software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026 DISCLAIMED. IN NO EVENT SHALL ETH-ASL BE LIABLE FOR ANY
00027 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00030 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "IO.h"
00037 #include "InspectorsImpl.h"
00038 
00039 #include <iostream>
00040 #include <fstream>
00041 #include <stdexcept>
00042 #include <ctype.h>
00043 #include "boost/algorithm/string.hpp"
00044 #include "boost/filesystem.hpp"
00045 #include "boost/filesystem/path.hpp"
00046 #include "boost/filesystem/operations.hpp"
00047 #include "boost/lexical_cast.hpp"
00048 
00049 
00050 using namespace std;
00051 using namespace PointMatcherSupport;
00052 
00053 
00054 // Tokenize a string, excepted if it begins with a '%' (a comment in CSV)
00055 static std::vector<string> csvLineToVector(const char* line)
00056 {
00057     std::vector<string> parsedLine;
00058     char delimiters[] = " \t,;";
00059     char *token;
00060     char tmpLine[1024];
00061     char *brkt;
00062     strcpy(tmpLine, line);
00063     token = strtok_r(tmpLine, delimiters, &brkt);
00064     if(line[0] != '%') // Jump line if it's commented
00065     {
00066         while (token)
00067         {
00068             parsedLine.push_back(string(token));
00069             token = strtok_r(NULL, delimiters, &brkt);
00070         }
00071     }
00072 
00073     return parsedLine;
00074 }
00075 
00076 // Open and parse a CSV file, return the data
00077 CsvElements parseCsvWithHeader(const std::string& fileName)
00078 {
00079     validateFile(fileName);
00080     
00081     ifstream is(fileName.c_str());
00082 
00083     unsigned elementCount=0;
00084     std::map<string, unsigned> keywordCols;
00085     CsvElements data;
00086 
00087     bool firstLine(true);
00088     unsigned lineCount=0;
00089     while (!is.eof())
00090     {
00091         char line[1024];
00092         is.getline(line, sizeof(line));
00093         line[sizeof(line)-1] = 0;
00094 
00095         if(firstLine)
00096         {
00097             std::vector<string> header = csvLineToVector(line);
00098                 
00099             elementCount = header.size();
00100             for(unsigned int i = 0; i < elementCount; i++)
00101             {
00102                 keywordCols[header[i]] = i;
00103             }
00104 
00105             firstLine = false;
00106         }
00107         else // load the rest of the file
00108         {
00109             std::vector<string> parsedLine = csvLineToVector(line);
00110             if(parsedLine.size() != elementCount && parsedLine.size() !=0)
00111             {
00112                 stringstream errorMsg;
00113                 errorMsg << "Error at line " << lineCount+1 << ": expecting " << elementCount << " columns but read " << parsedLine.size() << " elements.";
00114                 throw runtime_error(errorMsg.str());    
00115             }
00116 
00117             for(unsigned int i = 0; i < parsedLine.size(); i++)
00118             {
00119                 for(auto it=keywordCols.begin(); it!=keywordCols.end(); it++)
00120                 {
00121                     if(i == (*it).second)
00122                     {
00123                         data[(*it).first].push_back(parsedLine[i]); 
00124                     }
00125                 }
00126             }
00127         }
00128 
00129         lineCount++;
00130     }
00131     
00132     // Use for debug
00133     
00134     //for(auto it=data.begin(); it!=data.end(); it++)
00135     //{
00136     //  cout << "--------------------------" << endl;
00137     //  cout << "Header: |" << (*it).first << "|" << endl;
00138     //  //for(unsigned i=0; i<(*it).second.size(); i++)
00139     //  //{
00140     //  //  cout << (*it).second[i] << endl;
00141     //  //}
00142     //}
00143     
00144 
00145     return data;
00146 }
00147 
00148 
00150 template<typename T>
00151 PointMatcherIO<T>::FileInfo::FileInfo(const std::string& readingFileName, const std::string& referenceFileName, const std::string& configFileName, const TransformationParameters& initialTransformation, const TransformationParameters& groundTruthTransformation, const Vector& grativity):
00152     readingFileName(readingFileName),
00153     referenceFileName(referenceFileName),
00154     configFileName(configFileName),
00155     initialTransformation(initialTransformation),
00156     groundTruthTransformation(groundTruthTransformation),
00157     gravity(gravity)
00158 {}
00159 
00160 template struct PointMatcherIO<float>::FileInfo;
00161 template struct PointMatcherIO<double>::FileInfo;
00162 
00163 // Empty constructor
00164 template<typename T>
00165 PointMatcherIO<T>::FileInfoVector::FileInfoVector()
00166 {
00167 }
00168 
00170 
00183 template<typename T>
00184 PointMatcherIO<T>::FileInfoVector::FileInfoVector(const std::string& fileName, std::string dataPath, std::string configPath)
00185 {
00186     if (dataPath.empty())
00187     {
00188         #if BOOST_FILESYSTEM_VERSION >= 3
00189         dataPath = boost::filesystem::path(fileName).parent_path().string();
00190         #else
00191         dataPath = boost::filesystem::path(fileName).parent_path().file_string();
00192         #endif
00193     }
00194     if (configPath.empty())
00195     {
00196         #if BOOST_FILESYSTEM_VERSION >= 3
00197         configPath = boost::filesystem::path(fileName).parent_path().string();
00198         #else
00199         configPath = boost::filesystem::path(fileName).parent_path().file_string();
00200         #endif
00201     }
00202     
00203     const CsvElements data = parseCsvWithHeader(fileName);
00204     
00205     // Look for transformations
00206     const bool found3dInitialTrans(findTransform(data, "iT", 3));
00207     bool found2dInitialTrans(findTransform(data, "iT", 2));
00208     const bool found3dGroundTruthTrans(findTransform(data, "gT", 3));
00209     bool found2dGroundTruthTrans(findTransform(data, "gT", 2));
00210     if (found3dInitialTrans)
00211         found2dInitialTrans = false;
00212     if (found3dGroundTruthTrans)
00213         found2dGroundTruthTrans = false;
00214     
00215     // Check for consistency
00216     if (found3dInitialTrans && found2dGroundTruthTrans)
00217         throw runtime_error("Initial transformation is in 3D but ground-truth is in 2D");
00218     if (found2dInitialTrans && found3dGroundTruthTrans)
00219         throw runtime_error("Initial transformation is in 2D but ground-truth is in 3D");
00220     CsvElements::const_iterator readingIt(data.find("reading"));
00221     if (readingIt == data.end())
00222         throw runtime_error("Error transfering CSV to structure: The header should at least contain \"reading\".");
00223     CsvElements::const_iterator referenceIt(data.find("reference"));
00224     CsvElements::const_iterator configIt(data.find("config"));
00225     
00226     // Load reading
00227     const std::vector<string>& readingFileNames = readingIt->second;
00228     const unsigned lineCount = readingFileNames.size();
00229     boost::optional<std::vector<string> > referenceFileNames;
00230     boost::optional<std::vector<string> > configFileNames;
00231     if (referenceIt != data.end())
00232     {
00233         referenceFileNames = referenceIt->second;
00234         assert (referenceFileNames->size() == lineCount);
00235     }
00236     if (configIt != data.end())
00237     {
00238         configFileNames = configIt->second;
00239         assert (configFileNames->size() == lineCount);
00240     }
00241 
00242     // for every lines
00243     for(unsigned line=0; line<lineCount; line++)
00244     {
00245         FileInfo info;
00246         
00247         // Files
00248         info.readingFileName = localToGlobalFileName(dataPath, readingFileNames[line]);
00249         if (referenceFileNames)
00250             info.referenceFileName = localToGlobalFileName(dataPath, (*referenceFileNames)[line]);
00251         if (configFileNames)
00252             info.configFileName = localToGlobalFileName(configPath, (*configFileNames)[line]);
00253         
00254         // Load transformations
00255         if(found3dInitialTrans)
00256             info.initialTransformation = getTransform(data, "iT", 3, line);
00257         if(found2dInitialTrans)
00258             info.initialTransformation = getTransform(data, "iT", 2, line);
00259         if(found3dGroundTruthTrans)
00260             info.groundTruthTransformation = getTransform(data, "gT", 3, line);
00261         if(found2dGroundTruthTrans)
00262             info.groundTruthTransformation = getTransform(data, "gT", 2, line);
00263         
00264         // Build the list
00265         this->push_back(info);
00266     }
00267     
00268     // Debug: Print the list
00269     /*for(unsigned i=0; i<list.size(); i++)
00270     {
00271         cout << "\n--------------------------" << endl;
00272         cout << "Sequence " << i << ":" << endl;
00273         cout << "Reading path: " << list[i].readingFileName << endl;
00274         cout << "Reference path: " << list[i].referenceFileName << endl;
00275         cout << "Extension: " << list[i].fileExtension << endl;
00276         cout << "Tranformation:\n" << list[i].initialTransformation << endl;
00277         cout << "Grativity:\n" << list[i].gravity << endl;
00278     }
00279     */
00280 }
00281 
00283 template<typename T>
00284 std::string PointMatcherIO<T>::FileInfoVector::localToGlobalFileName(const std::string& parentPath, const std::string& fileName)
00285 {
00286     std::string globalFileName(fileName);
00287     if (!boost::filesystem::exists(globalFileName))
00288     {
00289         const boost::filesystem::path globalFilePath(boost::filesystem::path(parentPath) /  boost::filesystem::path(fileName));
00290         #if BOOST_FILESYSTEM_VERSION >= 3
00291         globalFileName = globalFilePath.string();
00292         #else
00293         globalFileName = globalFilePath.file_string();
00294         #endif
00295     }
00296     validateFile(globalFileName);
00297     return globalFileName;
00298 }
00299 
00301 template<typename T>
00302 bool PointMatcherIO<T>::FileInfoVector::findTransform(const CsvElements& data, const std::string& prefix, unsigned dim)
00303 {
00304     bool found(true);
00305     for(unsigned i=0; i<dim+1; i++)
00306     {
00307         for(unsigned j=0; j<dim+1; j++)
00308         {
00309             stringstream transName;
00310             transName << prefix << i << j;
00311             found = found && (data.find(transName.str()) != data.end());
00312         }
00313     }
00314     return found;
00315 }
00316 
00318 template<typename T>
00319 typename PointMatcherIO<T>::TransformationParameters PointMatcherIO<T>::FileInfoVector::getTransform(const CsvElements& data, const std::string& prefix, unsigned dim, unsigned line)
00320 {
00321     TransformationParameters transformation(TransformationParameters::Identity(dim+1, dim+1));
00322     for(unsigned i=0; i<dim+1; i++)
00323     {
00324         for(unsigned j=0; j<dim+1; j++)
00325         {
00326             stringstream transName;
00327             transName << prefix << i << j;
00328             CsvElements::const_iterator colIt(data.find(transName.str()));
00329             const T value = boost::lexical_cast<T> (colIt->second[line]);
00330             transformation(i,j) = value;
00331         }
00332     }
00333     return transformation;
00334 }
00335 
00336 template struct PointMatcherIO<float>::FileInfoVector;
00337 template struct PointMatcherIO<double>::FileInfoVector;
00338 
00340 void PointMatcherSupport::validateFile(const std::string& fileName)
00341 {
00342     boost::filesystem::path fullPath(fileName);
00343 
00344     ifstream ifs(fileName.c_str());
00345     if (!ifs.good())
00346     #if BOOST_FILESYSTEM_VERSION >= 3
00347       #if BOOST_VERSION >= 105000
00348             throw runtime_error(string("Cannot open file ") + boost::filesystem::complete(fullPath).native());
00349       #else
00350             throw runtime_error(string("Cannot open file ") + boost::filesystem3::complete(fullPath).native());
00351       #endif
00352     #else
00353         throw runtime_error(string("Cannot open file ") + boost::filesystem::complete(fullPath).native_file_string());
00354     #endif
00355 }
00356 
00357 
00359 template<typename T>
00360 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::load(const std::string& fileName)
00361 {
00362     const boost::filesystem::path path(fileName);
00363     const string& ext(boost::filesystem::extension(path));
00364     if (boost::iequals(ext, ".vtk"))
00365         return PointMatcherIO<T>::loadVTK(fileName);
00366     else if (boost::iequals(ext, ".csv"))
00367         return PointMatcherIO<T>::loadCSV(fileName);
00368     else
00369         throw runtime_error("loadAnyFormat(): Unknown extension \"" + ext + "\" for file \"" + fileName + "\", extension must be either \".vtk\" or \".csv\"");
00370 }
00371 
00372 template
00373 PointMatcher<float>::DataPoints PointMatcher<float>::DataPoints::load(const std::string& fileName);
00374 template
00375 PointMatcher<double>::DataPoints PointMatcher<double>::DataPoints::load(const std::string& fileName);
00376 
00377 
00390 template<typename T>
00391 typename PointMatcher<T>::DataPoints PointMatcherIO<T>::loadCSV(const std::string& fileName)
00392 {
00393     ifstream ifs(fileName.c_str());
00394     
00395     validateFile(fileName);
00396 
00397     return loadCSV(ifs);
00398 }
00399 
00402 template<typename T>
00403 typename PointMatcher<T>::DataPoints PointMatcherIO<T>::loadCSV(std::istream& is)
00404 {
00405     typedef typename DataPoints::Label Label;
00406     typedef typename DataPoints::Labels Labels;
00407     
00408     vector<T> xData;
00409     vector<T> yData;
00410     vector<T> zData;
00411     vector<T> padData;
00412     vector<string> header;
00413     int dim(0);
00414     bool firstLine(true);
00415     bool hasHeader(false);
00416     Labels labels;
00417     int xCol(-1);
00418     int yCol(-1);
00419     int zCol(-1);
00420 
00421     char delimiters[] = " \t,;";
00422     char *token;
00423     while (!is.eof())
00424     {
00425         char line[1024];
00426         is.getline(line, sizeof(line));
00427         line[sizeof(line)-1] = 0;
00428     
00429         // Look for text header
00430         unsigned int len = strspn(line, " ,+-.1234567890Ee");
00431         if(len != strlen(line))
00432         {
00433             //cout << "Header detected" << endl;
00434             hasHeader = true;
00435         }
00436         else
00437         {
00438             hasHeader = false;
00439         }
00440 
00441         // Count dimension using first line
00442         if(firstLine)
00443         {
00444             char tmpLine[1024];
00445             char *brkt;
00446             strcpy(tmpLine, line);
00447             token = strtok_r(tmpLine, delimiters, &brkt);
00448             while (token)
00449             {
00450                 dim++;
00451                 
00452                 // Load text header
00453                 if(hasHeader)
00454                 {
00455                     header.push_back(string(token));
00456                 }
00457 
00458                 token = strtok_r(NULL, delimiters, &brkt);
00459             }
00460         
00461                 
00462             if (hasHeader)
00463             {
00464                 // Search for x, y and z tags
00465                 for(unsigned int i = 0; i < header.size(); i++)
00466                 {
00467                     if(header[i].compare("x") == 0)
00468                         xCol = i;
00469                 
00470                     if(header[i].compare("y") == 0)
00471                         yCol = i;
00472                 
00473                     if(header[i].compare("z") == 0)
00474                         zCol = i;
00475                 }
00476                 if(xCol == -1 || yCol == -1)
00477                 {
00478                     for(unsigned int i = 0; i < header.size(); i++)
00479                     {
00480                         cout << "(" << i << ") " << header[i] << endl;
00481                     }
00482                     cout << endl << "Enter ID for x: ";
00483                     cin >> xCol;
00484                     cout << "Enter ID for y: ";
00485                     cin >> yCol;
00486                     cout << "Enter ID for z (-1 if 2D data): ";
00487                     cin >> zCol;
00488                 }
00489             }
00490             else
00491             {
00492                 // Check if it is a simple file with only coordinates
00493                 if (!(dim == 2 || dim == 3))
00494                 {
00495                     cout << "WARNING: " << dim << " columns detected. Not obivious which columns to load for x, y or z." << endl;
00496                     cout << endl << "Enter column ID (starting from 0) for x: ";
00497                     cin >> xCol;
00498                     cout << "Enter column ID (starting from 0) for y: ";
00499                     cin >> yCol;
00500                     cout << "Enter column ID (starting from 0, -1 if 2D data) for z: ";
00501                     cin >> zCol;
00502                 }
00503                 else
00504                 {
00505                     // Assume logical order...
00506                     xCol = 0;
00507                     yCol = 1;
00508                     if(dim == 3)
00509                         zCol = 2;
00510                 }
00511             }
00512 
00513             if(zCol != -1)
00514                 dim = 3;
00515             else
00516                 dim = 2;
00517         }
00518 
00519         // Load data!
00520         char *brkt;
00521         token = strtok_r(line, delimiters, &brkt);
00522         int currentCol = 0;
00523         while (token)
00524         {
00525             // Load data only if no text is on the line
00526             if(!hasHeader)
00527             {
00528                 if(currentCol == xCol)
00529                     xData.push_back(atof(token));
00530                 if(currentCol == yCol)
00531                     yData.push_back(atof(token));
00532                 if(currentCol == zCol)
00533                     zData.push_back(atof(token));
00534             }
00535 
00536             token = strtok_r(NULL, delimiters, &brkt);
00537             currentCol++;
00538         }
00539         
00540         // Add one for uniform coordinates
00541         padData.push_back(1);
00542         
00543         if (firstLine)
00544         {
00545             // create standard labels
00546             for (int i=0; i < dim; i++)
00547             {
00548                 string text;
00549                 text += char('x' + i);
00550                 labels.push_back(Label(text, 1));
00551             }
00552             labels.push_back(Label("pad", 1));
00553         }
00554 
00555         firstLine = false;
00556     }
00557 
00558     assert(xData.size() == yData.size());
00559     int nbPoints = xData.size();
00560 
00561     // Transfer loaded points in specific structure (eigen matrix)
00562     Matrix features(dim+1, nbPoints);
00563     for(int i=0; i < nbPoints; i++)
00564     {
00565         features(0,i) = xData[i];
00566         features(1,i) = yData[i];
00567         if(dim == 3)
00568         {
00569             features(2,i) = zData[i];
00570             features(3,i) = 1;
00571         }
00572         else
00573         {
00574             features(2,i) = 1;
00575         }
00576     }
00577     
00578     DataPoints dataPoints(features, labels);
00579     //cout << "Loaded " << dataPoints.features.cols() << " points." << endl;
00580     //cout << "Find " << dataPoints.features.rows() << " dimensions." << endl;
00581     //cout << features << endl;
00582 
00583     return dataPoints;
00584 }
00585 
00586 template
00587 PointMatcher<float>::DataPoints PointMatcherIO<float>::loadCSV(const std::string& fileName);
00588 template
00589 PointMatcher<double>::DataPoints PointMatcherIO<double>::loadCSV(const std::string& fileName);
00590 
00592 template<typename T>
00593 void PointMatcher<T>::DataPoints::save(const std::string& fileName) const
00594 {
00595     const boost::filesystem::path path(fileName);
00596     const string& ext(boost::filesystem::extension(path));
00597     if (boost::iequals(ext, ".vtk"))
00598         return PointMatcherIO<T>::saveVTK(*this, fileName);
00599     else if (boost::iequals(ext, ".csv"))
00600         return PointMatcherIO<T>::saveCSV(*this, fileName);
00601     else
00602         throw runtime_error("saveAnyFormat(): Unknown extension \"" + ext + "\" for file \"" + fileName + "\", extension must be either \".vtk\" or \".csv\"");
00603 }
00604 
00605 template
00606 void PointMatcher<float>::DataPoints::save(const std::string& fileName) const;
00607 template
00608 void PointMatcher<double>::DataPoints::save(const std::string& fileName) const;
00609 
00611 template<typename T>
00612 void PointMatcherIO<T>::saveCSV(const DataPoints& data, const std::string& fileName)
00613 {
00614     ofstream ofs(fileName.c_str());
00615     if (!ofs.good())
00616         throw runtime_error(string("Cannot open file ") + fileName);
00617     saveCSV(data, ofs);
00618 }
00619 
00621 template<typename T>
00622 void PointMatcherIO<T>::saveCSV(const DataPoints& data, std::ostream& os)
00623 {
00624     const int pointCount(data.features.cols());
00625     const int dimCount(data.features.rows());
00626     
00627     if (pointCount == 0)
00628     {
00629         cerr << "Warning, no points, doing nothing" << endl;
00630         return;
00631     }
00632     
00633     // write points
00634     for (int p = 0; p < pointCount; ++p)
00635     {
00636         for (int i = 0; i < dimCount-1; ++i)
00637         {
00638             os << data.features(i, p);
00639             if(i != dimCount-2)
00640                 os << " , ";
00641         }
00642         os << "\n";
00643     }
00644     
00645 }
00646 
00647 template
00648 void PointMatcherIO<float>::saveCSV(const DataPoints& data, const std::string& fileName);
00649 template
00650 void PointMatcherIO<double>::saveCSV(const DataPoints& data, const std::string& fileName);
00651 
00653 template<typename T>
00654 typename PointMatcher<T>::DataPoints PointMatcherIO<T>::loadVTK(const std::string& fileName)
00655 {
00656     ifstream ifs(fileName.c_str());
00657     if (!ifs.good())
00658         throw runtime_error(string("Cannot open file ") + fileName);
00659     return loadVTK(ifs);
00660 }
00661 
00663 template<typename T>
00664 typename PointMatcher<T>::DataPoints PointMatcherIO<T>::loadVTK(std::istream& is)
00665 {
00666     typedef typename DataPoints::Label Label;
00667     typedef typename DataPoints::Labels Labels;
00668     
00669     DataPoints loadedPoints;
00670 
00671     // parse header
00672     string line;
00673     getline(is, line);
00674     if (line.find("# vtk DataFile Version") != 0)
00675         throw runtime_error(string("Wrong magic header, found ") + line);
00676     getline(is, line);
00677     getline(is, line);
00678     if (line != "ASCII")
00679         throw runtime_error(string("Wrong file type, expecting ASCII, found ") + line);
00680     getline(is, line);
00681     if (line != "DATASET POLYDATA")
00682         throw runtime_error(string("Wrong data type, expecting DATASET POLYDATA, found ") + line);
00683 
00684 
00685     // parse points and descriptors
00686     string fieldName;
00687     string name;
00688     int pointCount = 0;
00689     string type;
00690     while (is.good())
00691     {
00692         is >> fieldName;
00693         
00694         // load features
00695         if(fieldName == "POINTS")
00696         {
00697             is >> pointCount;
00698             is >> type;
00699             
00700             if(!(type == "float" || type == "double"))
00701                     throw runtime_error(string("Field POINTS can only be of type double or float"));
00702 
00703             Matrix features(4, pointCount);
00704             for (int p = 0; p < pointCount; ++p)
00705             {
00706                 is >> features(0, p);
00707                 is >> features(1, p);
00708                 is >> features(2, p);
00709                 features(3, p) = 1.0;
00710             }
00711             loadedPoints.addFeature("x", features.row(0));
00712             loadedPoints.addFeature("y", features.row(1));
00713             loadedPoints.addFeature("z", features.row(2));
00714             loadedPoints.addFeature("pad", features.row(3));
00715         }
00716         else if(fieldName == "VERTICES")
00717         {
00718             int size;
00719             int verticeSize;
00720             is >> size >> verticeSize;
00721             // Skip vertice definition
00722             for (int p = 0; p < pointCount; p++)
00723             {
00724                 getline(is, line); 
00725                 if(line == "")
00726                     p--;
00727             }
00728         }
00729         else if(fieldName == "POINT_DATA")
00730         {
00731             int descriptorCount;
00732             is >> descriptorCount;
00733             if(pointCount != descriptorCount)
00734                 throw runtime_error(string("The size of POINTS is different than POINT_DATA"));
00735         }
00736         else // Load descriptors
00737         {
00738             // descriptor name
00739             is >> name;
00740 
00741             int dim = 0;
00742             bool skipLookupTable = false;
00743             if(fieldName == "SCALARS")
00744             {
00745                 dim = 1;
00746                 is >> type;
00747                 skipLookupTable = true;
00748             }
00749             else if(fieldName == "VECTORS")
00750             {
00751                 dim = 3;
00752                 is >> type;
00753             }
00754             else if(fieldName == "TENSORS")
00755             {
00756                 dim = 9;
00757                 is >> type;
00758             }
00759             else if(fieldName == "NORMALS")
00760             {
00761                 dim = 3;
00762                 is >> type;
00763             }
00764             else if(fieldName == "COLOR_SCALARS")
00765             {
00766                 is >> dim;
00767                 type = "float";
00768             }
00769             else
00770                 throw runtime_error(string("Unknown field name " + fieldName + ", expecting SCALARS, VECTORS, TENSORS, NORMALS or COLOR_SCALARS."));
00771 
00772             
00773             if(!(type == "float" || type == "double"))
00774                     throw runtime_error(string("Field " + fieldName + " is " + type + " but can only be of type double or float"));
00775                      
00776             // Skip LOOKUP_TABLE line
00777             if(skipLookupTable)
00778             {
00779                 //FIXME: FP - why the first line is aways empty?
00780                 getline(is, line); 
00781                 getline(is, line); 
00782             }
00783 
00784             Matrix descriptor(dim, pointCount);
00785             for (int p = 0; p < pointCount; ++p)
00786             {
00787                 for(int d = 0; d < dim; d++)
00788                 {
00789                     is >> descriptor(d, p);
00790                 }
00791             }
00792             loadedPoints.addDescriptor(name, descriptor);
00793         }
00794              
00795     }
00796     
00797     return loadedPoints;
00798 }
00799 
00800 template
00801 PointMatcherIO<float>::DataPoints PointMatcherIO<float>::loadVTK(const std::string& fileName);
00802 template
00803 PointMatcherIO<double>::DataPoints PointMatcherIO<double>::loadVTK(const std::string& fileName);
00804 
00805 
00807 template<typename T>
00808 void PointMatcherIO<T>::saveVTK(const DataPoints& data, const std::string& fileName)
00809 {
00810     Parametrizable::Parameters param({{"baseFileName", ""}});
00811     typedef typename InspectorsImpl<T>::VTKFileInspector VTKInspector;
00812     VTKInspector vtkInspector(param);
00813     vtkInspector.dumpDataPoints(data, fileName);
00814 }
00815 
00816 
00817 template
00818 void PointMatcherIO<float>::saveVTK(const PointMatcherIO<float>::DataPoints& data, const std::string& fileName);
00819 template
00820 void PointMatcherIO<double>::saveVTK(const PointMatcher<double>::DataPoints& data, const std::string& fileName);


libpointmatcher
Author(s): Stéphane Magnenat, François Pomerleau
autogenerated on Thu Jan 2 2014 11:16:06