00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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 unsigned PointMatcher<T>::DataPoints::getNbPoints() const
00130 {
00131 return features.cols();
00132 }
00133
00135 template<typename T>
00136 unsigned PointMatcher<T>::DataPoints::getEuclideanDim() const
00137 {
00138 return (features.rows() - 1);
00139 }
00140
00142 template<typename T>
00143 unsigned PointMatcher<T>::DataPoints::getHomogeneousDim() const
00144 {
00145 return features.rows();
00146 }
00147
00149 template<typename T>
00150 unsigned PointMatcher<T>::DataPoints::getNbGroupedDescriptors() const
00151 {
00152 return descriptorLabels.size();
00153 }
00154
00156 template<typename T>
00157 unsigned PointMatcher<T>::DataPoints::getDescriptorDim() const
00158 {
00159 return descriptors.rows();
00160 }
00161
00162
00164 template<typename T>
00165 bool PointMatcher<T>::DataPoints::operator ==(const DataPoints& that) const
00166 {
00167
00168 bool isEqual = false;
00169 if((features.rows() == that.features.rows()) &&
00170 (features.cols() == that.features.cols()) &&
00171 (descriptors.rows() == that.descriptors.rows()) &&
00172 (descriptors.cols() == that.descriptors.cols()))
00173 {
00174 isEqual = (features == that.features) &&
00175 (featureLabels == that.featureLabels) &&
00176 (descriptors == that.descriptors) &&
00177 (featureLabels == that.featureLabels);
00178 }
00179
00180
00181
00182 return isEqual;
00183
00184 }
00185
00187 template<typename T>
00188 void PointMatcher<T>::DataPoints::concatenate(const DataPoints& dp)
00189 {
00190 const int nbPoints1 = this->features.cols();
00191 const int nbPoints2 = dp.features.cols();
00192 const int nbPointsTotal = nbPoints1 + nbPoints2;
00193
00194 const int dimFeat = this->features.rows();
00195 if(dimFeat != dp.features.rows())
00196 {
00197 stringstream errorMsg;
00198 errorMsg << "Cannot concatenate DataPoints because the dimension of the features are not the same. Actual dimension: " << dimFeat << " New dimension: " << dp.features.rows();
00199 throw InvalidField(errorMsg.str());
00200 }
00201
00202
00203 this->features.conservativeResize(Eigen::NoChange, nbPointsTotal);
00204 this->features.rightCols(nbPoints2) = dp.features;
00205
00206
00207 if (this->descriptorLabels == dp.descriptorLabels)
00208 {
00209 if (this->descriptorLabels.size() > 0)
00210 {
00211
00212 this->descriptors.conservativeResize(Eigen::NoChange, nbPointsTotal);
00213 this->descriptors.rightCols(nbPoints2) = dp.descriptors;
00214 }
00215 }
00216 else
00217 {
00218
00219
00220
00221 Labels newDescLabels;
00222 for(BOOST_AUTO(it, this->descriptorLabels.begin()); it != this->descriptorLabels.end(); ++it)
00223 {
00224 for(BOOST_AUTO(jt, dp.descriptorLabels.begin()); jt != dp.descriptorLabels.end(); ++jt)
00225 {
00226 if (it->text == jt->text)
00227 {
00228 if (it->span != jt->span)
00229 throw InvalidField(
00230 (boost::format("The field %1% has dimension %2% in this, different than dimension %3% in that") % it->text % it->span % jt->span).str()
00231 );
00232 newDescLabels.push_back(*it);
00233 break;
00234 }
00235 }
00236 }
00237
00238
00239 if (newDescLabels.size() > 0)
00240 {
00241 Matrix newDescriptors;
00242 Labels filledLabels;
00243 this->allocateFields(newDescLabels, filledLabels, newDescriptors);
00244 assert(newDescLabels == filledLabels);
00245
00246
00247 unsigned row(0);
00248 for(BOOST_AUTO(it, newDescLabels.begin()); it != newDescLabels.end(); ++it)
00249 {
00250 View view(newDescriptors.block(row, 0, it->span, newDescriptors.cols()));
00251 view.leftCols(nbPoints1) = this->getDescriptorViewByName(it->text);
00252 view.rightCols(nbPoints2) = dp.getDescriptorViewByName(it->text);
00253 row += it->span;
00254 }
00255
00256
00257 this->descriptors.swap(newDescriptors);
00258 this->descriptorLabels = newDescLabels;
00259 }
00260 else
00261 {
00262 this->descriptors = Matrix();
00263 this->descriptorLabels = Labels();
00264 }
00265 }
00266 assertDescriptorConsistency();
00267 }
00268
00270 template<typename T>
00271 void PointMatcher<T>::DataPoints::conservativeResize(Index pointCount)
00272 {
00273 features.conservativeResize(Eigen::NoChange, pointCount);
00274 if (descriptors.cols() > 0)
00275 descriptors.conservativeResize(Eigen::NoChange, pointCount);
00276 }
00277
00279 template<typename T>
00280 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::createSimilarEmpty() const
00281 {
00282 const int nbPoints(features.cols());
00283 DataPoints output(
00284 Matrix(features.rows(), nbPoints),
00285 featureLabels
00286 );
00287 if (descriptors.cols() > 0)
00288 {
00289 assert(descriptors.cols() == nbPoints);
00290 output.descriptors = Matrix(descriptors.rows(), nbPoints);
00291 output.descriptorLabels = descriptorLabels;
00292 }
00293 else
00294 {
00295 assert(descriptors.rows() == 0);
00296 }
00297 return output;
00298 }
00299
00301 template<typename T>
00302 typename PointMatcher<T>::DataPoints PointMatcher<T>::DataPoints::createSimilarEmpty(Index pointCount) const
00303 {
00304 DataPoints output(
00305 Matrix(features.rows(), pointCount),
00306 featureLabels
00307 );
00308 if (descriptors.cols() > 0)
00309 {
00310 output.descriptors = Matrix(descriptors.rows(), pointCount);
00311 output.descriptorLabels = descriptorLabels;
00312 }
00313 else
00314 {
00315 assert(descriptors.rows() == 0);
00316 }
00317 return output;
00318 }
00319
00321 template<typename T>
00322 void PointMatcher<T>::DataPoints::setColFrom(Index thisCol, const DataPoints& that, Index thatCol)
00323 {
00324 features.col(thisCol) = that.features.col(thatCol);
00325 if (descriptors.cols() > 0)
00326 descriptors.col(thisCol) = that.descriptors.col(thatCol);
00327 }
00328
00329
00331 template<typename T>
00332 void PointMatcher<T>::DataPoints::allocateFeature(const std::string& name, const unsigned dim)
00333 {
00334 allocateField(name, dim, featureLabels, features);
00335 }
00336
00338 template<typename T>
00339 void PointMatcher<T>::DataPoints::allocateFeatures(const Labels& newLabels)
00340 {
00341 allocateFields(newLabels, featureLabels, features);
00342 }
00343
00345 template<typename T>
00346 void PointMatcher<T>::DataPoints::addFeature(const std::string& name, const Matrix& newFeature)
00347 {
00348 removeFeature("pad");
00349 addField(name, newFeature, featureLabels, features);
00350 addField("pad", Matrix::Ones(1, features.cols()), featureLabels, features);
00351 }
00352
00354 template<typename T>
00355 void PointMatcher<T>::DataPoints::removeFeature(const std::string& name)
00356 {
00357 removeField(name, featureLabels, features);
00358 }
00359
00361 template<typename T>
00362 typename PointMatcher<T>::Matrix PointMatcher<T>::DataPoints::getFeatureCopyByName(const std::string& name) const
00363 {
00364 return Matrix(getFeatureViewByName(name));
00365 }
00366
00368 template<typename T>
00369 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getFeatureViewByName(const std::string& name) const
00370 {
00371 return getConstViewByName(name, featureLabels, features);
00372 }
00373
00375 template<typename T>
00376 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getFeatureViewByName(const std::string& name)
00377 {
00378 return getViewByName(name, featureLabels, features);
00379 }
00380
00382 template<typename T>
00383 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getFeatureRowViewByName(const std::string& name, const unsigned row) const
00384 {
00385 return getConstViewByName(name, featureLabels, features, int(row));
00386 }
00387
00389 template<typename T>
00390 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getFeatureRowViewByName(const std::string& name, const unsigned row)
00391 {
00392 return getViewByName(name, featureLabels, features, int(row));
00393 }
00394
00396 template<typename T>
00397 bool PointMatcher<T>::DataPoints::featureExists(const std::string& name) const
00398 {
00399 return fieldExists(name, 0, featureLabels);
00400 }
00401
00403 template<typename T>
00404 bool PointMatcher<T>::DataPoints::featureExists(const std::string& name, const unsigned dim) const
00405 {
00406 return fieldExists(name, dim, featureLabels);
00407 }
00408
00410 template<typename T>
00411 unsigned PointMatcher<T>::DataPoints::getFeatureDimension(const std::string& name) const
00412 {
00413 return getFieldDimension(name, featureLabels);
00414 }
00415
00417 template<typename T>
00418 unsigned PointMatcher<T>::DataPoints::getFeatureStartingRow(const std::string& name) const
00419 {
00420 return getFieldStartingRow(name, featureLabels);
00421 }
00422
00424 template<typename T>
00425 void PointMatcher<T>::DataPoints::allocateDescriptor(const std::string& name, const unsigned dim)
00426 {
00427 allocateField(name, dim, descriptorLabels, descriptors);
00428 }
00429
00431 template<typename T>
00432 void PointMatcher<T>::DataPoints::allocateDescriptors(const Labels& newLabels)
00433 {
00434 allocateFields(newLabels, descriptorLabels, descriptors);
00435 }
00436
00438 template<typename T>
00439 void PointMatcher<T>::DataPoints::addDescriptor(const std::string& name, const Matrix& newDescriptor)
00440 {
00441 addField(name, newDescriptor, descriptorLabels, descriptors);
00442 }
00443
00445 template<typename T>
00446 void PointMatcher<T>::DataPoints::removeDescriptor(const std::string& name)
00447 {
00448 removeField(name, descriptorLabels, descriptors);
00449 }
00450
00451
00453 template<typename T>
00454 typename PointMatcher<T>::Matrix PointMatcher<T>::DataPoints::getDescriptorCopyByName(const std::string& name) const
00455 {
00456 return Matrix(getDescriptorViewByName(name));
00457 }
00458
00460 template<typename T>
00461 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getDescriptorViewByName(const std::string& name) const
00462 {
00463 return getConstViewByName(name, descriptorLabels, descriptors);
00464 }
00465
00467 template<typename T>
00468 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getDescriptorViewByName(const std::string& name)
00469 {
00470 return getViewByName(name, descriptorLabels, descriptors);
00471 }
00472
00474 template<typename T>
00475 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getDescriptorRowViewByName(const std::string& name, const unsigned row) const
00476 {
00477 return getConstViewByName(name, descriptorLabels, descriptors, int(row));
00478 }
00479
00481 template<typename T>
00482 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getDescriptorRowViewByName(const std::string& name, const unsigned row)
00483 {
00484 return getViewByName(name, descriptorLabels, descriptors, int(row));
00485 }
00486
00488 template<typename T>
00489 bool PointMatcher<T>::DataPoints::descriptorExists(const std::string& name) const
00490 {
00491 return fieldExists(name, 0, descriptorLabels);
00492 }
00493
00495 template<typename T>
00496 bool PointMatcher<T>::DataPoints::descriptorExists(const std::string& name, const unsigned dim) const
00497 {
00498 return fieldExists(name, dim, descriptorLabels);
00499 }
00500
00502 template<typename T>
00503 unsigned PointMatcher<T>::DataPoints::getDescriptorDimension(const std::string& name) const
00504 {
00505 return getFieldDimension(name, descriptorLabels);
00506 }
00507
00509 template<typename T>
00510 unsigned PointMatcher<T>::DataPoints::getDescriptorStartingRow(const std::string& name) const
00511 {
00512 return getFieldStartingRow(name, descriptorLabels);
00513 }
00514
00516 template<typename T>
00517 void PointMatcher<T>::DataPoints::assertDescriptorConsistency() const
00518 {
00519 if (descriptors.rows() == 0)
00520 {
00521 if (descriptors.cols() != 0)
00522 throw std::runtime_error(
00523 (boost::format("Point cloud has degenerate descriptor dimensions of rows=0, cols=%1%") % descriptors.cols()).str()
00524 );
00525 if (descriptorLabels.size() > 0)
00526 throw std::runtime_error(
00527 (boost::format("Point cloud has no descriptor data but %1% descriptor labels") % descriptorLabels.size()).str()
00528 );
00529 }
00530 else
00531 {
00532 if (descriptors.cols() != features.cols())
00533 throw std::runtime_error(
00534 (boost::format("Point cloud has %1% points in features but %2% points in descriptors") % features.cols() % descriptors.cols()).str()
00535 );
00536 int descDim(0);
00537 for (BOOST_AUTO(it, descriptorLabels.begin()); it != descriptorLabels.end(); ++it)
00538 descDim += it->span;
00539 if (descriptors.rows() != descDim)
00540 throw std::runtime_error(
00541 (boost::format("Descriptor labels return %1% total dimensions but there are %2% in the descriptors matrix") % descDim % descriptors.rows()).str()
00542 );
00543 }
00544 }
00545
00547 template<typename T>
00548 void PointMatcher<T>::DataPoints::allocateField(const std::string& name, const unsigned dim, Labels& labels, Matrix& data) const
00549 {
00550 if (fieldExists(name, 0, labels))
00551 {
00552 const unsigned descDim(getFieldDimension(name, labels));
00553 if (descDim != dim)
00554 {
00555 throw InvalidField(
00556 (boost::format("The existing field %1% has dimension %2%, different than requested dimension %3%") % name % descDim % dim).str()
00557 );
00558 }
00559 }
00560 else
00561 {
00562 const int oldDim(data.rows());
00563 const int totalDim(oldDim + dim);
00564 const int pointCount(features.cols());
00565 data.conservativeResize(totalDim, pointCount);
00566 labels.push_back(Label(name, dim));
00567 }
00568 }
00569
00571 template<typename T>
00572 void PointMatcher<T>::DataPoints::allocateFields(const Labels& newLabels, Labels& labels, Matrix& data) const
00573 {
00574 typedef vector<bool> BoolVector;
00575 BoolVector present(newLabels.size(), false);
00576
00577
00578 size_t additionalDim(0);
00579 for (size_t i = 0; i < newLabels.size(); ++i)
00580 {
00581 const string& newName(newLabels[i].text);
00582 const size_t newSpan(newLabels[i].span);
00583 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00584 {
00585 if (it->text == newName)
00586 {
00587 if (it->span != newSpan)
00588 throw InvalidField(
00589 (boost::format("The existing field %1% has dimension %2%, different than requested dimension %3%") % newName % it->span % newSpan).str()
00590 );
00591 present[i] = true;
00592 break;
00593 }
00594 }
00595 if (!present[i])
00596 additionalDim += newSpan;
00597 }
00598
00599
00600 const int oldDim(data.rows());
00601 const int totalDim(oldDim + additionalDim);
00602 const int pointCount(features.cols());
00603 data.conservativeResize(totalDim, pointCount);
00604 for (size_t i = 0; i < newLabels.size(); ++i)
00605 {
00606 if (!present[i])
00607 labels.push_back(newLabels[i]);
00608 }
00609 }
00610
00612 template<typename T>
00613 void PointMatcher<T>::DataPoints::addField(const std::string& name, const Matrix& newField, Labels& labels, Matrix& data) const
00614 {
00615 const int newFieldDim = newField.rows();
00616 const int newPointCount = newField.cols();
00617 const int pointCount = features.cols();
00618
00619 if (newField.rows() == 0)
00620 return;
00621
00622
00623 if (fieldExists(name, 0, labels))
00624 {
00625 const int fieldDim = getFieldDimension(name, labels);
00626
00627 if(fieldDim == newFieldDim)
00628 {
00629
00630 if(pointCount == newPointCount)
00631 {
00632 const int row = getFieldStartingRow(name, labels);
00633 data.block(row, 0, fieldDim, pointCount) = newField;
00634 }
00635 else
00636 {
00637 stringstream errorMsg;
00638 errorMsg << "The field " << name << " cannot be added because the number of points is not the same. Old point count: " << pointCount << "new: " << newPointCount;
00639 throw InvalidField(errorMsg.str());
00640 }
00641 }
00642 else
00643 {
00644 stringstream errorMsg;
00645 errorMsg << "The field " << name << " already exists but could not be added because the dimension is not the same. Old dim: " << fieldDim << " new: " << newFieldDim;
00646 throw InvalidField(errorMsg.str());
00647 }
00648 }
00649 else
00650 {
00651 if(pointCount == newPointCount || pointCount == 0)
00652 {
00653 const int oldFieldDim(data.rows());
00654 const int totalDim = oldFieldDim + newFieldDim;
00655 data.conservativeResize(totalDim, newPointCount);
00656 data.bottomRows(newFieldDim) = newField;
00657 labels.push_back(Label(name, newFieldDim));
00658 }
00659 else
00660 {
00661 stringstream errorMsg;
00662 errorMsg << "The field " << name << " cannot be added because the number of points is not the same. Old point count: " << pointCount << " new: " << newPointCount;
00663 throw InvalidField(errorMsg.str());
00664 }
00665 }
00666 }
00668 template<typename T>
00669 void PointMatcher<T>::DataPoints::removeField(const std::string& name, Labels& labels, Matrix& data) const
00670 {
00671
00672 const unsigned deleteId = getFieldStartingRow(name, labels);
00673 const unsigned span = getFieldDimension(name, labels);
00674 const unsigned keepAfterId = deleteId + span;
00675 const unsigned lastId = data.rows() - 1;
00676 const unsigned sizeKeep = data.rows() - keepAfterId;
00677 const unsigned nbPoints = data.cols();
00678
00679
00680
00681 if(keepAfterId <= lastId)
00682 {
00683 data.block(deleteId, 0, sizeKeep, nbPoints) = data.block(keepAfterId, 0, sizeKeep, nbPoints);
00684 }
00685
00686
00687 data.conservativeResize(data.rows()-span, nbPoints);
00688
00689
00690 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00691 {
00692 if (it->text == name)
00693 {
00694 labels.erase(it);
00695 break;
00696 }
00697 }
00698
00699 }
00700
00701
00704 template<typename T>
00705 const typename PointMatcher<T>::DataPoints::ConstView PointMatcher<T>::DataPoints::getConstViewByName(const std::string& name, const Labels& labels, const Matrix& data, const int viewRow) const
00706 {
00707 unsigned row(0);
00708 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00709 {
00710 if (it->text == name)
00711 {
00712 if (viewRow >= 0)
00713 {
00714 if (viewRow >= int(it->span))
00715 throw InvalidField(
00716 (boost::format("Requesting row %1% of field %2% that only has %3% rows") % viewRow % name % it->span).str()
00717 );
00718 return data.block(row + viewRow, 0, 1, data.cols());
00719 }
00720 else
00721 return data.block(row, 0, it->span, data.cols());
00722 }
00723 row += it->span;
00724 }
00725 throw InvalidField("Field " + name + " not found");
00726 }
00727
00730 template<typename T>
00731 typename PointMatcher<T>::DataPoints::View PointMatcher<T>::DataPoints::getViewByName(const std::string& name, const Labels& labels, Matrix& data, const int viewRow) const
00732 {
00733 unsigned row(0);
00734 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00735 {
00736 if (it->text == name)
00737 {
00738 if (viewRow >= 0)
00739 {
00740 if (viewRow >= int(it->span))
00741 throw InvalidField(
00742 (boost::format("Requesting row %1% of field %2% that only has %3% rows") % viewRow % name % it->span).str()
00743 );
00744 return data.block(row + viewRow, 0, 1, data.cols());
00745 }
00746 else
00747 return data.block(row, 0, it->span, data.cols());
00748 }
00749 row += it->span;
00750 }
00751 throw InvalidField("Field " + name + " not found");
00752 }
00753
00755 template<typename T>
00756 bool PointMatcher<T>::DataPoints::fieldExists(const std::string& name, const unsigned dim, const Labels& labels) const
00757 {
00758 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00759 {
00760 if (it->text == name)
00761 {
00762 if (dim == 0 || it->span == dim)
00763 return true;
00764 else
00765 return false;
00766 }
00767 }
00768 return false;
00769 }
00770
00771
00773 template<typename T>
00774 unsigned PointMatcher<T>::DataPoints::getFieldDimension(const std::string& name, const Labels& labels) const
00775 {
00776 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00777 {
00778 if (it->text == name)
00779 return it->span;
00780 }
00781 return 0;
00782 }
00783
00784
00786 template<typename T>
00787 unsigned PointMatcher<T>::DataPoints::getFieldStartingRow(const std::string& name, const Labels& labels) const
00788 {
00789 unsigned row(0);
00790 for(BOOST_AUTO(it, labels.begin()); it != labels.end(); ++it)
00791 {
00792 if (it->text == name)
00793 return row;
00794 row += it->span;
00795 }
00796 return 0;
00797 }
00798
00799 template struct PointMatcher<float>::DataPoints;
00800 template struct PointMatcher<double>::DataPoints;
00801
00802
00804 template<typename T>
00805 void PointMatcher<T>::swapDataPoints(DataPoints& a, DataPoints& b)
00806 {
00807 a.features.swap(b.features);
00808 swap(a.featureLabels, b.featureLabels);
00809 a.descriptors.swap(b.descriptors);
00810 swap(a.descriptorLabels, b.descriptorLabels);
00811 }
00812
00813 template
00814 void PointMatcher<float>::swapDataPoints(DataPoints& a, DataPoints& b);
00815 template
00816 void PointMatcher<double>::swapDataPoints(DataPoints& a, DataPoints& b);