DataPoints.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 "PointMatcher.h"
00037 #include "PointMatcherPrivate.h"
00038 #include <iostream>
00039 
00040 using namespace std;
00041 
00043 template<typename T>
00044 PointMatcher<T>::DataPoints::Label::Label(const std::string& text, const size_t span):
00045         text(text),
00046         span(span)
00047 {}
00048 
00050 template<typename T>
00051 PointMatcher<T>::DataPoints::InvalidField::InvalidField(const std::string& reason):
00052         runtime_error(reason)
00053 {}
00054 
00056 template<typename T>
00057 bool PointMatcher<T>::DataPoints::Label::operator ==(const Label& that) const
00058 {
00059         return (this->text == that.text) && (this->span == that.span);
00060 }
00061 
00063 template<typename T>
00064 PointMatcher<T>::DataPoints::Labels::Labels()
00065 {}
00066 
00068 template<typename T>
00069 PointMatcher<T>::DataPoints::Labels::Labels(const Label& label):
00070         std::vector<Label>(1, label)
00071 {}
00072 
00074 template<typename T>
00075 bool PointMatcher<T>::DataPoints::Labels::contains(const std::string& text) const
00076 {
00077         for (const_iterator it(this->begin()); it != this->end(); ++it)
00078         {
00079                 if (it->text == text)
00080                         return true;
00081         }
00082         return false;
00083 }
00084 
00086 template<typename T>
00087 size_t PointMatcher<T>::DataPoints::Labels::totalDim() const
00088 {
00089         size_t dim(0);
00090         for (const_iterator it(this->begin()); it != this->end(); ++it)
00091                 dim += it->span;
00092         return dim;
00093 }
00094 
00096 template<typename T>
00097 PointMatcher<T>::DataPoints::DataPoints()
00098 {}
00099 
00101 template<typename T>
00102 PointMatcher<T>::DataPoints::DataPoints(const Labels& featureLabels, const Labels& descriptorLabels, const size_t pointCount):
00103         featureLabels(featureLabels),
00104         descriptorLabels(descriptorLabels)
00105 {
00106         features.resize(featureLabels.totalDim(), pointCount);
00107         if(descriptorLabels.totalDim())
00108                 descriptors.resize(descriptorLabels.totalDim(), pointCount);
00109 }
00110 
00112 template<typename T>
00113 PointMatcher<T>::DataPoints::DataPoints(const Matrix& features, const Labels& featureLabels):
00114         features(features),
00115         featureLabels(featureLabels)
00116 {}
00117 
00119 template<typename T>
00120 PointMatcher<T>::DataPoints::DataPoints(const Matrix& features, const Labels& featureLabels, const Matrix& descriptors, const Labels& descriptorLabels):
00121         features(features),
00122         featureLabels(featureLabels),
00123         descriptors(descriptors),
00124         descriptorLabels(descriptorLabels)
00125 {}
00126 
00128 template<typename T>
00129 bool PointMatcher<T>::DataPoints::operator ==(const DataPoints& that) const
00130 {
00131         return
00132                 (features == that.features) &&
00133                 (featureLabels == that.featureLabels) &&
00134                 (descriptors == that.descriptors) &&
00135                 (featureLabels == that.featureLabels);
00136 }
00137 
00139 template<typename T>
00140 void PointMatcher<T>::DataPoints::concatenate(const DataPoints& dp)
00141 {
00142         const int nbPoints1 = this->features.cols();
00143         const int nbPoints2 = dp.features.cols();
00144         const int nbPointsTotal = nbPoints1 + nbPoints2;
00145 
00146         const int dimFeat = this->features.rows();
00147         if(dimFeat != dp.features.rows())
00148         {
00149                 stringstream errorMsg;
00150                 errorMsg << "Cannot concatenate DataPoints because the dimension of the features are not the same. Actual dimension: " << dimFeat << " New dimension: " << dp.features.rows(); 
00151                 throw InvalidField(errorMsg.str());
00152         }
00153         
00154         // concatenate features
00155         this->features.conservativeResize(Eigen::NoChange, nbPointsTotal);
00156         this->features.rightCols(nbPoints2) = dp.features;
00157         
00158         // concatenate descriptors
00159         if (this->descriptorLabels == dp.descriptorLabels)
00160         {
00161                 if (this->descriptorLabels.size() > 0)
00162                 {
00163                         // same descriptors, fast merge
00164                         this->descriptors.conservativeResize(Eigen::NoChange, nbPointsTotal);
00165                         this->descriptors.rightCols(nbPoints2) = dp.descriptors;
00166                 }
00167         }
00168         else
00169         {
00170                 // different descriptors, slow merge
00171                 
00172                 // collect labels to be kept
00173                 Labels newDescLabels;
00174                 for(BOOST_AUTO(it, this->descriptorLabels.begin()); it != this->descriptorLabels.end(); ++it)
00175                 {
00176                         for(BOOST_AUTO(jt, dp.descriptorLabels.begin()); jt != dp.descriptorLabels.end(); ++jt)
00177                         {
00178                                 if (it->text == jt->text)
00179                                 {
00180                                         if (it->span != jt->span)
00181                                                 throw InvalidField(
00182                                                 (boost::format("The field %1% has dimension %2% in this, different than dimension %3% in that") % it->text % it->span % jt->span).str()
00183                                         );
00184                                         newDescLabels.push_back(*it);
00185                                         break;
00186                                 }
00187                         }
00188                 }
00189                 
00190                 // allocate new descriptors
00191                 if (newDescLabels.size() > 0)
00192                 {
00193                         Matrix newDescriptors;
00194                         Labels filledLabels;
00195                         this->allocateFields(newDescLabels, filledLabels, newDescriptors);
00196                         assert(newDescLabels == filledLabels);
00197                         
00198                         // fill
00199                         unsigned row(0);
00200                         for(BOOST_AUTO(it, newDescLabels.begin()); it != newDescLabels.end(); ++it)
00201                         {
00202                                 View view(newDescriptors.block(row, 0, it->span, newDescriptors.cols()));
00203                                 view.leftCols(nbPoints1) = this->getDescriptorViewByName(it->text);
00204                                 view.rightCols(nbPoints2) = dp.getDescriptorViewByName(it->text);
00205                                 row += it->span;
00206                         }
00207                         
00208                         // swap descriptors
00209                         this->descriptors.swap(newDescriptors);
00210                         this->descriptorLabels = newDescLabels;
00211                 }
00212                 else
00213                 {
00214                         this->descriptors = Matrix();
00215                         this->descriptorLabels = Labels();
00216                 }
00217         }
00218         assertDescriptorConsistency();
00219 }
00220 
00222 template<typename T>
00223 void PointMatcher<T>::DataPoints::conservativeResize(Index pointCount)
00224 {
00225         features.conservativeResize(Eigen::NoChange, pointCount);
00226         if (descriptors.cols() > 0)
00227                 descriptors.conservativeResize(Eigen::NoChange, pointCount);
00228 }
00229 
00231 template<typename T>
00232 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::createSimilarEmpty() const
00233 {
00234         const int nbPoints(features.cols());
00235         DataPoints output(
00236                 Matrix(features.rows(), nbPoints),
00237                 featureLabels
00238         );
00239         if (descriptors.cols() > 0)
00240         {
00241                 assert(descriptors.cols() == nbPoints);
00242                 output.descriptors = Matrix(descriptors.rows(), nbPoints);
00243                 output.descriptorLabels = descriptorLabels;
00244         }
00245         else
00246         {
00247                 assert(descriptors.rows() == 0);
00248         }
00249         return output;
00250 }
00251 
00253 template<typename T>
00254 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::createSimilarEmpty(Index pointCount) const
00255 {
00256         DataPoints output(
00257                 Matrix(features.rows(), pointCount),
00258                 featureLabels
00259         );
00260         if (descriptors.cols() > 0)
00261         {
00262                 output.descriptors = Matrix(descriptors.rows(), pointCount);
00263                 output.descriptorLabels = descriptorLabels;
00264         }
00265         else
00266         {
00267                 assert(descriptors.rows() == 0);
00268         }
00269         return output;
00270 }
00271 
00273 template<typename T>
00274 void PointMatcher<T>::DataPoints::setColFrom(Index thisCol, const DataPoints& that, Index thatCol)
00275 {
00276         features.col(thisCol) = that.features.col(thatCol);
00277         if (descriptors.cols() > 0)
00278                 descriptors.col(thisCol) = that.descriptors.col(thatCol);
00279 }
00280 
00281 
00283 template<typename T>
00284 void PointMatcher<T>::DataPoints::allocateFeature(const std::string& name, const unsigned dim)
00285 {
00286         allocateField(name, dim, featureLabels, features);
00287 }
00288 
00290 template<typename T>
00291 void PointMatcher<T>::DataPoints::allocateFeatures(const Labels& newLabels)
00292 {
00293         allocateFields(newLabels, featureLabels, features);
00294 }
00295 
00297 template<typename T>
00298 void PointMatcher<T>::DataPoints::addFeature(const std::string& name, const Matrix& newFeature)
00299 {
00300         addField(name, newFeature, featureLabels, features);
00301 }
00302 
00304 template<typename T>
00305 typename PointMatcher<T>::Matrix PointMatcher<T>::DataPoints::getFeatureCopyByName(const std::string& name) const
00306 {
00307         return Matrix(getFeatureViewByName(name));
00308 }
00309 
00311 template<typename T>
00312 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getFeatureViewByName(const std::string& name) const
00313 {
00314         return getConstViewByName(name, featureLabels, features);
00315 }
00316 
00318 template<typename T>
00319 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getFeatureViewByName(const std::string& name)
00320 {
00321         return getViewByName(name, featureLabels, features);
00322 }
00323 
00325 template<typename T>
00326 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getFeatureRowViewByName(const std::string& name, const unsigned row) const
00327 {
00328         return getConstViewByName(name, featureLabels, features, int(row));
00329 }
00330 
00332 template<typename T>
00333 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getFeatureRowViewByName(const std::string& name, const unsigned row)
00334 {
00335         return getViewByName(name, featureLabels, features, int(row));
00336 }
00337 
00339 template<typename T>
00340 bool PointMatcher<T>::DataPoints::featureExists(const std::string& name) const
00341 {
00342         return fieldExists(name, 0, featureLabels);
00343 }
00344 
00346 template<typename T>
00347 bool PointMatcher<T>::DataPoints::featureExists(const std::string& name, const unsigned dim) const
00348 {
00349         return fieldExists(name, dim, featureLabels);
00350 }
00351 
00353 template<typename T>
00354 unsigned PointMatcher<T>::DataPoints::getFeatureDimension(const std::string& name) const
00355 {
00356         return getFieldDimension(name, featureLabels);
00357 }
00358 
00360 template<typename T>
00361 unsigned PointMatcher<T>::DataPoints::getFeatureStartingRow(const std::string& name) const
00362 {
00363         return getFieldStartingRow(name, featureLabels);
00364 }
00365 
00367 template<typename T>
00368 void PointMatcher<T>::DataPoints::allocateDescriptor(const std::string& name, const unsigned dim)
00369 {
00370         allocateField(name, dim, descriptorLabels, descriptors);
00371 }
00372 
00374 template<typename T>
00375 void PointMatcher<T>::DataPoints::allocateDescriptors(const Labels& newLabels)
00376 {
00377         allocateFields(newLabels, descriptorLabels, descriptors);
00378 }
00379 
00381 template<typename T>
00382 void PointMatcher<T>::DataPoints::addDescriptor(const std::string& name, const Matrix& newDescriptor)
00383 {
00384         addField(name, newDescriptor, descriptorLabels, descriptors);
00385 }
00386 
00388 template<typename T>
00389 typename PointMatcher<T>::Matrix PointMatcher<T>::DataPoints::getDescriptorCopyByName(const std::string& name) const
00390 {
00391         return Matrix(getDescriptorViewByName(name));
00392 }
00393 
00395 template<typename T>
00396 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getDescriptorViewByName(const std::string& name) const
00397 {
00398         return getConstViewByName(name, descriptorLabels, descriptors);
00399 }
00400 
00402 template<typename T>
00403 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getDescriptorViewByName(const std::string& name)
00404 {
00405         return getViewByName(name, descriptorLabels, descriptors);
00406 }
00407 
00409 template<typename T>
00410 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getDescriptorRowViewByName(const std::string& name, const unsigned row) const
00411 {
00412         return getConstViewByName(name, descriptorLabels, descriptors, int(row));
00413 }
00414 
00416 template<typename T>
00417 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getDescriptorRowViewByName(const std::string& name, const unsigned row)
00418 {
00419         return getViewByName(name, descriptorLabels, descriptors, int(row));
00420 }
00421 
00423 template<typename T>
00424 bool PointMatcher<T>::DataPoints::descriptorExists(const std::string& name) const
00425 {
00426         return fieldExists(name, 0, descriptorLabels);
00427 }
00428 
00430 template<typename T>
00431 bool PointMatcher<T>::DataPoints::descriptorExists(const std::string& name, const unsigned dim) const
00432 {
00433         return fieldExists(name, dim, descriptorLabels);
00434 }
00435 
00437 template<typename T>
00438 unsigned PointMatcher<T>::DataPoints::getDescriptorDimension(const std::string& name) const
00439 {
00440         return getFieldDimension(name, descriptorLabels);
00441 }
00442 
00444 template<typename T>
00445 unsigned PointMatcher<T>::DataPoints::getDescriptorStartingRow(const std::string& name) const
00446 {
00447         return getFieldStartingRow(name, descriptorLabels);
00448 }
00449 
00451 template<typename T>
00452 void PointMatcher<T>::DataPoints::assertDescriptorConsistency() const
00453 {
00454         if (descriptors.rows() == 0)
00455         {
00456                 if (descriptors.cols() != 0)
00457                         throw std::runtime_error(
00458                                 (boost::format("Point cloud has degenerate descriptor dimensions of rows=0, cols=%1%") % descriptors.cols()).str()
00459                         );
00460                 if (descriptorLabels.size() > 0)
00461                         throw std::runtime_error(
00462                                 (boost::format("Point cloud has no descriptor data but %1% descriptor labels") % descriptorLabels.size()).str()
00463                         );
00464         }
00465         else
00466         {
00467                 if (descriptors.cols() != features.cols())
00468                         throw std::runtime_error(
00469                                 (boost::format("Point cloud has %1% points in features but %2% points in descriptors") % features.cols() % descriptors.cols()).str()
00470                         );
00471                 int descDim(0);
00472                 for (BOOST_AUTO(it, descriptorLabels.begin()); it != descriptorLabels.end(); ++it)
00473                         descDim += it->span;
00474                 if (descriptors.rows() != descDim)
00475                         throw std::runtime_error(
00476                                 (boost::format("Descriptor labels return %1% total dimensions but there are %2% in the descriptors matrix") % descDim % descriptors.rows()).str()
00477                         );
00478         }
00479 }
00480 
00482 template<typename T>
00483 void PointMatcher<T>::DataPoints::allocateField(const std::string& name, const unsigned dim, Labels& labels, Matrix& data) const
00484 {
00485         if (fieldExists(name, 0, labels))
00486         {
00487                 const unsigned descDim(getFieldDimension(name, labels));
00488                 if (descDim != dim)
00489                 {
00490                         throw InvalidField(
00491                                 (boost::format("The existing field %1% has dimension %2%, different than requested dimension %3%") % name % descDim % dim).str()
00492                         );
00493                 }
00494         }
00495         else
00496         {
00497                 const int oldDim(data.rows());
00498                 const int totalDim(oldDim + dim);
00499                 const int pointCount(features.cols());
00500                 data.conservativeResize(totalDim, pointCount);
00501                 labels.push_back(Label(name, dim));
00502         }
00503 }
00504 
00506 template<typename T>
00507 void PointMatcher<T>::DataPoints::allocateFields(const Labels& newLabels, Labels& labels, Matrix& data) const
00508 {
00509         typedef vector<bool> BoolVector;
00510         BoolVector present(newLabels.size(), false);
00511         
00512         // for fields that exist, take note and check dimension
00513         size_t additionalDim(0);
00514         for (size_t i = 0; i < newLabels.size(); ++i)
00515         {
00516                 const string& newName(newLabels[i].text);
00517                 const size_t newSpan(newLabels[i].span);
00518                 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00519                 {
00520                         if (it->text == newName)
00521                         {
00522                                 if (it->span != newSpan)
00523                                         throw InvalidField(
00524                                                 (boost::format("The existing field %1% has dimension %2%, different than requested dimension %3%") % newName % it->span % newSpan).str()
00525                                         );
00526                                 present[i] = true;
00527                                 break;
00528                         }
00529                 }
00530                 if (!present[i])
00531                         additionalDim += newSpan;
00532         }
00533         
00534         // for new fields allocate
00535         const int oldDim(data.rows());
00536         const int totalDim(oldDim + additionalDim);
00537         const int pointCount(features.cols());
00538         data.conservativeResize(totalDim, pointCount);
00539         for (size_t i = 0; i < newLabels.size(); ++i)
00540         {
00541                 if (!present[i])
00542                         labels.push_back(newLabels[i]);
00543         }
00544 }
00545 
00547 template<typename T>
00548 void PointMatcher<T>::DataPoints::addField(const std::string& name, const Matrix& newField, Labels& labels, Matrix& data) const
00549 {
00550         const int newFieldDim = newField.rows();
00551         const int newPointCount = newField.cols();
00552         const int pointCount = features.cols();
00553 
00554         if (newField.rows() == 0)
00555                 return;
00556 
00557         // Replace if the field exists
00558         if (fieldExists(name, 0, labels))
00559         {
00560                 const int fieldDim = getFieldDimension(name, labels);
00561                 
00562                 if(fieldDim == newFieldDim)
00563                 {
00564                         // Ensure that the number of points in the point cloud and in the field are the same
00565                         if(pointCount == newPointCount)
00566                         {
00567                                 const int row = getFieldStartingRow(name, labels);
00568                                 data.block(row, 0, fieldDim, pointCount) = newField;
00569                         }
00570                         else
00571                         {
00572                                 stringstream errorMsg;
00573                                 errorMsg << "The field " << name << " cannot be added because the number of points is not the same. Old point count: " << pointCount << "new: " << newPointCount;
00574                                 throw InvalidField(errorMsg.str());
00575                         }
00576                 }
00577                 else
00578                 {
00579                         stringstream errorMsg;
00580                         errorMsg << "The field " << name << " already exists but could not be added because the dimension is not the same. Old dim: " << fieldDim << " new: " << newFieldDim;
00581                         throw InvalidField(errorMsg.str());
00582                 }
00583         }
00584         else // Add at the end if it is a new field
00585         {
00586                 if(pointCount == newPointCount || pointCount == 0)
00587                 {
00588                         const int oldFieldDim(data.rows());
00589                         const int totalDim = oldFieldDim + newFieldDim;
00590                         data.conservativeResize(totalDim, newPointCount);
00591                         data.bottomRows(newFieldDim) = newField;
00592                         labels.push_back(Label(name, newFieldDim));
00593                 }
00594                 else
00595                 {
00596                         stringstream errorMsg;
00597                         errorMsg << "The field " << name << " cannot be added because the number of points is not the same. Old point count: " << pointCount << " new: " << newPointCount;
00598                         throw InvalidField(errorMsg.str());
00599                 }
00600         }
00601 }
00602 
00605 template<typename T>
00606 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getConstViewByName(const std::string& name, const Labels& labels, const Matrix& data, const int viewRow) const
00607 {
00608         unsigned row(0);
00609         for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00610         {
00611                 if (it->text == name)
00612                 {
00613                         if (viewRow >= 0)
00614                         {
00615                                 if (viewRow >= int(it->span))
00616                                         throw InvalidField(
00617                                                 (boost::format("Requesting row %1% of field %2% that only has %3% rows") % viewRow % name % it->span).str()
00618                                         );
00619                                 return data.block(row + viewRow, 0, 1, data.cols());
00620                         }
00621                         else
00622                                 return data.block(row, 0, it->span, data.cols());
00623                 }
00624                 row += it->span;
00625         }
00626         throw InvalidField("Field " + name + " not found");
00627 }
00628 
00631 template<typename T>
00632 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getViewByName(const std::string& name, const Labels& labels, Matrix& data, const int viewRow) const
00633 {
00634         unsigned row(0);
00635         for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00636         {
00637                 if (it->text == name)
00638                 {
00639                         if (viewRow >= 0)
00640                         {
00641                                 if (viewRow >= int(it->span))
00642                                         throw InvalidField(
00643                                                 (boost::format("Requesting row %1% of field %2% that only has %3% rows") % viewRow % name % it->span).str()
00644                                         );
00645                                 return data.block(row + viewRow, 0, 1, data.cols());
00646                         }
00647                         else
00648                                 return data.block(row, 0, it->span, data.cols());
00649                 }
00650                 row += it->span;
00651         }
00652         throw InvalidField("Field " + name + " not found");
00653 }
00654 
00656 template<typename T>
00657 bool PointMatcher<T>::DataPoints::fieldExists(const std::string& name, const unsigned dim, const Labels& labels) const
00658 {
00659         for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00660         {
00661                 if (it->text == name)
00662                 {
00663                         if (dim == 0 || it->span == dim)
00664                                 return true;
00665                         else
00666                                 return false;
00667                 }
00668         }
00669         return false;
00670 }
00671 
00672 
00674 template<typename T>
00675 unsigned PointMatcher<T>::DataPoints::getFieldDimension(const std::string& name, const Labels& labels) const
00676 {
00677         for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00678         {
00679                 if (it->text == name)
00680                         return it->span;
00681         }
00682         return 0;
00683 }
00684 
00685 
00687 template<typename T>
00688 unsigned PointMatcher<T>::DataPoints::getFieldStartingRow(const std::string& name, const Labels& labels) const
00689 {
00690         unsigned row(0);
00691         for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00692         {
00693                 if (it->text == name)
00694                         return row;
00695                 row += it->span;
00696         }
00697         return 0;
00698 }
00699 
00700 template struct PointMatcher<float>::DataPoints;
00701 template struct PointMatcher<double>::DataPoints;
00702 
00703 
00705 template<typename T>
00706 void PointMatcher<T>::swapDataPoints(DataPoints& a, DataPoints& b)
00707 {
00708         a.features.swap(b.features);
00709         swap(a.featureLabels, b.featureLabels);
00710         a.descriptors.swap(b.descriptors);
00711         swap(a.descriptorLabels, b.descriptorLabels);
00712 }
00713 
00714 template
00715 void PointMatcher<float>::swapDataPoints(DataPoints& a, DataPoints& b);
00716 template
00717 void PointMatcher<double>::swapDataPoints(DataPoints& a, DataPoints& b);


upstream_src
Author(s):
autogenerated on Wed Sep 24 2014 10:41:58